A few notes
Variable name
Naming variables is hard but very important.
The code you're showing is, as others have mentionned, to test if a number is prime.
If you're using prime
as a variable name for this number, there shouldn't be any use is checking it is prime!
So
(2..prime/2).none?{|i| prime % i == 0}
should be
(2..number/2).none?{|i| number % i == 0}
To make it even more obvious, this code could be written in a method :
def is_prime?(number)
(2..number/2).none?{|i| number % i == 0}
end
The ?
is here to indicate that the method returns a boolean.
For none?
:
none?
can be called on any Enumerable (Arrays, Hash and Array-like objects).
- It must be used with a block. It executes this block with every element, one after the other.
- If any block returns a value other than
nil
or false
, none?
stops and returns false
- If no block returns a truthy value, it returns
true
.
none?
is equivalent to all?
with the opposite condition in block.
Example :
puts [1, 3, 5, 7].none?{ |n| n.even? }
#=> true
puts [1, 3, 5, 7].all?{ |n| n.odd? }
#=> true
puts [1, 2, 3, 4, 5, 6, 7].none? { |n| n > 6 }
#=> false
Optimization
If number % 2 == 0
is false, it means that number
is odd. There's no use in checking if number/2
divides number
, we know it is also false
.
It means that the range is too big! It could be (2..number/3)
But if number isn't divisible by 3, there's also no point in checking if number
is divisible by number/3
.
It goes on an on until the range is as small as possible :
(2..Math.sqrt(number))
This will make the execution much faster for big numbers.
Using the method
def is_prime?(number)
(2..Math.sqrt(number)).none? { |i| number % i == 0 }
end
p (2..100).select { |n| is_prime?(n) }
#=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
To check it is correct, we can use the Prime library :
require 'prime'
p (2..100).select { |n| is_prime?(n) } == Prime.take_while{|p| p<100 }
#=> true