Getting a 'nil:Nil Class' error in Ruby, but the array doesn't seem to empty - ruby

I'm trying to code the 'Sieve of Eratosthenes' in Ruby and I'm having difficulty in the second 'while' loop. I want to test to see if integers[j] % integers[0] == 0, but the compiler keeps giving me a nil:Nil Class error at this line. I can't figure out the problem.
n = gets.chomp.to_i
puts
while n < 2
puts 'Please enter an integer >= 2.'
puts
n = gets.chomp.to_i
puts
end
integers = []
i = 0
while i <= n - 3
integers[i] = i + 2
i += 1
end
primes = []
j = 1
while integers != []
primes.push integers[0]
while j <= integers.length
if integers[j] % integers[0] == 0
integers.delete(integers[j])
end
j += 1
end
integers.shift
j = 1
end
puts integers
puts
puts primes
Thanks in advance for any help!

It's an off-by-one error. You're testing for j <= integers.length. So, for example, if you array has five items, the last iteration will be integers[5]. But the last index in a five-item array is 4 (because it starts at 0). You want j < integers.length.

Related

Ruby- prime number unique and duplicates

I'm just learning Ruby :) and Im trying to create a simple prime-number program where all the primes of a number are printed.
I'm getting errors where the prime and nonprime numbers are mixed up
(ie: input of 9 will get you all nonprimes).
I'm sorry for such a beginner question - I'm struggling alot and need some help :)
puts "Enter a number please "
num = gets.chomp.to_i
i = 2
number = 2
while i < num
if number % i == 0
prime = false
end
i += 1
end
if prime == true
puts "#{number} is prime"
else
puts "#{number} is not prime"
end
number += 1
end
while i < num
if number % i == 0
prime = false
end
i += 1
end
# ...
It looks like that first end is meant to be an else.
It's easier to catch these things when you simplify your code, e.g. this method reduces to this (although there are other issues with it):
i = 2
number = 2
while i < num
(number % i).zero? ? prime = false : i += 1
puts "#{number} is #{'not ' unless prime}prime"
number += 1
end
End error is because of else
while i < num
if number % i == 0
prime = false
else
i += 1
end
if you have a short If - neater is writing it like:
if-condition ? 1 : 0
and in your case while is.. not the nicest choice - you should use range
(1...3).map{|x| puts(x) }
{} - allows multiline(with do end end)
this prints [1,2]
(1..3).map{|x| x*2 }
would be [2,4,9]
This should be enough hints of how to play around with your code without ruining the process.

How to loop over an entire method until you achieve what you want ? (ruby)

I'm learning ruby and practicing with codewars, and I've come to a challenge that I feel I mainly understand (rudimentarily) but I'm unable to figure out how to continue looping over the method until I reach the result I'm looking for.
The challenge is asking to reduce a number, by multiplying its digits, until the multiplication results in a single digit. In the end it wants you to return the number of times you had to multiply the number until you arrived at a single digit. Example -> given -> 39; 3 * 9 = 27, 2 * 7 = 14, 1 * 4 = 4; answer -> 3
Here's my code :
def persistence(n)
if n < 10
return 0
end
arr = n.to_s.split("")
sum = 1
count = 0
arr.each do |num|
sum *= num.to_i
if num == arr[-1]
count += 1
end
end
if sum < 10
return count
else
persistence(sum)
end
end
Thanks for your help!
Your function is looking great with recursion but you are reseting the count variable to 0 each time the loop runs, I think if you use an auxiliar method it should run ok:
this is in base of your code with minor improvements:
def persistence(n)
return 0 if n < 10
count = 0
multiply_values(n, count)
end
def multiply_values(n, count)
arr = n.to_s.chars
sum = 1
arr.each do |num|
sum *= num.to_i
if num == arr[-1]
count += 1
end
end
if sum < 10
return count
else
multiply_values(sum, count)
end
end
a shorter solution could be to do:
def persistence(n)
return 0 if n < 10
multiply_values(n, 1)
end
def multiply_values(n, count)
sum = n.to_s.chars.map(&:to_i).reduce(&:*)
return count if sum < 10
multiply_values(sum, count + 1)
end
and without recursion:
def persistence(n)
return 0 if n < 10
count = 0
while n > 10
n = n.to_s.chars.map(&:to_i).reduce(&:*)
count += 1
end
count
end
Let's look at a nicer way to do this once:
num = 1234
product = num.to_s.split("").map(&:to_i).reduce(&:*)
Breaking it down:
num.to_s.split("")
As you know, this gets us ["1", "2", "3", "4"]. We can easily get back to [1, 2, 3, 4] by mapping the #to_i method to each string in that array.
num.to_s.split("").map(&:to_i)
We then need to multiply them together. #reduce is a handy method. We can pass it a block:
num.to_s.split("").map(&:to_i).reduce { |a, b| a * b }
Or take a shortcut:
num.to_s.split("").map(&:to_i).reduce(&:*)
As for looping, you could employ recursion, and create product_of_digits as a new method for Integer.
class Integer
def product_of_digits
if self < 10
self
else
self.to_s.split("").map(&:to_i).reduce(&:*).product_of_digits
end
end
end
We can now simply call this method on any integer.
1344.product_of_digits # => 6

NoMethodError with .chr.to_i

I'm trying to create a recursive method sum_of_digits(i) that takes the sum of integers, i.e. '456' = 4+5+6 = 15
However, I receive a NoMethodError for chr.to_i in the following code:
def sum_of_digits(i)
input = i.to_s
if i == 0
return 0
elsif input.length == 1
return i
else
for n in 1..input.length
sum += input[i].chr.to_i % 10^(n-1)
end
end
return sum
end
Thank you!
String indexes are zero-based in ruby. The problem is here:
for n in 1..input.length
it should be written as
for n in 0..input.length-1
BTW, call to chr is superfluous as well, since you already have a string representation of a digit there. As well, sum must be declared in advance and set to zero.
Also, the whole code is not ruby idiomatic: one should avoid using unnecessary returns and for-loop. The modified version (just in case) would be:
def sum_of_digits(i)
input = i.to_s
case
when i == 0 then 0 # return zero
when input.length == 1 then i # return i
else
sum = 0
input.length.times do |index|
sum += input[index].to_i % 10^index
end
sum
end
end
or, even better, instead of
sum = 0
input.length.times do |index|
sum += input[index].to_i % 10^index
end
sum
one might use inject:
input.length.times.inject(0) do |sum, index|
sum += input[index].to_i % 10^index
end

Project Euler #50 - Consecutive prime sum - Ruby

I'm trying to solve Project Euler problem #50 (https://projecteuler.net/problem=50) where the problem is defined as:
Which prime, below one-million, can be written as the sum of the most
consecutive primes?
I've come up with two different solutions both giving the same wrong answer which leads me to believe the error happens as I'm building my list of primes, however, I can't seem to find any error. My solutions also seem to work for N = 10 and N = 100 but not N = 1000. Any help is appreciated.
Solution 1: (output = 958577)
require 'Prime'
# Initialising primes
N = 1_000_000
primes = {}
(2..N).each do |i|
primes[i] = true
end
i = 2
while i * i <= N
if primes[i]
j = i
while i * j <= N
primes[i * j] = false
j += 1
end
end
i += 1
end
# New prime list where total sum is less than N
new_primes = []
i = 2
sum = 0
while sum + i < N
if primes[i]
new_primes << i
sum += i
end
i += 1
end
# Keep removing last prime from list until total sum is prime
while true
if Prime.prime?( new_primes.inject(0, :+) )
puts new_primes.inject(0, :+)
break
else
new_primes.delete_at(-1)
end
end
Solution 2: (output = 958577)
require 'Prime'
# Initialising primes
N = 1_000_000
primes = {}
(2..N).each do |i|
primes[i] = true
end
i = 2
while i * i <= N
if primes[i]
j = i
while i * j <= N
primes[i * j] = false
j += 1
end
end
i += 1
end
sum = 0
max = 0
i = 2
while i < N
if primes[i]
sum += i
if sum < N && Prime.prime?(sum)
max = sum
end
end
i += 1
end
puts max
(w.r.t to Solution 2) Your method to find primes seems correct. The problem is with your logic. If the primes less than N are p_1,p_2,..,p_k, then you are only considering
only the sums p_1, p_1+p_2, p_1+p_2+p_3,...,p_1+p_2+..+p_k. What about sums not starting from p_1, say p_3+p_4.

Ruby - Prime Number calculator

I need some feedback to figure out why I cant puts or print anything from my methods on the screen. This is a simple script I wrote to solve the problem of finding the 1001st prime number. Thanks
def primes
# iterates through numbers until it has the 1001th prime number and returns it.
# I chose to create the num_primes variable instead of counting the number of
# elements in in_prime_array every iteration
# based upon a guess that it would be faster to check.
is_prime_array = []
num_primes = 0
i = 2
loop do
is_prime_array << i && num_primes += 1 if is_prime?(i) == true
i += 1
break if num_primes == 1001
end
is_prime_array[1001]
end
def is_prime? (num)
# Checks to see if the individual number given is a prime number or not.
i = 2
loop do
if i == num
return true
elsif num % i == 0
return false
else
i += 1
end
end
end
Thanks for any help!
EDIT
I took your advice and tried this pice of code:
def is_prime? (num)
# Checks to see if the individual number given is a prime number or not.
i = 2
loop do
if i == num
return true
elsif num % i == 0
return false
else
i += 1
end
end
end
i = 0
count = 0
loop do
count += 1 if is_prime?(x)
puts "#{i}" if count == 1001
break
end
It still returns nothing. Hummm
i = 0
count = 0
loop do
if is_prime(i)
count += 1
end
if count == 10001
puts "#{i}"
break
end
end
Simple method :)
It's an off-by-one error. If you have 1001 elements in an array, the last element will be at index 1000.
Where you have
is_prime_array[1001]
Change it to
is_prime_array[1000]
And you can do this:
puts primes
=> 7927
You could also have
is_prime_array.last
instead of a specific index number.
What are you trying to "puts"? The first thing I notice is that there is no call to primes in the file, so nothing will happen if you try to run this code by itself. Maybe that's why you don't see anything printed.
Here's an example of how to print a few variables inside your loop:
loop do
...
puts "At iteration #{i}, we have prime=#{is_prime?(i)}"
If you don't know, enclosing a statement with #{<statement goes here>} inside a string is the same as appending the return value of <statement goes here> to the string at that position. This is the same as "Str " + blah + " rest of str" in a language like Java.

Resources