I needed to perform this calculation very fast, so I created a benchmark with 7 methods as candidates:
require 'benchmark'
def candidate1(a, b)
return false if b.size > a.size
b.each_with_index do |el, i|
return false if a[i] != el
end
true
end
def candidate2(a, b)
return false if b.size > a.size
i = 0
b.each do |el|
return false if a[i] != el
i += 1
end
true
end
def candidate3(a, b)
return false if b.size > a.size
0.upto(b.size) do |i|
return false if a[i] != b[i]
end
true
end
def candidate4(a, b)
0.upto(b.size) do |i|
return false if a[i] != b[i]
end
true
end
def candidate5(a, b)
i = 0
b.each do |el|
return false if a[i] != el
i += 1
end
true
end
def candidate6(a, b)
return false if b.size > a.size
i = -1
b.each do |el|
return false if a[i+=1] != el
end
true
end
def candidate7(a, b)
a.take(b.size) == b
end
TEST_CASES = [
[[3,3,3,3], [3,3,3,3]],
[[3,3], [3,3,3,3]],
[[3,3,3,3], [3,3]],
[[1,2,3,4], [5,6,7,8]],
[[1,2,3,4], [5,6,7]],
[[], []],
[[1,2,3,4],[1,2,3]],
[[1,2,3,4,5,6,7,8,9,10,11,12,13],[1,2,3]],
[[1,2,3],[1,2,3,4,5,6,7,8,9,10,11,12,13]]
]
N = 1_000_000
Benchmark.bm do |x|
puts "Running all testcases #{N} times on each candidate"
i = 1.upto(7) do |i|
x.report do
method_name = "candidate#{i}"
puts method_name
N.times do
TEST_CASES.each_with_index do |c, j|
send(method_name, c[0], c[1])
end
end
end
end
end
Here's what I got:
candidate1
4.713704 0.010974 4.724678 ( 4.742682)
candidate2
3.867821 0.009236 3.877057 ( 3.888543)
candidate3
5.521557 0.014552 5.536109 ( 5.577994)
candidate4
6.403158 0.010979 6.414137 ( 6.428128)
candidate5
4.730323 0.010388 4.740711 ( 4.753335)
candidate6
3.891551 0.021362 3.912913 ( 3.964875)
candidate7
3.942376 0.008003 3.950379 ( 3.964634)
To summarise: candidates 2 and 6 were always outperforming others, sometimes one was winning, sometimes another:
def candidate2(a, b)
return false if b.size > a.size
i = 0
b.each do |el|
return false if a[i] != el
i += 1
end
true
end
def candidate6(a, b)
return false if b.size > a.size
i = -1
b.each do |el|
return false if a[i+=1] != el
end
true
end
[1, 2] == [2, 1]should be false.ary.first(beginning.length) == beginning, reads a little clearer. Or you could sayarr[0...beginning.length] == beginning(triple periods means "up to but not including")