Why do I get "stack level too deep" with recursion? - ruby

I have this ruby code:
def get_sum n
return 0 if n<1
(n%3==0 || n%5==0) ? n+get_sum(n-1) : get_sum(n-1) #continue execution
end
puts get_sum 999
Seems to be working for values up until 999. When I try 9999 it gives me this:
stack level too deep (SystemStackError)
So, I added this:
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
but nothing happened.
My ruby version is:
ruby 1.9.3p392 (2013-02-22 revision 39386) [x86_64-darwin12.2.1]
I also increased the machine's stack size ulimit -s 32768 which I think is 32MB?
I don't think it is my code's fault as it works with smaller numbers, and I don't think 9999 is a big number. I have 8GB of RAM and I think it is more than enough. Any ideas/help?

Your method cannot take advantage of tail-call optimization (TCO) because it's not tail-recursive, the last expression of the method should be a call to the method itself, get_sum. So there is nothing wrong, simply you reached the recursion limit. With Ruby 1.9.3, that limit is:
def recursive(x)
puts(x)
recursive(x+1)
end
recursive(0)
...
8731
This method, on the other hand, is tail-recursive:
def self.get_sum_tc(n, acc = 0)
if n < 1
acc
else
get_sum_tc(n - 1, acc + ((n % 3 == 0 || n % 5 == 0) ? n : 0))
end
end
Your Ruby may or may not support it. In Ruby you can use recursion when you have some certainties about the depth-level you'll reach, but it's definitely not idiomatic to loop over a collection of unknown size. You usually have other abstractions for this kind of tasks, for example:
(1..9999).select { |x| x % 5 == 0 || x % 3 == 0 }.reduce(0, :+)

The problem is, you have a routine n+get_sum(n-1), when n has common factors 3 or 5, Ruby goes ahead to this routine. This cannot be optimized by tail-recursion. Ruby has to keep the current frame to remember the current n and only when get_sum(n-1) is computed can Ruby return and throw away the frame.
Generally, the stack space is expensive. By default, the operating system reserves fixed amount of stack space (say 1M, or maybe less) for each thread. This can be consumed up quickly. For your code, (9999/3 + 9999/5) recursive calls consumed all the stack space.
If you want to keep the recursive programming pattern, you have to change the behavior of your method call from recursive (your current state) to iterative.
def get_sum(n, sum = 0)
return sum if n < 1
if n % 3 == 0 || n % 5 == 0
get_sum(n - 1, sum + n)
else
get_sum(n - 1, sum)
end
end
However, it seems that Ruby's tail recursion optimization isn't that powerful. For the above code sample, there are two different get_sum() tail calls. Ruby won't optimize this. You'll have to rewrite the two calls into one.
And besides, to make this work with the RubyVM tweak you have provided, you have to load the method definition at runtime. That's because the RubyVM tweak happens at runtime. You can't put the method definition directly in the same file, or the method will be parsed at compile time and no optimization will take effect.
You can either put the get_sum in a separate file and require that lib after the RubyVM tweak:
# file: test_lib.rb
def get_sum(n, sum = 0)
if n < 1
sum
else
get_sum(n - 1, sum + (n % 3 == 0 || n % 5 == 0 ? n : 0))
end
end
# eof
# file: test.rb
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
require_relative 'test_lib'
puts get_sum(999999)
Or, use eval to evaluate the method definition in a String at runtime:
RubyVM::InstructionSequence.compile_option = {
:tailcall_optimization => true,
:trace_instruction => false
}
eval <<END
def get_sum(n, sum = 0)
if n < 1
sum
else
get_sum(n - 1, sum + (n % 3 == 0 || n % 5 == 0 ? n : 0))
end
end
END
puts get_sum(990000)

Related

newbie : Ruby programming for factorials

So I got this question as an assignment in Computer class and I literally have no idea why the solution was such. I am hoping someone can explain it thoroughly to me.
My problem is:
How does one know that n*(n-1)*(n-2)*...*2*1 is actually just the math expression n! Is this just a magical formula that I have to remember? (Yes, I don't know much math beyond arithmetic)
Is there a better way of programming factorials
Write a method that takes an integer n in; it should return
n*(n-1)*(n-2)*...*2*1. Assume n >= 0.
As a special case, factorial(0) == 1.
Difficulty: easy.
def factorial(n)
if n < 0
return nil
end
result = 1
while n > 0
result = result * n
n -= 1
end
return result
end
puts("factorial(0) == 1: #{factorial(0) == 1}")
puts("factorial(1) == 1: #{factorial(1) == 1}")
puts("factorial(2) == 2: #{factorial(2) == 2}")
puts("factorial(3) == 6: #{factorial(3) == 6}")
puts("factorial(4) == 24: #{factorial(4) == 24}")
Yes, that is the definition of a factorial. One knows it by having learned the definition.
There are many ways to code up a factorial. Yours happens to be the most basic one. As you learn more about Ruby, you will start to be able to write more idiomatic code. For example...
def factorial_functional(n)
n < 0 ? nil : (1..n).inject(1, &:*)
end
def factorial_recursive(n)
return if n < 0
return 1 if n == 0
n * factorial_recursive(n - 1)
end
It is arguable what is "better", since there are so many factors: readability, conciseness, speed, memory usage... And readability is directly related to the target audience: I'm sure your code is more readable to you than either of my examples, but to someone experienced it is much more of a hassle to go through your longer code.
Amadan already showed better ways of writing the factorials method, but I believe you were also asking for an explanation of the solution you brought in.
# The method `factorial` receives a number `n` and returns `n!`.
def factorial(n)
if n < 0 # If the number `n` is negative
return nil # `n!` can't be calculated, so return nothing.
end # Otherwise, go on...
result = 1 # `result` is 1. For now...
while n > 0 # While the number `n` is positive
result = result * n # `result` becomes `result` times `n`.
n -= 1 # Decrease the number `n` by one.
end
# Once the number `n` becomes zero, `result` is
# equal to the multiplication of all numbers from 1
# to what `n` was at the very beginning.
return result # Return `result`
end
I would also like to contribute the following "better" way of defining the factorial method that can be read, more or less, in plain English:
def factorial(number)
return unless number.is_a? Integer and number >= 0
total = 1
number.downto 1 do |this_number|
total = total * this_number
end
return total
end

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

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

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

Optimization of code for speed

It's a prime number sieve, but not Eratosthenes's Sieve.
I feel that it's poorly written because I'm new to programming and Ruby in general. This is only the second program I've written in Ruby, but I'd like to optimize it as best as possible. The problem is I don't have a firm understanding of what I need to change to make it faster, except that I know the program path/data structures aren't ideal - I just don't have a concept to work from to MAKE them ideal
An ideal answer won't necessarily say "change X to Y", but it would be more helpful if it pointed me in the direction of a good resource for this kind of information, or a method by which I can derive information regarding efficiency of different pieces of the program.
count = 0
x = 0
$results = Array.new []
inpt = []
class PrimeFun
def initialize(x, y)
array1 = (x..y).to_a
array1.each do |n|
if PrimeFun.primelogic(n%60, n) == 1
array1.delete_if { |p| p % n == 0}
$results << n
elsif n == 2 || n == 3 || n == 5
$results << n
end
end
end
def self.primelogic(r, n)
#prime = case r
when 1, 13, 17, 29, 37, 41, 49, 53
formulaone(n)
when 7, 19, 31, 43
formulatwo(n)
when 11, 23, 47, 59
formulathree(n)
else -1
end
end
def self.formulaone(n)
#x = 1
#y = -1
until 4*(#x**2) >= n
#y = -#y if Math.sqrt(n-(4*(#x**2))).floor - Math.sqrt(n-(4*(#x**2))) == 0
#x += 1
end
#y
end
def self.formulatwo(n)
#x = 1
#y = -1
until 3*(#x**2) >= n
#y = -#y if Math.sqrt(n-(3*(#x**2))).floor - Math.sqrt(n-(3*(#x**2))) == 0
#x += 1
end
#y
end
def self.formulathree(n)
#x = 1
#y = -1
until 3*(#x**2) >= n
#y = -#y if Math.sqrt(((#x**2)+n)/3).floor - Math.sqrt(((#x**2)+n)/3) == 0 && #x > #y
#x += 1
end
#y
end
end
x = STDIN.gets.to_i
while count < x
inpt << STDIN.gets.chomp
count += 1
end
inpt.each do |n|
a = n.split(" ").map { |a| a.to_i }
PrimeFun.new(a[0], a[1])
$results << ""
end
puts $results
You should familiarize yourself with the Benchmark module included in the Ruby standard library to measure the running time of (different versions of) your methods. I have not run the below code suggestions through Benchmark myself, they are just some quick ideas off the top of my head on how to improve the speed and readability of your code - feel free to benchmark them and report back with the results! :-)
Profiling your code to find the bottlenecks is also a good idea - no point spending hours optimizing parts of your code that is not contributing a large amount to the total run time. Check out the ruby-prof gem for a good tool to help you with this.
Now for a quick look at your code and some suggestions for improvement.
Without considering the actual algorithm your are using, your first order of business should be to eliminate your code's tendency to recalculate the same values over and over multiple times.
Also, you seem to be using instance variables (#x, #y, etc.) where local variables will do the job nicely. Not to mention your use of class methods which are only being called from within instance methods of the same class. You should turn those into instance methods as well. (These are not really optimization hints, but suggestions on how to improve your Ruby code.)
Take this method as an example:
def self.formulaone(n)
#x = 1
#y = -1
until 4*(#x**2) >= n
#y = -#y if Math.sqrt(n-(4*(#x**2))).floor - Math.sqrt(n-(4*(#x**2))) == 0
#x += 1
end
#y
end
In the loop, you are calculating the expression 4*(#x**2) three times. One is enough, so store the result in a temporary local variable, fsq. You are also calculating the square root of the same number two times inside the loop. Again, store the value in a temporary variable root, and use that.
def formulaone_b(n)
x = 1
y = -1
until (fsq = 4*(x**2)) >= n
root = Math.sqrt(n - fsq)
y = -y if root.floor - root == 0
x += 1
end
y
end
That should be a good start.
Probably not an optimization, but you can make the code a bit cleaner by calculating the range for x beforehand, then iterate over it using each:
def formulaone_c(n)
y = -1
(1..Math.sqrt(n / 4)).each do |x|
root = Math.sqrt(n - 4*(x**2))
y = -y if root.floor == root # See below
end
y
end
In the above code I have also replaced the comparison root.floor - root == 0 with the simpler but equivalent comparison root.floor == root, removing one unnecessary substraction.
One more idea: instead of calculating n - 4*(x**2) for each iteration, you might just gain a tiny bit of speed by noticing that this value will decrease by x * 8 + 4 every step, so use a helper variable d to update the value of the former expression like this:
def formulaone_d(n)
y = -1
d = n - 4 # Value of n - 4*(x**2) when x = 1
(1..Math.sqrt(n / 4)).each do |x|
root = Math.sqrt(d)
y = -y if root.floor == root
d -= x * 8 + 4 # Value of n - 4*(x**2) after x increases
end
y
end
Correctness
First, your code is not correct:
def self.formulathree(n)
#x = 1
#y = -1
until 3*(#x**2) >= n
#y = -#y if Math.sqrt(((#x**2)+n)/3).floor - Math.sqrt(((#x**2)+n)/3) == 0 && #x > #y
#x += 1
end
#y
end
Whether or not #y is less than #x is immaterial, and it's always true, since #y = ±1 and when #x = 1, #y = -1 < 1.
What you are interested in is the number of representations
n = 3*a^2 - b^2
with integers a > b > 0. Now, a^2 = (n + b^2)/3, so you want
(n + b^2)/3 > b^2
n + b^2 > 3*b^2
n > 2*b^2
and not n > 3*b^2 (b stands for #x here). For example,
143 = 11* 13 = 3*7^2 - 2^2 = 3*8^2 - 7^2
but 3*7^2 = 147 > 143, so #x = 7 wouldn't be considered, so 143 would be deemed prime by formulathree and
179 = 3*9^2 - 8^2
would not be considered prime, although it is, since 3*8^2 = 192 > 179.
Another problem becomes apparent when you output each considered n in initialize for debugging.
array1 = (x..y).to_a
array1.each do |n|
if PrimeFun.primelogic(n%60, n) == 1
array1.delete_if { |p| p % n == 0}
array1.each is more or less
for(index = 0; index < array1.length; ++i)
but when you remove the multiples of n, you also remove n itself, so the element directly after moves to the index n had, and is skipped. You can fix that by deleting only multiples of n greater than n:
array1.delete_if { |p| p > n && p % n == 0 }
Performance
The big performance problem is the algorithm. If you call initialize(2,n), for every prime, you traverse the array and remove multiples by trial division. Each prime is divided by each smaller prime (except 2, 3 and 5) to see whether it shall be removed from the array. That is the infamous Turner "sieve" whose complexity is O((n/log n)^2), almost quadratic. Since you don't even remove multiples of 2,3 and 5 from the array unless these multiples have larger prime factors, the complexity might be even slightly worse.
Micro-optimisations simply aren't worth the effort before you pick a better algorithm.
The next problem is the determination of primality using formulaX. If you also removed multiples of 2, 3 and 5 from the array, the test wouldn't even be necessary, every considered number would be a known prime per trial division. Since you don't, checking the candidate for divisibility by 2, 3 or 5 would be much faster than primelogic.
primelogic uses the logic also used for the Atkin sieve to determine primality, but it tests every number in isolation, therefore testing each number n is O(√n). Computing the square root is far more complicated than a division, hence that takes longer than a prime test by trial division.

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!! :-)

Resources