Why doesn't my solution to Euler #7 (10001st prime) work? - ruby

This is my code. The code doesn't run at all which leads me to believe that the problem is an infinite loop or something of that sort.
# Question_7, Answer = 104743
# By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
# What is the 10 001st prime number?
def prime_at(x)
primes = [2, 3]
n = 4
test = true
while primes.length <= x
primes.each do |i|
if n % i != 0
test = false
end
end
if test == true
primes.push(n)
end
n += 1
end
puts primes[-1]
end
prime_at(10001)

Yes you have an infinite loop. The bug is that once the variable test is set to false it never changes to true, so you are not adding elements into the primes array. That means that the condition of your loop primes.length <= x is going to be always true. Hence the infinite loop.

Your test is wrong. n%i != 0 means the number is not divisble by i, meaning the prime test should not fail. There's a lot of 'extra' syntax in here that makes your method a bit hard to understand. For example, test == true is redundant (if test is true or false or anything else, you can just say if test). n%i != 0 returns a boolean value already, so that whole if statement around it is unneeded.
It may seem a bit odd to drop so many constructs found in other languages, but Ruby lets you express your ideas very clearly and understandably. Here's what I would suggest for this method (I didn't change your algorithm at all, this is simply a rewrite):
def prime_at(x)
primes = [2,3]
n = 4
until primes.length == x
primes << n if primes.all? {|p| n % p > 0 }
n += 1
end
primes.last
end

Related

Code Optimization - Generating Prime Numbers

I am trying to write a code for the following problem:
Input
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n (1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.
Sample Input:
2
1 10
3 5
Sample Output:
2
3
5
7
3
5
My code:
def prime?(number)
return false if number == 1
(2..number-1).each do |n|
return false if number % n == 0
end
true
end
t = gets.strip.to_i
for i in 1..t
mi, ni = gets.strip.split(' ')
mi = mi.to_i
ni = ni.to_i
i = mi
while i <= ni
puts i if prime?(i)
i += 1
end
puts "\n"
end
The code is running fine, only problem I am having is that it is taking a lot of time when run against big input ranges as compared to other programming languages.
Am I doing something wrong here? Can this code be further optimized for faster runtime?
I have tried using a for loop, normal loop, creating an array and then printing it.
Any suggestions.
Ruby is slower than some other languages, depending on what language you compare it to; certainly slower than C/C++. But your problem is not the language (although it influences the run-time behavior), but your way of finding primes. There are many better algorithms for finding primes, such as the Sieve of Eratosthenes or the Sieve of Atkin. You might also read the “Generating Primes” page on Wikipedia and follow the links there.
By the way, for the Sieve of Eratosthenes, there is even a ready-to-use piece of code on Stackoverflow. I'm sure a little bit of googling will turn up implementations for other algorithms, too.
Since your problem is finding primes within a certain range, this is the Sieve of Eratosthenes code found at the above link modified to suit your particular problem:
def better_sieve_upto(first, last)
sieve = [nil, nil] + (2..last).to_a
sieve.each do |i|
next unless i
break if i*i > last
(i*i).step(last, i) {|j| sieve[j] = nil }
end
sieve.reject {|i| !i || i < first}
end
Note the change from "sieve.compact" to a complexer "sieve.reject" with a corresponding condition.
Return true if the number is 2, false if the number is evenly divisible by 2.
Start iterating at 3, instead of 2. Use a step of two.
Iterate up to the square root of the number, instead of the number minus one.
def prime?(number)
return true if number == 2
return false if number <= 1 or number % 2 == 0
(3..Math.sqrt(number)).step(2) do |n|
return false if number % n == 0
end
true
end
This will be much faster, but still not very fast, as #Technation explains.
Here's how to do it using the Sieve of Eratosthenes built into Ruby. You'll need to precompute all the primes up to the maximum maximum, which will be very quick, and then select the primes that fall within each range.
require 'prime'
ranges = Array.new(gets.strip.to_i) do
min, max = gets.strip.split.map(&:to_i)
Range.new(min, max)
end
primes = Prime.each(ranges.map(&:max).max, Prime::EratosthenesGenerator.new)
ranges.each do |range|
primes.each do |prime|
next if prime < range.min
break if prime > range.max
puts prime
end
primes.rewind
puts "\n"
end
Here's how the various solutions perform with the range 50000 200000:
Your original prime? function: 1m49.639s
My modified prime? function: 0m0.687s
Prime::EratosthenesGenerator: 0m0.221s
The more ranges being processed, the faster the Prime::EratosthenesGenerator method should be.

Why is my Ruby code for Project Euler #10 so slow?

I am relatively new to Ruby but it seems simple enough as far as a language goes. I am working through the Euler Project with Ruby and I'm having a huge issue with speed on the following:
The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
Find the sum of all the primes below two million.
My code:
beginning_time = Time.now
(1..10000).each { |i| i }
def isPrime(num)
factors = 0
primecount = 1
while primecount <= num
if (num%primecount == 0)
factors += 1
end
if (factors > 2)
return false
end
primecount += 1
end
return true
end
def make_sieve(num)
sieve = Array.new(num)
summation = 0
for i in 1..num
if(isPrime(i) == true)
summation += i
puts i
for x in i..num
if x%i == 0
# Go through entire array and make all multiples of i False
sieve[x] = false
else
sieve[i] = true
end
end
else
# If i is NOT prime, move to the next number. in the For Loop
next
end
end
puts summation
end
make_sieve(2000000)
end_time = Time.now
puts "Time elapsed #{(end_time - beginning_time)*1000} milliseconds"
I think I have the right idea with the sieve but I really have no clue what's going on that makes this program run so slow. I run it with 20,000 and it takes about 15 seconds, which seems slow even still, although the output comes out MUCH faster than when I put 2,000,000.
Am I going about this the wrong way logically or syntactically or both?
Your isPrime() test is very slow on primes; but you don't even need it. The key to sieve is, initially all the numbers are marked as prime; then for each prime we mark off all its multiples. So when we get to a certain entry in the sieve, we already know whether it is a prime or not - whether it is marked true for being prime, or it is marked false for being composite (a multiple of some smaller prime).
There is no need to test it being prime, at all.
And to find the multiples, we just count: for 5, it's each 5th entry after it; for 7 - each 7th. No need to test them with % operator, just set to false right away. No need to set any of them to true, because all numbers were set to true at the start.
You seem to be writing JavaScript code in Ruby, and are missing the subtleties that makes Ruby so elegant. You should take a look at something like Ruby Best Practices, which is quite a light read but deals with using Ruby idioms instead of imposing the concepts of another language.
As has been said, the whole point of an Eratosthenes sieve is that you just remove all compound numbers from a list, leaving just the primes. There is no need to check each element for primeness.
This is a Rubyish solution. It runs in about 1.5 seconds. It is a little complicated by the representing number N by array element N-1, so (i+i+1 .. num).step(i+1) is equivalent to (n * 2 .. num).step(n)
def make_sieve(num)
sieve = Array.new(num, true)
sieve.each_with_index do |is_prime, i|
next if i == 0 or not is_prime
(i+i+1 .. num).step(i+1) { |i| sieve[i] = false }
end
puts sieve.each_index.select { |i| sieve[i] }.map { |i| i+1 }.inject(:+)
end
make_sieve(2_000_000)
output
142913828923

How do I generate the first n prime numbers?

I am learning Ruby and doing some math stuff. One of the things I want to do is generate prime numbers.
I want to generate the first ten prime numbers and the first ten only. I have no problem testing a number to see if it is a prime number or not, but was wondering what the best way is to do generate these numbers?
I am using the following method to determine if the number is prime:
class Integer < Numeric
def is_prime?
return false if self <= 1
2.upto(Math.sqrt(self).to_i) do |x|
return false if self%x == 0
end
true
end
end
In Ruby 1.9 there is a Prime class you can use to generate prime numbers, or to test if a number is prime:
require 'prime'
Prime.take(10) #=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Prime.take_while {|p| p < 10 } #=> [2, 3, 5, 7]
Prime.prime?(19) #=> true
Prime implements the each method and includes the Enumerable module, so you can do all sorts of fun stuff like filtering, mapping, and so on.
If you'd like to do it yourself, then something like this could work:
class Integer < Numeric
def is_prime?
return false if self <= 1
2.upto(Math.sqrt(self).to_i) do |x|
return false if self%x == 0
end
true
end
def next_prime
n = self+1
n = n + 1 until n.is_prime?
n
end
end
Now to get the first 10 primes:
e = Enumerator.new do |y|
n = 2
loop do
y << n
n = n.next_prime
end
end
primes = e.take 10
require 'prime'
Prime.first(10) # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Check out Sieve of Eratosthenes. This is not Ruby specific but it is an algorithm to generate prime numbers. The idea behind this algorithm is that you have a list/array of numbers say
2..1000
You grab the first number, 2. Go through the list and eliminate everything that is divisible by 2. You will be left with everything that is not divisible by 2 other than 2 itself (e.g. [2,3,5,7,9,11...999]
Go to the next number, 3. And again, eliminate everything that you can divide by 3. Keep going until you reach the last number and you will get an array of prime numbers. Hope that helps.
http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
People already mentioned the Prime class, which definitely would be the way to go. Someone also showed you how to use an Enumerator and I wanted to contribute a version using a Fiber (it uses your Integer#is_prime? method):
primes = Fiber.new do
Fiber.yield 2
value = 3
loop do
Fiber.yield value if value.is_prime?
value += 2
end
end
10.times { p primes.resume }
# First 10 Prime Numbers
number = 2
count = 1
while count < 10
j = 2
while j <= number
break if number%j == 0
j += 1
end
if j == number
puts number
count += 1
end
number += 1
end
Implemented the Sieve of Eratosthene (more or less)
def primes(size)
arr=(0..size).to_a
arr[0]=nil
arr[1]=nil
max=size
(size/2+1).times do |n|
if(arr[n]!=nil) then
cnt=2*n
while cnt <= max do
arr[cnt]=nil
cnt+=n
end
end
end
arr.compact!
end
Moreover here is a one-liner I like a lot
def primes_c a
p=[];(2..a).each{|n| p.any?{|l|n%l==0}?nil:p.push(n)};p
end
Of course those will find the primes in the first n numbers, not the first n primes, but I think an adaptation won't require much effort.
Here is a way to generate the prime numbers up to a "max" argument from scratch, without using Prime or Math. Let me know what you think.
def prime_test max
primes = []
(1..max).each {|num|
if
(2..num-1).all? {|denom| num%denom >0}
then
primes.push(num)
end
}
puts primes
end
prime_test #enter max
I think this may be an expensive solution for very large max numbers but seems to work well otherwise:
def multiples array
target = array.shift
array.map{|item| item if target % item == 0}.compact
end
def prime? number
reversed_range_array = *(2..number).reverse_each
multiples_of_number = multiples(reversed_range_array)
multiples_of_number.size == 0 ? true : false
end
def primes_in_range max_number
range_array = *(2..max_number)
range_array.map{|number| number if prime?(number)}.compact
end
class Numeric
def prime?
return self == 2 if self % 2 == 0
(3..Math.sqrt(self)).step(2) do |x|
return false if self % x == 0
end
true
end
end
With this, now 3.prime? returns true, and 6.prime? returns false.
Without going to the efforts to implement the sieve algorithm, time can still be saved quickly by only verifying divisibility until the square root, and skipping the odd numbers. Then, iterate through the numbers, checking for primeness.
Remember: human time > machine time.
I did this for a coding kata and used the Sieve of Eratosthenes.
puts "Up to which number should I look for prime numbers?"
number = $stdin.gets.chomp
n = number.to_i
array = (1..n).to_a
i = 0
while array[i]**2 < n
i = i + 1
array = array.select do |element|
element % array[i] != 0 || element / array[i] == 1
end
end
puts array.drop(1)
Ruby: Print N prime Numbers
http://mishra-vishal.blogspot.in/2013/07/include-math-def-printnprimenumbernoofp.html
include Math
def print_n_prime_number(no_of_primes=nil)
no_of_primes = 100 if no_of_primes.nil?
puts "1 \n2"
count = 1
number = 3
while count < no_of_primes
sq_rt_of_num = Math.sqrt(number)
number_divisible_by = 2
while number_divisible_by <= sq_rt_of_num
break if(number % number_divisible_by == 0)
number_divisible_by = number_divisible_by + 1
end
if number_divisible_by > sq_rt_of_num
puts number
count = count+1
end
number = number + 2
end
end
print_n_prime_number
Not related at all with the question itself, but FYI:
if someone doesn't want to keep generating prime numbers again and again (a.k.a. greedy resource saver)
or maybe you already know that you must to work with subsequent prime numbers in some way
other unknown and wonderful cases
Try with this snippet:
require 'prime'
for p in Prime::Generator23.new
# `p` brings subsequent prime numbers until the end of the days (or until your computer explodes)
# so here put your fabulous code
break if #.. I don't know, I suppose in some moment it should stop the loop
end
fp
If you need it, you also could use another more complex generators as Prime::TrialDivisionGenerator or Prime::EratosthenesGenerator. More info
Here's a super compact method that generates an array of primes with a single line of code.
def get_prime(up_to)
(2..up_to).select { |num| (2...num).all? { |div| (num % div).positive? } }
end
def get_prime(number)
(2..number).each do |no|
if (2..no-1).all? {|num| no % num > 0}
puts no
end
end
end
get_prime(100)

Ruby - determine if a number is a prime

I'm running through the problems on Project Euler to teach myself Ruby programming. I know there is a built-in function to do this, but I'm avoiding the built-in functions to help me learn.
So I have to write a method to determine if a number is a prime. The first method works, but the second doesn't. Can anyone explain why?
def is_prime n
for d in 2..(n - 1)
if (n % d) == 0
return false
end
end
true
end
def is_prime2 n
foundDivider = false
for d in 2..(n - 1)
foundDivider = ((n % d) == 0) or foundDivider
end
not foundDivider
end
It's because = is of higher precedence than or. See Ruby's operator precedence table below (highest to lowest precedence):
[ ] [ ]=
**
! ~ + -
* / %
+ -
>> <<
&
^ |
<= < > >=
<=> == === != =~ !~
&&
||
.. ...
? :
= %= { /= -= += |= &= >>= <<= *= &&= ||= **=
defined?
not
or and
if unless while until
begin/end
The problematic line is being parsed as...
(foundDivider = ((n % d) == 0)) or foundDivider
...which is certainly not what you mean. There are two possible solutions:
Force the precedence to be what you really mean...
foundDivider = (((n % d) == 0) or foundDivider)
...or use the || operator instead, which has higher precedence than =:
foundDivider = ((n % d) == 0) || foundDivider
Ruby comes with predefined classes such as Prime. All you have to do is to require that class into your project.
require 'prime'
Than, you can use some of the Prime methods such as first to get first x prime elements:
Prime.first(5) # Ret => [2, 3, 5, 6, 11]
Or you could do something like this:
Prime.each(100) do |prime|
p prime # Ret => [2, 3, 5, 7, 11, ..., 97]
end
I hope you find this useful.
def prime(n)
return false if n < 2
(2..n/2).none?{|i| n % i == 0}
end
A prime number is any number that has no positive divisors other than itself and 1.
def prime? n
(2..Math.sqrt(n)).none? {|f| n % f == 0}
end
The range of factors should start at 2 and end at the square root of n because every number is divisible by one and no number is divisible by two numbers greater than its square root.
Explanation: A non-prime number is the product of two numbers.
n = f1 * f2
n is always divisible by its square root so both f1 and f2 cannot be greater than the square root of n, otherwise f1 * f2 would be greater than n. Therefore, at least one factor is less than or at most equal to Math.sqrt(n). In the case of finding prime numbers its only necessary to find one factor so we should loop from 2 to the square root of n.
Find prime numbers from loop:
def get_prime_no_upto(number)
pre = [1]
start = 2
primes = (start..number).to_a
(start..number).each do |no|
(start..no).each do |num|
if ( no % num == 0) && num != no
primes.delete(no)
break
end
end
end
pre + primes
end
and use it as below:
puts get_prime_no_upto(100)
Cheers!
Here is code that will prompt you to enter a number for prime check:
puts "welcome to prime number check"
puts "enter number for check: "
n = gets
n = n.to_i
def prime(n)
puts "That's not an integer." unless n.is_a? Integer
is_prime = true
for i in 2..n-1
if n % i == 0
is_prime = false
end
end
if is_prime
puts "#{n} is prime!"
else
puts "#{n} is not prime."
end
end
prime(n)
Based on the answer by Darmouse but including edge cases
def prime? (n)
if n <= 1
false
elsif n == 2
true
else
(2..n/2).none? { |i| n % i == 0}
end
end
FYI - re: DarkMouses prime method above - I found it really helpful, but there are a few errors (I think!) that need explaining:
It should be parentheses rather than square brackets... Otherwise you get a TypeError
Range can't be coerced into Fixnum (TypeError)
Secondly, that first colon before 'false' would cause an error too. It's incorrect syntax, as far as I know. Get rid of it.
Lastly, I think you got it the wrong way round?? If you correct the errors I mentioned, it returns true if it ISN'T a prime, and false if it IS.
You can drop the ternary operator altogether I think, and just do:
def prime?(n)
(2..n/2).none?{|i| n % i == 0}
end
Obviously it doesn't cover the edge cases (0,1,2), but let's not split hairs.
...For those who enjoy hairsplitting, here is my full solution to this problem:
def prime?(n)
return false if n < 2
(2..Math.sqrt(n)).none? {|num| length % num == 0}
end
Hope I didn't miss anything :)
This is a little bit off topic according to the details, but correct for the title : using bash integration in ruby you could do :
def is_prime n
`factor #{n}`.split.count < 3
end
bash factor function returns a number plus all of his factors, so if the number is prime, there will be two words count.
This is usefull for code golf only.
I tried this and it worked:
def prime?(n)
return false if n < 2
return true if n == 3 || n == 2
if (2...n-1).any?{|i| n % i == 0}
false
else
true
end
end
def prime?(n)
if n <= 1
return false
else (2..n-1).to_a.all? do |integer|
n % integer != 0
end
end
end
From my prime? lab. Started with eliminating all integers less than or equal to 1.
def prime(n)
pn = [2]
if n < 2
return false
else
(2..n).each do |i|
not_prime = false
(2..Math.sqrt(i).ceil).each do |j|
not_prime = true if i % j == 0
end
pn.push(i) unless not_prime
end
end
return pn
end
p prime(30) gives
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
It will return true if the number is prime.
def prime_number(number)
(2..(number-1)).each do |value|
if (number % value) == 0
return false
end
return true
end
end
puts prime_number(4)
class Object
private
def prime? num
if (2..3).include? num
return true
else
!num.even? and num % 3 != 0 and num > 1
end
end
end
prime? 1
prime? 2
prime? 9
prime? 17
** FOR A SIMPLE SHORTED METHOD**
FIRST INSTALL PRIME GEM
require 'prime'
`p prime.first(20)`
Now save that file as your desired name, this will generate the first 20 prime numbers Automatically!! :-)

Simple recursion problem

I'm taking my first steps into recursion and dynamic programming and have a question about forming subproblems to model the recursion.
Problem:
How many different ways are there to
flip a fair coin 5 times and not have
three or more heads in a row?
If some could put up some heavily commented code (Ruby preferred but not essential) to help me get there. I am not a student if that matters, this is a modification of a Project Euler problem to make it very simple for me to grasp. I just need to get the hang of writing recursion formulas.
If you would like to abstract the problem into how many different ways are there to flip a fair coin Y times and not have Z or more heads in a row, that may be beneficial as well. Thanks again, this website rocks.
You can simply create a formula for that:
The number of ways to flip a coin 5 times without having 3 heads in a row is equal to the number of combinations of 5 coin flips minus the combinations with at least three heads in a row. In this case:
HHH-- (4 combinations)
THHH- (2 combinations)
TTHHH (1 combination)
The total number of combinations = 2^5 = 32. And 32 - 7 = 25.
If we flip a coin N times without Q heads in a row, the total amount is 2^N and the amount with at least Q heads is 2^(N-Q+1)-1. So the general answer is:
Flip(N,Q) = 2^N - 2^(N-Q+1) +1
Of course you can use recursion to simulate the total amount:
flipme: N x N -> N
flipme(flipsleft, maxhead) = flip(flipsleft, maxhead, 0)
flip: N x N x N -> N
flip(flipsleft, maxhead, headcount) ==
if flipsleft <= 0 then 0
else if maxhead<=headcount then 0
else
flip(flipsleft - 1, maxhead, headcount+1) + // head
flip(flipsleft - 1, maxhead, maxhead) // tail
Here's my solution in Ruby
def combination(length=5)
return [[]] if length == 0
combination(length-1).collect {|c| [:h] + c if c[0..1]!= [:h,:h]}.compact +
combination(length-1).collect {|c| [:t] + c }
end
puts "There are #{combination.length} ways"
All recursive methods start with an early out for the end case.
return [[]] if length == 0
This returns an array of combinations, where the only combination of zero length is []
The next bit (simplified) is...
combination(length-1).collect {|c| [:h] + c } +
combination(length-1).collect {|c| [:t] + c }
So.. this says.. I want all combinations that are one shorter than the desired length with a :head added to each of them... plus all the combinations that are one shorter with a tail added to them.
The way to think about recursion is.. "assuming I had a method to do the n-1 case.. what would I have to add to make it cover the n case". To me it feels like proof by induction.
This code would generate all combinations of heads and tails up to the given length.
We don't want ones that have :h :h :h. That can only happen where we have :h :h and we are adding a :h. So... I put an if c[0..1] != [:h,:h] on the adding of the :h so it will return nil instead of an array when it was about to make an invalid combination.
I then had to compact the result to ignore all results that are just nil
Isn't this a matter of taking all possible 5 bit sequences and removing the cases where there are three sequential 1 bits (assuming 1 = heads, 0 = tails)?
Here's one way to do it in Python:
#This will hold all possible combinations of flipping the coins.
flips = [[]]
for i in range(5):
#Loop through the existing permutations, and add either 'h' or 't'
#to the end.
for j in range(len(flips)):
f = flips[j]
tails = list(f)
tails.append('t')
flips.append(tails)
f.append('h')
#Now count how many of the permutations match our criteria.
fewEnoughHeadsCount = 0
for flip in flips:
hCount = 0
hasTooManyHeads = False
for c in flip:
if c == 'h': hCount += 1
else: hCount = 0
if hCount >= 3: hasTooManyHeads = True
if not hasTooManyHeads: fewEnoughHeadsCount += 1
print 'There are %s ways.' % fewEnoughHeadsCount
This breaks down to:
How many ways are there to flip a fair coin four times when the first flip was heads + when the first flip was tails:
So in python:
HEADS = "1"
TAILS = "0"
def threeOrMoreHeadsInARow(bits):
return "111" in bits
def flip(n = 5, flips = ""):
if threeOrMoreHeadsInARow(flips):
return 0
if n == 0:
return 1
return flip(n - 1, flips + HEADS) + flip(n - 1, flips + TAILS)
Here's a recursive combination function using Ruby yield statements:
def combinations(values, n)
if n.zero?
yield []
else
combinations(values, n - 1) do |combo_tail|
values.each do |value|
yield [value] + combo_tail
end
end
end
end
And you could use regular expressions to parse out three heads in a row:
def three_heads_in_a_row(s)
([/hhh../, /.hhh./, /..hhh/].collect {|pat| pat.match(s)}).any?
end
Finally, you would get the answer using something like this:
total_count = 0
filter_count = 0
combinations(["h", "t"], 5) do |combo|
count += 1
unless three_heads_in_a_row(combo.join)
filter_count += 1
end
end
puts "TOTAL: #{ total_count }"
puts "FILTERED: #{ filter_count }"
So that's how I would do it :)

Resources