Define zero and non-zero scenarios - with one value (zero) that has special meaning
I am comparing values in multiple arrays. I want to mark values that have "zero" and "non-zero" at the same time in the same array. For some reason I am stuck. Here are the test cases / scenarios:
1. zero and zero => ignore
2. non-zero and non-zero => ignore
3. zero and non-zero => this is what we are after!
4. only zero => ignore
5. only non-zero => ignore
Here is my code:
def unique_with_zero?(*arr)
arr.uniq!
arr.sort!
if arr.size == 1
print 'ignore: ', arr, "\n"
end
if arr.size > 2
print 'candidate: ', arr, "\n"
end
end
#test cases
unique_with_zero?(30,20,40) #false
unique_with_zero?(111,0,500) #true - zero and other non-zero values
unique_with_zero?(1,1,3,1) #false
unique_with_zero?(0) #false - we need multiple values
unique_with_zero?(1) #false
unique_with_zero?(0,0) #false
source to share
Gentlemen, start your engines!
require 'fruity'
def benchem(arr, msg)
puts msg
compare do
exupery { arru=arr.uniq; arru.size >= 2 && arru.include?(0) }
krill { arr.any?(&:zero?) && arr.uniq.length > 1 }
wired9 { !!(arr.find { |elem| elem == 0 } && arr.find { |elem| elem != 0 }) }
cary { mn, mx = arr.minmax_by(&:abs); mn.zero? && !mx.zero? }
end
end
I changed excupery
(destructive) arr.uniq!
to (non-destructive) arru = arr.dup
to make it comparable to other methods that are not non-destructive.
def bench_for_n(n)
arr = Array.new(n) { 0 }
benchem arr, "\n\nn = #{n}, all 0"
arr[rand n] = 1
benchem arr, "\nn = #{n}, one 1, rest 0"
arr[rand n] = 1
arr[rand n] = 1
arr[rand n] = 1
benchem arr, "\nn = #{n}, four 1's, rest 0"
arr = Array.new(n) { 1 }
benchem arr "\nn = #{n}, all 1"
arr[rand n] = 0
benchem arr "\nn = #{n}, one 0, rest 1"
arr[rand n] = 0
arr[rand n] = 0
arr[rand n] = 0
benchem arr, "\nn = #{n}, four 0's, rest 1"
end
bench_for_n(1_000)
n = 1000, all 0
Running each test 128 times. Test will take about 2 seconds.
exupery is similar to krill
krill is faster than wired9 by 4x ± 1.0
wired9 is faster than cary by 2x ± 0.1
n = 1000, one 1, rest 0
Running each test 128 times. Test will take about 1 second.
krill is similar to exupery
exupery is faster than wired9 by 4x ± 1.0
wired9 is faster than cary by 2x ± 0.1
n = 1000, four 1's, rest 0
Running each test 1024 times. Test will take about 5 seconds.
wired9 is faster than krill by 5x ± 1.0
krill is similar to exupery
exupery is faster than cary by 9x ± 1.0
n = 1000, all 1
Running each test 128 times. Test will take about 1 second.
exupery is faster than krill by 3x ± 1.0
krill is faster than wired9 by 2x ± 0.1
wired9 is faster than cary by 2x ± 0.1
n = 1000, one 0, rest 1
Running each test 128 times. Test will take about 1 second.
exupery is faster than krill by 3x ± 1.0
krill is similar to wired9
wired9 is faster than cary by 2x ± 1.0
n = 1000, four 0's, rest 1
Running each test 128 times. Test will take about 1 second.
exupery is faster than krill by 3x ± 0.1
krill is similar to wired9
wired9 is faster than cary by 3x ± 1.0
I also ran a test for n = 10_000
and got very similar results.
source to share
Assuming all values are array Numeric
), we can do this with a single pass through the array using Enumerable # minmax_by :
def zero_and_nonzero?(*arr)
mn, mx = arr.minmax_by(&:abs)
mn.zero? && !mx.zero?
end
zero_and_nonzero?() #=> false
zero_and_nonzero?(30,20,40) #=> false
zero_and_nonzero?(111,0,500) #=> true
zero_and_nonzero?(1,1,3,1) #=> false
zero_and_nonzero?(0) #=> false
zero_and_nonzero?(1) #=> false
zero_and_nonzero?(0,-1) #=> true
zero_and_nonzero?(0.0,1.1) #=> true
source to share