package kata func SumLetters(a string, b string) bool { return len(a) == len(b) && len(a) > 0 }
def verify_sum(a, b)a&&b&&a.sum==b.sum||falseend- package kata
- func SumLetters(a string, b string) bool {
- return len(a) == len(b) && len(a) > 0
- }
package kata_test import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "codewarrior/kata" ) func dotest(a string, b string, expected bool) { actual := SumLetters(a, b) Expect(actual).To(Equal(expected)) } var _ = Describe("Tests", func() { It("Example 1", func() { dotest("Sebastian", "Patricia", false) }) It("Example 2", func() { dotest("Anna", "Nana", true) }) It("Example 3", func() { dotest("John", "", false) }) It("Example 4", func() { dotest("", "", false) }) })
# From Ruby 3.0, RSpec is used under the hood.# See https://rspec.info/# Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well.describe "Example" doit "should return the sum" doexpect(verify_sum("Sebastian", "Patricia")).to eq(false)expect(verify_sum("Anna", "Nana")).to eq(true)expect(verify_sum("John", nil)).to eq(false)expect(verify_sum(nil, nil)).to eq(false)# The following is still supported, but new tests should now use them.# Test.assert_equals(add(1, 1), 2)endend- package kata_test
- import (
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
- . "codewarrior/kata"
- )
- func dotest(a string, b string, expected bool) {
- actual := SumLetters(a, b)
- Expect(actual).To(Equal(expected))
- }
- var _ = Describe("Tests", func() {
- It("Example 1", func() {
- dotest("Sebastian", "Patricia", false)
- })
- It("Example 2", func() {
- dotest("Anna", "Nana", true)
- })
- It("Example 3", func() {
- dotest("John", "", false)
- })
- It("Example 4", func() {
- dotest("", "", false)
- })
- })
describe "basic tests" do specify { expect(riddle("Two?")).to eq(3) } specify { expect(riddle("Ten?")).to eq(3) } specify { expect(riddle("Three?")).to eq(5) } end
test.assert_equals(riddle("Two?"), 3)test.assert_equals(riddle("Ten?"), 3)test.assert_equals(riddle("Three?"), 5)- describe "basic tests" do
- specify { expect(riddle("Two?")).to eq(3) }
- specify { expect(riddle("Ten?")).to eq(3) }
- specify { expect(riddle("Three?")).to eq(5) }
- end
A bit faster:
Rehearsal ------------------------------------
3.207147 0.008056 3.215203 ( 3.215506)
0.760552 0.000013 0.760565 ( 0.760609)
1.287006 0.000000 1.287006 ( 1.287230)
0.466994 0.000000 0.466994 ( 0.467006)
0.105617 0.000005 0.105622 ( 0.105649)
0.065559 0.000017 0.065576 ( 0.065609)
--------------------------- total: 5.900966sec
user system total real
1.493939 0.000000 1.493939 ( 1.494093) # Eileenandrea
0.785715 0.000000 0.785715 ( 0.785772) # Eileenandrea, a==b check
1.238191 0.000018 1.238209 ( 1.238325) # 深紅心
0.484410 0.000000 0.484410 ( 0.484429) # 深紅心, a==b check
0.076156 0.000000 0.076156 ( 0.076182) # pawptart
0.065472 0.000000 0.065472 ( 0.065472) # pawptart (refactored)
def one_away(a, b) return true if a == b case a.size - b.size when -1 then compare(a, b) when 0 then compare(b, a, 1) when 1 then compare(b, a) else false end end def compare(a, b, o = 0) (0..b.size).each do |i| return a[0, i] == b[0, i] && a[i + o, a.size] == b[i + 1, b.size] if a[i] != b[i] end true end
- def one_away(a, b)
- return true if a == b
- case a.size - b.size
when -1..1 then compare(a, b)- when -1 then compare(a, b)
- when 0 then compare(b, a, 1)
- when 1 then compare(b, a)
- else false
- end
- end
def compare(a, b)c = 0i = 0x, y = [a, b].sort_by(&:size) # Don't have to do this, but it makes the code easierx_off = x.size < y.size ? 0 : 1 # Used in case the string sizes are mismatched# Find the first difference# Use the index to split the strings into substrings# Compare the substringswhile i < y.sizeif x[i] != y[i]return x[0, i] == y[0, i] && x[i + x_off, x.size] == y[i + 1, y.size]endi += 1- def compare(a, b, o = 0)
- (0..b.size).each do |i|
- return a[0, i] == b[0, i] && a[i + o, a.size] == b[i + 1, b.size] if a[i] != b[i]
- end
- true
- end
# From Ruby 3.0, RSpec is used under the hood. # See https://rspec.info/ # Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well. require 'benchmark' describe "Basic test" do it "should true if edit is one or less" do expect(one_away('pale', 'ple')).to eq(true) expect(one_away('pales', 'pale')).to eq(true) expect(one_away('pale', 'bale')).to eq(true) expect(one_away('pale', 'pale')).to eq(true) expect(one_away('pale', 'bake')).to eq(false) expect(one_away('ale', 'pale')).to eq(true) expect(one_away('ale', 'pales')).to eq(false) end end describe "Benchmarks" do let(:pairs) do pairs = [] ALPHABET = ('a'..'z').to_a 10000.times do string = Array.new(500) { ALPHABET.sample }.join modified = string.dup while rand < 0.5 # 50% chance to modify single letter in a random location modified[rand(25)] = ALPHABET.sample end while rand < 0.1 # 10% chance to drop a letter at a random location modified.slice!(rand(modified.size)) end pairs << [string, modified] end pairs end it 'is fast!' do Benchmark.bmbm do |x| x.report do pairs.each { |pair| solution1(*pair) } end # Eileenandrea x.report do pairs.each { |pair| solution1mod(*pair) } end # Eileenandrea, much faster to check a == b up front x.report do pairs.each { |pair| solution2(*pair) } end # 深紅心 x.report do pairs.each { |pair| solution2mod(*pair) } end # 深紅心, much faster to check a == b up front x.report do pairs.each { |pair| solution3(*pair) } end # pawptart x.report do pairs.each { |pair| one_away(*pair) } end # pawptart end end end
- # From Ruby 3.0, RSpec is used under the hood.
- # See https://rspec.info/
- # Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well.
- require 'benchmark'
- describe "Basic test" do
- it "should true if edit is one or less" do
- expect(one_away('pale', 'ple')).to eq(true)
- expect(one_away('pales', 'pale')).to eq(true)
- expect(one_away('pale', 'bale')).to eq(true)
- expect(one_away('pale', 'pale')).to eq(true)
- expect(one_away('pale', 'bake')).to eq(false)
- expect(one_away('ale', 'pale')).to eq(true)
- expect(one_away('ale', 'pales')).to eq(false)
- end
- end
- describe "Benchmarks" do
- let(:pairs) do
- pairs = []
- ALPHABET = ('a'..'z').to_a
- 10000.times do
- string = Array.new(500) { ALPHABET.sample }.join
- modified = string.dup
- while rand < 0.5 # 50% chance to modify single letter in a random location
- modified[rand(25)] = ALPHABET.sample
- end
- while rand < 0.1 # 10% chance to drop a letter at a random location
- modified.slice!(rand(modified.size))
- end
- pairs << [string, modified]
- end
- pairs
- end
- it 'is fast!' do
- Benchmark.bmbm do |x|
- x.report do pairs.each { |pair| solution1(*pair) } end # Eileenandrea
- x.report do pairs.each { |pair| solution1mod(*pair) } end # Eileenandrea, much faster to check a == b up front
- x.report do pairs.each { |pair| solution2(*pair) } end # 深紅心
- x.report do pairs.each { |pair| solution2mod(*pair) } end # 深紅心, much faster to check a == b up front
- x.report do pairs.each { |pair| solution3(*pair) } end # pawptart
- x.report do pairs.each { |pair| one_away(*pair) } end # pawptart
- end
- end
- end
Added some benchmarks, improved some existing solutions
Substring comparison is orders of magnitude faster than iterating over each letter of the string in Ruby.
==
drops down into C to perform the comparison instead of relying on Ruby's relatively slow iteration.
Sample benchmark:
Rehearsal ------------------------------------
2.953821 0.028788 2.982609 ( 2.983072) # Eileenandrea
1.069810 0.000000 1.069810 ( 1.069971) # 深紅心
0.414153 0.000074 0.414227 ( 0.414269) # 深紅心 (modified)
0.087044 0.003973 0.091017 ( 0.091033) # pawptart
--------------------------- total: 4.557663sec
user system total real
1.521839 0.000000 1.521839 ( 1.522046)
1.044602 0.000028 1.044630 ( 1.044804)
0.407469 0.000000 0.407469 ( 0.407515)
0.065739 0.000000 0.065739 ( 0.065745)
def one_away(a, b) return true if a == b case a.size - b.size when -1..1 then compare(a, b) else false end end def compare(a, b) c = 0 i = 0 x, y = [a, b].sort_by(&:size) # Don't have to do this, but it makes the code easier x_off = x.size < y.size ? 0 : 1 # Used in case the string sizes are mismatched # Find the first difference # Use the index to split the strings into substrings # Compare the substrings while i < y.size if x[i] != y[i] return x[0, i] == y[0, i] && x[i + x_off, x.size] == y[i + 1, y.size] end i += 1 end end
def one_away(a,b)case a.length - b.lengthwhen 0i = 0while i < a.length && a[i] == b[i]i += 1endi += 1# probably slower than just using substring equality,while i < a.length && a[i] == b[i]i += 1end# but the allure of pretty complexities is too muchreturn i >= a.lengthwhen 1return helper(a,b)when -1return helper(b, a)elsereturn false- def one_away(a, b)
- return true if a == b
- case a.size - b.size
- when -1..1 then compare(a, b)
- else false
- end
- end
def helper(longer, shorter)i = 0while i < shorter.length && longer[i] == shorter[i]i += 1endwhile i < shorter.length && longer[i + 1] == shorter[i]i += 1- def compare(a, b)
- c = 0
- i = 0
- x, y = [a, b].sort_by(&:size) # Don't have to do this, but it makes the code easier
- x_off = x.size < y.size ? 0 : 1 # Used in case the string sizes are mismatched
- # Find the first difference
- # Use the index to split the strings into substrings
- # Compare the substrings
- while i < y.size
- if x[i] != y[i]
- return x[0, i] == y[0, i] && x[i + x_off, x.size] == y[i + 1, y.size]
- end
- i += 1
- end
return i >= shorter.length- end
# From Ruby 3.0, RSpec is used under the hood. # See https://rspec.info/ # Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well. require 'benchmark' describe "Basic test" do it "should true if edit is one or less" do expect(one_away('pale', 'ple')).to eq(true) expect(one_away('pales', 'pale')).to eq(true) expect(one_away('pale', 'bale')).to eq(true) expect(one_away('pale', 'pale')).to eq(true) expect(one_away('pale', 'bake')).to eq(false) expect(one_away('ale', 'pale')).to eq(true) expect(one_away('ale', 'pales')).to eq(false) end end describe "Benchmarks" do let(:pairs) do pairs = [] ALPHABET = ('a'..'z').to_a 10000.times do string = Array.new(500) { ALPHABET.sample }.join modified = string.dup while rand < 0.5 # 50% chance to modify single letter in a random location modified[rand(25)] = ALPHABET.sample end while rand < 0.1 # 10% chance to drop a letter at a random location modified.slice!(rand(modified.size)) end pairs << [string, modified] end pairs end it 'is fast!' do Benchmark.bmbm do |x| x.report do pairs.each { |pair| solution1(*pair) } end # Eileenandrea x.report do pairs.each { |pair| solution2(*pair) } end # 深紅心 x.report do pairs.each { |pair| solution2mod(*pair) } end # 深紅心, much faster to check a == b up front x.report do pairs.each { |pair| one_away(*pair) } end # pawptart end end end
- # From Ruby 3.0, RSpec is used under the hood.
- # See https://rspec.info/
- # Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well.
- require 'benchmark'
- describe "Basic test" do
- it "should true if edit is one or less" do
- expect(one_away('pale', 'ple')).to eq(true)
- expect(one_away('pales', 'pale')).to eq(true)
- expect(one_away('pale', 'bale')).to eq(true)
- expect(one_away('pale', 'pale')).to eq(true)
- expect(one_away('pale', 'bake')).to eq(false)
- expect(one_away('ale', 'pale')).to eq(true)
- expect(one_away('ale', 'pales')).to eq(false)
- end
- end
- describe "Benchmarks" do
- let(:pairs) do
- pairs = []
- ALPHABET = ('a'..'z').to_a
- 10000.times do
- string = Array.new(500) { ALPHABET.sample }.join
- modified = string.dup
- while rand < 0.5 # 50% chance to modify single letter in a random location
- modified[rand(25)] = ALPHABET.sample
- end
- while rand < 0.1 # 10% chance to drop a letter at a random location
- modified.slice!(rand(modified.size))
- end
- pairs << [string, modified]
- end
- pairs
- end
- it 'is fast!' do
- Benchmark.bmbm do |x|
- x.report do pairs.each { |pair| solution1(*pair) } end # Eileenandrea
- x.report do pairs.each { |pair| solution2(*pair) } end # 深紅心
- x.report do pairs.each { |pair| solution2mod(*pair) } end # 深紅心, much faster to check a == b up front
- x.report do pairs.each { |pair| one_away(*pair) } end # pawptart
- end
- end
- end
# It doesn't get any simpler, but we can definitely make it harder! def minimal_square(a, b): # This solution abuses the fact that we can multiply by True/False: # For instance, 1 * True = 1 and 1 * False = 0 # # A step further: # (a * (a > b ) + b * ( b >= a )) is equivalent to max(a, b) # # And: # (a * ( a < b ) + b * ( b <= a )) is equivalent to min(a, b) # # Putting it all together, the following is equivalent to: # max(min(a,b)*2,max(a,b))**2 side = (((a*(a<b)+b*(b<=a))*2)*(((a*(a<b)+b*(b<=a))*2)>(a*(a>b)+b*(b>=a))))+\ ((a*(a>b)+b*(b>=a))*(((a*(a<b)+b*(b<=a))*2)<=(a*(a>b)+b*(b>=a)))) return side**2
- # It doesn't get any simpler, but we can definitely make it harder!
- def minimal_square(a, b):
return max(min(a, b)*2, max(a, b))**2# This is my first kumite (∩_∩)# I think this is the best solution there's not much to improve on# The problem isn't too hard- # This solution abuses the fact that we can multiply by True/False:
- # For instance, 1 * True = 1 and 1 * False = 0
- #
- # A step further:
- # (a * (a > b ) + b * ( b >= a )) is equivalent to max(a, b)
- #
- # And:
- # (a * ( a < b ) + b * ( b <= a )) is equivalent to min(a, b)
- #
- # Putting it all together, the following is equivalent to:
- # max(min(a,b)*2,max(a,b))**2
- side = (((a*(a<b)+b*(b<=a))*2)*(((a*(a<b)+b*(b<=a))*2)>(a*(a>b)+b*(b>=a))))+\
- ((a*(a>b)+b*(b>=a))*(((a*(a<b)+b*(b<=a))*2)<=(a*(a>b)+b*(b>=a))))
- return side**2
import codewars_test as test import random @test.describe("Simple tests") def test_group(): @test.it("Test 1") def test_case1(): test.assert_equals(minimal_square(2, 3), 16) @test.it("Test 2") def test_case2(): test.assert_equals(minimal_square(3, 7), 49) @test.it("Test 3") def test_case3(): test.assert_equals(minimal_square(4, 10), 100) @test.describe("Edge cases") def test_group(): @test.it("Impossible rectangle") def impossible_case(): test.assert_equals(minimal_square(0, 0), 0) @test.it("Rectangle is a square") def square_case(): test.assert_equals(minimal_square(1, 1), 4) @test.describe("Random cases") def test_group(): for x in range(1, 101): a = random.randint(1, 100) b = random.randint(1, 100) test.assert_equals(minimal_square(a,b), solution(a,b))
- import codewars_test as test
# TODO Write testsimport solution # or from solution import example- import random
# test.assert_equals(actual, expected, [optional] message)- @test.describe("Simple tests")
- def test_group():
- @test.it("Test 1")
- def test_case1():
- test.assert_equals(minimal_square(2, 3), 16)
- @test.it("Test 2")
- def test_case2():
- test.assert_equals(minimal_square(3, 7), 49)
- @test.it("Test 3")
- def test_case3():
- test.assert_equals(minimal_square(4, 10), 100)
- @test.describe("Edge cases")
- def test_group():
- @test.it("Impossible rectangle")
- def impossible_case():
- test.assert_equals(minimal_square(0, 0), 0)
- @test.it("Rectangle is a square")
- def square_case():
- test.assert_equals(minimal_square(1, 1), 4)
- @test.describe("Random cases")
- def test_group():
- for x in range(1, 101):
- a = random.randint(1, 100)
- b = random.randint(1, 100)
- test.assert_equals(minimal_square(a,b), solution(a,b))
Add in non-arithmetic operators
def calculator(a, operator, b): return "Not a valid operation" if operator not in ['+', '-', '/', '*'] else eval(str(a) + operator + str(b))
- def calculator(a, operator, b):
return eval(str(a) + operator + str(b))- return "Not a valid operation" if operator not in ['+', '-', '/', '*'] else eval(str(a) + operator + str(b))
from random import randint, choice Test.describe("Basic Tests") Test.assert_equals(calculator(2, "-", 2), 0) Test.assert_equals(calculator(5, "+", 5), 10) Test.assert_equals(calculator(10, "-", 20), -10) Test.assert_equals(calculator(1, "=", 1), "Not a valid operation") Test.describe("Complex Test") Test.assert_equals(calculator(-10, "/", -5), 2.0) Test.assert_equals(calculator(100, "*", 0), 0) Test.describe("Random Test") for x in range(150): a = randint(-10000, 10000) b = randint(-10000, 10000) operator = choice(["+", "-", "*", "/", "="]) operations = {"+": lambda x, y: x + y, "-": lambda x, y: x - y, "*": lambda x, y: x * y, "/": lambda x, y: x / y, "=": lambda x, y: "Not a valid operation"} Test.assert_equals(calculator(a, operator, b), operations[operator](a, b))
- from random import randint, choice
- Test.describe("Basic Tests")
- Test.assert_equals(calculator(2, "-", 2), 0)
- Test.assert_equals(calculator(5, "+", 5), 10)
- Test.assert_equals(calculator(10, "-", 20), -10)
- Test.assert_equals(calculator(1, "=", 1), "Not a valid operation")
- Test.describe("Complex Test")
- Test.assert_equals(calculator(-10, "/", -5), 2.0)
- Test.assert_equals(calculator(100, "*", 0), 0)
- Test.describe("Random Test")
for x in range(100):- for x in range(150):
- a = randint(-10000, 10000)
- b = randint(-10000, 10000)
operator = choice(["+", "-", "*", "/"])- operator = choice(["+", "-", "*", "/", "="])
- operations = {"+": lambda x, y: x + y, "-": lambda x, y: x - y,
"*": lambda x, y: x * y, "/": lambda x, y: x / y}- "*": lambda x, y: x * y, "/": lambda x, y: x / y,
- "=": lambda x, y: "Not a valid operation"}
- Test.assert_equals(calculator(a, operator, b), operations[operator](a, b))