Reputation: 323
I'm making a program in ruby to find all of the prime factors of a given number. I'm aware that ruby has a .Prime class, but I'd like to accomplish this without using it.
Everything is working well except for one catch: I can't find a way to run modulo on a range of numbers. I've tried to find an answer online, in the Ruby documentation, and on older posts here. So far I've found nothing that helped.
Here's the code:
def prime(n)
r = Range.new(2, n-1)
r.each { |x| puts x if n % x == 0 && x % (2..x-1) != 0}
end
print "Please enter a number: "
prime(gets.chomp.to_i)
EDIT: Sorry, I may have been vague. This bit of code:
x % (2..x-1) != 0
Kicks back this:
euler2.rb:3:in `%': Enumerator can't be coerced into Fixnum (TypeError)
from euler2.rb:3:in `block in divisible'
from euler2.rb:3:in `each'
from euler2.rb:3:in `divisible'
from euler2.rb:7:in `<main>'
I've googled that error, but with no luck. If I change the code to a non-range, it works.
Upvotes: 0
Views: 539
Reputation: 16506
Your logic is incorrect. You try something much simpler like:
def prime(n)
!(2..n-1).detect{|x| n%x == 0}
end
Here detect will return the first value of x
that matches the condition n%x == 0
. If none matches nil
is returned. Therefore in case of a prime number (2..n-1).detect{|x| n%x == 0}
will return nil
and !
will make it true
. For composite numbers their lowest divisor will be returned and !
will make it false
.
What is wrong with your code?
you are doing x % (2..x-1)
. Here (2..x-1)
is a Range. You cannot do modulo of a Fixnum with a Range. Hence you will get:
TypeError: Range can't be coerced into Fixnum
You can improve x % (2..x-1)
using something like (2..x-1).each{|n| x%n}
or any other Enumerator in place of each
. However I still think your logic is overly complicated or a simple problem like this.
Upvotes: 3
Reputation: 1789
How about any?
?
def prime(n)
range = Range.new(2, n-1)
composite = range.any? { |i| n%i == 0 }
!composite
end
Of course this is going to be slow for large numbers.
Upvotes: 0