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  

      

+3


source to share


5 answers


array.any?(&:zero?) && array.uniq.length > 1



+2


source


arr.find { |elem| elem == 0 } && arr.find { |elem| elem != 0 }

      



runs faster than array.uniq, a lot

+1


source


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.

+1


source


Since you are already removing duplicates, all you have to check is if it contains zero and whatever. So after the call, uniq!

you only need:

return arr.size >= 2 && arr.include?(0)

0


source


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

      

0


source







All Articles