Project Euler Solutions 1 - 5 5

Posted by Aaron Feng Mon, 31 Dec 2007 23:49:00 GMT

Click on each problem for a more detailed solution.

1. Add all the natural numbers below 1000 that are multiples of 3 or 5.

start = Time.now
total = 0
(1...1000).each do |n|
  total += n if (n % 3).zero? or (n % 5).zero?
end

puts "Took: #{Time.now - start} seconds"
puts total

Took: 0.000977 seconds

2. Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed one million.

start = Time.now
def fib(n1, n2, total)
  return total if n2 > 1000000 
  total += n2 if (n2 % 2).zero? 
  fib(n2, n1 + n2, total)
end

puts "Took: #{Time.now - start} seconds"
puts fib(1, 2, 0)

Took: 1.0e-05 seconds

3. Find the largest prime factor of 317584931803.

def next_prime(start_num, max_num)
  is_prime = true
  prime = 0
  (start_num + 1..max_num).each do |n|
    prime = n
    (2..n - 1).each do |nn| 
      if (n % nn).zero? then is_prime = false; break; end
    end
    if is_prime then break; end
    is_prime = true
  end
  prime
end

start = Time.now
n = 1
biggest_prime = 0
num = 317584931803

while(num != 1 or num > n)
  n = next_prime(n,  num)
  if n > 0
    result = num % n 

    if (result).zero?
      biggest_prime = n
      num = num / n 
    end
  end
  n += 1  
end

puts "Took: #{Time.now - start} seconds"
puts biggest_prime

Took: 0.477182 seconds

4. Find the largest palindrome made from the product of two 3-digit numbers.

start = Time.now
result = 0
left = 0
right = 0

(100...1000).to_a.reverse.each do |l|
  (100...1000).to_a.reverse.each do |r|
    temp = (l * r).to_s 

    if temp == temp.reverse and temp.to_i > result
      result = temp.to_i
      left = l
      right = r
    end     
  end
end

puts "Took: #{Time.now - start} seconds"
puts "#{left} * #{right} = #{result}"

Took: 1.501993 seconds

5. What is the smallest number divisible by each of the numbers 1 to 20?

def is_prime(num)
  if num < 2  then return false; end
  (2..num - 1).each do |n|
    if (num % n).zero?
      return false
    end
  end
  return true
end

def smallest_factor(num)
  (2..num - 1).each do |n|
    if (num % n).zero? then return n; end
  end
  return num
end

start = Time.now
result = 1 
(1..20).each do |n|
  if is_prime(n) 
    result = result * n
  elsif not (result % n).zero? 
    result = result * smallest_factor(n) 
  end
end

puts "Took: #{Time.now - start} seconds"
puts result

Took: 0.00018 seconds

Comments

Leave a response

  1. john Thu, 03 Jan 2008 03:09:41 GMT

    Divisible by all 1, ..., 20. = LCM(1,...,20) lcm(a,b,c) = lcm(a,lcm(b,c)) ... etc

    lcm(x,y) = x * y / gcd(x,y) gcd(x,y) = return x == 0 ? y : gcd(y, x%y)

  2. ashton Fri, 04 Jan 2008 23:43:24 GMT

    Why do you use tail recursion, when it's not necessary? It bottoms out to doing a loop... int n1 = 1, n2 = 2, sum = 0; while (n2 <= 1000000) { sum += (n2 % 2) ? 0 : n2; n2 += n1; n1 = n2 - n1; }

  3. Aaron Feng Sun, 06 Jan 2008 22:37:16 GMT

    I agree. It's matter of taste. There are many ways a problem can be solved. It's just matter of how you picture it in your head.

    On the side note, I think you meant: sum += (n2 % 2) ? n2 : 0;

  4. ashton Tue, 08 Jan 2008 02:34:45 GMT

    Aaron, No, I think you are a bit confused. (n2 % 2) evaluates to being true if it's nonzero, meaning: ((n2 % 2) != 0), which assumes that if it's odd, then perform the "then" statement to the if component.

    i.e., if ((n2 %2) == 1) sum += 0; else sum += n2;

  5. Aaron Feng Tue, 08 Jan 2008 03:34:16 GMT

    Ah yes. Thanks for the correction.

Comments