Working with Ruby
Hi, I am Jan. This is my old Ruby blog. I still post about Ruby, but I now do it on idiosyncratic-ruby.com. You should also install Irbtools to improve your IRB.

Project Euler 1-5 (Ruby)

projecteuler.net tries to get you thinking about how to solve mathematical problems by programming. Here are the first five problems, solved in Ruby, including comments.

 1
2
3
4
5
6
7
8
9
10
11
12
# https://projecteuler.net/index.php?section=problems&id=1
#  look at the first 1000 numbers and add those to the sum
#  that are multiples of 3 or 5

sum = 0 # initial sum

1000.times{ |n| # iteration index (0-999)
  sum += n if n%3==0 || # add to sum if divisible by
              n%5==0    #  3 or 5 without rest
}

puts sum

 1
2
3
4
5
6
7
8
9
10
11
12
# https://projecteuler.net/index.php?section=problems&id=2
#  calculate fibonacci (non-recursive) and sum all even values

n=m = 1 # first two fib. numbers
sum = 0 # initial sum

while m < 4_000_000 # as long as fib. sequence is < 4 000 000
  n,m = m,n+m # calculate next step (sum of the prev. 2 numbers)
  sum += n  if n.even? # add to sum if even [ruby 1.9]
end

puts sum

 1
2
3
4
5
6
7
8
9
10
11
12
13
# https://projecteuler.net/index.php?section=problems&id=3
#  find the largest prime factor of 600 851 475 143

a = 600_851_475_143
f = 2 # smallest possible prime factor

# Divide "evil big number" by lowest prime factors to get the
#  biggest one. Prime factors are the numbers, which do not
#  leave a rest. If a possible number is not a prime factor 
#  candidate anymore, check the next one.
a%f==0 ? a/=f : f+=1  while a>1

puts f

 1
2
3
4
5
6
7
8
9
10
11
12
13
# https://projecteuler.net/index.php?section=problems&id=4
#  find the largest palindrome made from xxx*xxx

products = # get an array of ALL xxx*xxx
  (100..999).map{ |a|
    (100..999).map{ |b|
      a*b
    }
  }.flatten.select{ |p|      # select those, which are reversed
    p.to_s == p.to_s.reverse # the same as non-reversed
  }.sort.reverse # sort them and reverse result

puts products[0] # put out first (and largest) palindrome

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# https://projecteuler.net/index.php?section=problems&id=5
#  find a number that you can divide by 1..20
#  using the method described at the solution sheet at euler

# needed input
till = 20
primes = [2,3,5,7,11,13,17,19]

# get factor for each prime
factors = primes.map{ |f|
  f > (limit ||= till**0.5) ? 1 : # only calcutlate if f < square root of till
  ( Math.log(20)/Math.log(f) ).to_i # calc using log (see euler sheet)
}

# now multiply all primes**factors
number = 1
p = primes.each  # init extern iterators
f = factors.each

loop{ number *= p.next**f.next } # loop breaks when StopIteration is raised

# output
puts number

Other solutions: 6-18, 19-25

Creative Commons License

Bob | January 18, 2010

For problem 1, the following solution is more in the spirit of Ruby, IMHO:

puts (1...1000).select {|n| n % 3 == 0 || n % 5 == 0}.inject(0) {|s, n| s + n}

J-_-L | January 18, 2010

Although I think, the Listing 1 method is the easist-to-understand method, I agree, your way is more Ruby-like. In Ruby 1.9 / 1.87 you can even write it further significant: puts (1...1000).select{|n| n % 3 == 0 || n % 5 == 0}.inject(:+)

Mark | August 02, 2010

Or...

(1...1000).reduce(0) do |sum,n|
sum += n if n % 3 == 0 || n % 5 == 0
sum
end

Juan Romero Abelleira | June 04, 2011

Or instead of brute forcing the problem you could modify the steps through the range:

puts (0...1000).step(3).to_a.concat((0...1000).step(5).to_a).inject(:+)

J-_-L | June 13, 2011

@Juan Nice approach :D (but you need to add uniq). A cool 1.9.2 rewrite may be: <code>[*(0...1000).step(3),*(0...1000).step(5)].uniq.inject(:+)</code>