55502f40dc8b7c769880b10874abc9d0

Sorry if I shouldn't be posting these solutions here... I'm learning Ruby and know there has to be some better ways to do this...

if $0 == __FILE__
        total = 0

        def fibonacci_below max
                first = 1
                second = 2
                fib = [first, second]
                while second+first <= max
                        fib << first + second
                        first = second
                        second = fib.last
                end
                fib
        end
        
        fib = fibonacci_below(4000000)
        fib.reject!{ |x| x.odd?}
        p fib.inject{|sum, x| sum + x}
end

Refactorings

No refactoring yet !

F9a9ba6663645458aa8630157ed5e71e

Ants

January 24, 2012, January 24, 2012 20:20, permalink

No rating. Login to rate!

Your code is already nicely written with loose coupling and tight cohesion. For general purpose code, or code that will be maintained over a long time, you want to keep things this way. You've nicely separated the concerns, and made the code very readable as to what is happening through its phases of operation.

Unfortunately, for the Euler project problems. Often the general purpose solutions are the slowest. Code has to be written precisely to solve that problem, and quite often that problem only. By taking advantage of the characteristics of the problem, one gets insights and can optimize the algorithm/code. So one can then refactor the code to be optimal, but not always necessarily more readable. (Personally, for code that I'll be expected to maintain over the long run, I'll always pick readable over fast, but that's just my preference.)

So to that end of refactoring to go faster, notice how your code loops over the array multiple times. The first time is to actually generate the contents. The second to reject the odd numbers, and the last to sum up the numbers. Since all that matters is just getting the sum at the end of the run, you can forego of maintaining the array, and just keeping a running sum of all the odd numbers.

def sum_odd_fib_numbers_below max
    first = 1
    second = 2
    fib = first + second
    sum = 1
    while fib <= max
        sum += fib if fib.odd?
        first = second
        second = fib
        fib = first + second
    end
    sum
end

print sum_odd_fib_numbers_below 4000000
F9a9ba6663645458aa8630157ed5e71e

Ants

January 24, 2012, January 24, 2012 20:30, permalink

No rating. Login to rate!

Sorry, the point was to get the sum of all the even Fibonacci numbers...

def sum_even_fib_numbers_below max
    return 0 if max < 2
    first = 1
    second = 2
    fib = first + second
    sum = 2
    while fib <= max
        sum += fib if fib.even?
        first = second
        second = fib
        fib = first + second
    end
    sum
end

print sum_even_fib_numbers_below 4000000
F9a9ba6663645458aa8630157ed5e71e

Ants

January 24, 2012, January 24, 2012 20:46, permalink

No rating. Login to rate!

And getting rid of the ugly corner case check for max < 2, and using the multi-assignment...

def sum_even_fib_numbers_below max
    prev = 1
    fib = 1
    sum = 0
    while fib <= max
        sum += fib if fib.even?
        prev, fib = fib, prev + fib
    end
    sum
end

print sum_even_fib_numbers_below 4000000

Your refactoring





Format Copy from initial code

or Cancel