Project Euler #3 Ruby - ruby

The task:
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143?
The correct answer is 6857.
My code:
def prime?(n)
(2..(n-1)).each { |x| false if n % x == 0 }
true
end
x = 2
prime_factor_arr = []
number = 600_851_475_143
while x < number
if number % x == 0 && prime?(x)
prime_factor_arr << x
number = number / x
end
x += 1
end
puts prime_factor_arr.last
puts prime?(prime_factor_arr.last)
puts prime_factor_arr
In the above case, I get 1471 as the largest prime. If I change the code to:
while x < (number / x)
if number % x == 0 && prime?(x)
prime_factor_arr << x
end
x += 1
end
I get 486847. The array printed in the end is:
[71, 839, 1471, 6857, 59569, 104441, 486847]
It is not clear to me why my code does not work. Could anybody help?

For the answer to the question, Sergio is right. But the code Sergio suggests (as well as yours) will not work correctly when number is a prime itself.
A better way to write is:
def prime?(n); (2...n).none?{|x| n.%(x).zero?} end
number = 600_851_475_143
number.downto(1).find{|x| number.%(x).zero? and prime?(x)}

Try this.
def prime? n
(2..(n-1)).each { |x| return false if n % x == 0 }
true
end
n = 600_851_475_143
a = []
product_sum = 1
x = 2 # 2 is the first prime number
while product_sum < n
if n % x == 0 && prime?(x)
a << x
product_sum *= x
end
x += 1
end
puts "The answer is #{a.last}"

The prime lib (from standard lib) is very nice for Project Euler. But it takes the fun out of this one:
require "prime"
600851475143.prime_division.last.first # => 6857

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.

Ruby FizzBuzz using arrays, my logic seems right but it is getting an error

FizzBuzz, a classic problem, returns all the numbers up to N with a slight twist. If a number is divisible by 3, it is replaced with "fizz". If it's divisible by 5, it's replaced with "buzz". If it's divisible by both, it's replaced with "fizzbuzz"
I keep getting this Error message:
comparison of Fixnum with nil failed
Can someone explain this error message to me please? Also why is the code not working?
def fizz_buzz(n)
arr = (1..n).to_a
i = 0
while arr[i] < arr[n]
if i % 3 == 0 && i % 5 == 0
arr[i] = 'fizzbuzz'
elsif i % 3 == 0
arr[i] = 'fizz'
elsif i % 5 == 0
arr[i] = 'buzz'
else
arr[i] = i
i += 1
end
end
return arr
end
fizz_buzz(12)
Your conditions are just a bit off, give this a try:
def fizz_buzz(n)
arr = (1..n).to_a
i = 0
while i < n
if arr[i] % 3 == 0 && arr[i] % 5 == 0
arr[i] = 'fizzbuzz'
elsif arr[i] % 3 == 0
arr[i] = 'fizz'
elsif arr[i] % 5 == 0
arr[i] = 'buzz'
end
i+=1
end
return arr
end
Trying to access arr[n] puts you outside the bounds of the array which returns nil in Ruby.
You can update the code the ruby way, by using blocks and guards, I don't remember last time I used a while loop in ruby :)
Also, Array.new accepts a block as an argument which you can exploit to build your Array in a single step:
def fizz_buzz(n)
Array.new(n) do |index|
x = index + 1
case
when x % 3 == 0 && x % 5 == 0 then "fizzbuzz"
when x % 3 == 0 then "fizz"
when x % 5 == 0 then "buzz"
else x
end
end
end
Notice I used 1 as a base index and not 0, you can just remove x = index + 1 and replace x with index to have it working in a zero index base
A solution with a block instead of the while loop, and guards
def fizz_buzz(n)
arr = (1..n).to_a
0.upto(n - 1) do |i|
arr[i] = "fizzbuzz" and next if i % 3 == 0 && i % 5 == 0
arr[i] = "fizz" and next if i % 3 == 0
arr[i] = "buzz" if i % 5 == 0
end
arr
end
#brad-melanson beat me to the straight-forward answer to your question, so I'll share an answer which uses some common Ruby idioms (passing a range to the Array constructor and map), which simplify things, prevent you from having to do any iteration bookkeeping and prevent the possibility of off-by-one errors, out-of-bounds errors, etc.
def fizz_buzz(n)
Array(1..12).map do |n|
if n % 3 == 0 && n % 5 == 0
'fizzbuzz'
elsif n % 3 == 0
'fizz'
elsif n % 5 == 0
'buzz'
else
n
end
end
end
result = fizz_buzz 12
# result => [1, 2, "fizz", 4, "buzz", "fizz", 7, 8, "fizz", "buzz", 11, "fizz"]

Finding the sum of the digits of a factorial

factorial_sum(5) should return 3. The error I'm getting is that "inject is an undefined method". I was also wondering if it's possible to combine the two functions. I wasn't sure as I am just starting out on recursion. Thanks!
def factorial_sum(x)
factorial = factorial(x)
factorial.to_s.split('').collect { |i| i.to_i }
sum = factorial.inject { |sum, n| sum + n }
end
def factorial(x)
if x < 0
return "Negative numbers don't have a factorial"
elsif x == 0
1
else
factorial = x * factorial(x - 1)
end
end
puts factorial_sum(5)
factorial.to_s.split('').collect { |i| i.to_i }
This line is a no-op. You build a list and then throw it away. You probably meant factorial = ...
I have to say though that this would be pretty easy to find with a little effort and some print statements...
By the way, here's a slightly more concise way:
(1..x).reduce(:*).to_s.chars.map(&:to_i).reduce(:+)
A direct way without temporarily converting it into strings, and without recursion.
s, q = 0, 120
while q > 0
q, r = q.divmod(10)
s += r
end
s # => 3

Finding a prime number using a **custom** Ruby method

I would like to pass an array of numbers to my is_prime? method and return if the numbers are valid or not. I do not want to use:
require 'prime'
a = [1,2,3,4,5]
Hash[a.zip(a.map(&Prime.method(:prime?)))]
This is learning experience. My current code is only outputing the first number in the array. Can someone help me understand what I am doing wrong? Thanks!
def is_prime?(*nums)
i = 2
nums.each do |num|
while i < num
is_divisible = ((num % i) == 0)
if is_divisible == false
x = "#{num}: is NOT a prime number." #false
else
x = "#{num}: is a prime number." #true
end
i +=1
end
return x
end
end
puts is_prime?(27,13,42)
You are returning in the loop.
A few bugs in your method:
def is_prime?(*nums)
nums.each do |num|
return false if num == 1
next if num == 2 # 2 is the only even prime
i = 2 # needs to be reset for each num
while i < num
return false if num % i == 0 # num is not prime
i += 1
end
end
true # We'll reach here only if all the numbers are prime
end
This will return your results in the same format as your usage of the prime library with the same logic as your custom function:
def is_prime?(*nums)
nums.each_with_object({}) do |num, hsh|
hsh[num] = num > 1 && 2.upto(num - 1).none? { |i| num % i == 0 }
end
end
puts is_prime?(27,13,42)
# => {27=>false, 13=>true, 42=>false}
Since you mention this is just for learning, I'm assuming you know that a sieve is a better way to go for this than brute force iteration.
If you want an explanation of how the above code works or further help understanding why your current code doesn't, let me know in the comments.

more ruby way of doing project euler #2

I'm trying to learn Ruby, and am going through some of the Project Euler problems. I solved problem number two as such:
def fib(n)
return n if n < 2
vals = [0, 1]
n.times do
vals.push(vals[-1]+vals[-2])
end
return vals.last
end
i = 1
s = 0
while((v = fib(i)) < 4_000_000)
s+=v if v%2==0
i+=1
end
puts s
While that works, it seems not very ruby-ish—I couldn't come up with any good purely Ruby answer like I could with the first one ( puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).
For a nice solution, why don't you create a Fibonacci number generator, like Prime or the Triangular example I gave here.
From this, you can use the nice Enumerable methods to handle the problem. You might want to wonder if there is any pattern to the even Fibonacci numbers too.
Edit your question to post your solution...
Note: there are more efficient ways than enumerating them, but they require more math, won't be as clear as this and would only shine if the 4 million was much higher.
As demas' has posted a solution, here's a cleaned up version:
class Fibo
class << self
include Enumerable
def each
return to_enum unless block_given?
a = 0; b = 1
loop do
a, b = b, a + b
yield a
end
end
end
end
puts Fibo.take_while { |i| i < 4000000 }.
select(&:even?).
inject(:+)
My version based on Marc-André Lafortune's answer:
class Some
#a = 1
#b = 2
class << self
include Enumerable
def each
1.upto(Float::INFINITY) do |i|
#a, #b = #b, #a + #b
yield #b
end
end
end
end
puts Some.take_while { |i| i < 4000000 }.select { |n| n%2 ==0 }
.inject(0) { |sum, item| sum + item } + 2
def fib
first, second, sum = 1,2,0
while second < 4000000
sum += second if second.even?
first, second = second, first + second
end
puts sum
end
You don't need return vals.last. You can just do vals.last, because Ruby will return the last expression (I think that's the correct term) by default.
fibs = [0,1]
begin
fibs.push(fibs[-1]+fibs[-2])
end while not fibs[-1]+fibs[-2]>4000000
puts fibs.inject{ |sum, n| n%2==0 ? sum+n : sum }
Here's what I got. I really don't see a need to wrap this in a class. You could in a larger program surely, but in a single small script I find that to just create additional instructions for the interpreter. You could select even, instead of rejecting odd but its pretty much the same thing.
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
puts fib.take_while{|i| i < 4000000}
.reject{|x| x.odd?}
.inject(:+)
That's my approach. I know it can be less lines of code, but maybe you can take something from it.
class Fib
def first
#p0 = 0
#p1 = 1
1
end
def next
r =
if #p1 == 1
2
else
#p0 + #p1
end
#p0 = #p1
#p1 = r
r
end
end
c = Fib.new
f = c.first
r = 0
while (f=c.next) < 4_000_000
r += f if f%2==0
end
puts r
I am new to Ruby, but here is the answer I came up with.
x=1
y=2
array = [1,2]
dar = []
begin
z = x + y
if z % 2 == 0
a = z
dar << a
end
x = y
y = z
array << z
end while z < 4000000
dar.inject {:+}
puts "#{dar.sum}"
def fib_nums(num)
array = [1, 2]
sum = 0
until array[-2] > num
array.push(array[-1] + array[-2])
end
array.each{|x| sum += x if x.even?}
sum
end

Resources