@Euler[0]

Good news, everyone! My code formatting woes are over. I fixed the funkiness with pre, so I can use that instead of h2 now. pre is nice because it preserves spaces (before, I was using the space character code instead -- it was hideous). I should also be able to extend code past the page margins now. The only downside of all this is that I have to go back and reformat all my old posts now. A small price to pay, all considered.

Anyways, today's subject is Project Euler, which is a series of mathematical problems that can be solved with code. They get pretty hard, so I haven't done a whole lot of them yet. Here's the first one:

Problem 1:
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.

Pretty simple, as would be expected of any "Problem 1." Here's the braindead solution:

sub problem1 {
    $total = 0;
    for (1..999) {
        if ($_ % 3 == 0 or $_ % 5 == 0) {
            $total += $_;
        }
    }
    return $total;
}

Of course, it's appalling to me that this much code is required for such a simple task. So let's golf it down a bit. As you might expect, the if statement can be reduced to a conditional. The definition of $total is also unnecessary, because variables are initialized to zero by default.

sub problem1 {
    $x += ($_ % 3 == 0 or $_ % 5 == 0) ? $_ : 0 for (1..999);
    return $x;
}

The return statement could be replaced with a simple $x, but I'm not really shooting for the lowest character count here. It's just fun to tweak the functional aspects of the code.
Let's do one more:

Problem 2:
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.

You'll find that lots of Project Euler problems deal with large sets of data. This is probably to make it impractical to solve the problems by hand (though to my knowledge, all the problems can be solved manually, given enough time).
Here's my solution:

sub problem2 {
    @fib = (1,1);
    push @fib, $fib[-1] + $fib[-2] for (1..31);
    $x += ($_ % 2) ? 0 : $_ for (@fib);
    return $x;
}

Here we see $_ % 2 being used as a conditional, because zero is false and non-zero is true. Note that this trick could be used in problem 1 as well, but or would have to be changed to and.
This could could definitely used some improvement. The first for loop is a bit of a cheat; I simply used the fact that past 31, the values of the series are greater than four million. It also seems lame to use two for loops when one could probably suffice.
The clever way of doing this problem lies in generating Fibonacci numbers. First, we can observe that only every third Fibonacci number is even. Additionally, the ratio between adjacent numbers is approximately ϕ = 1.618..., or phi. So we can generate even Fibonacci numbers by multiplying the last number by ϕ3. I found that 7 significant figures are enough to ensure accuracy.

sub problem2 {
    for ($i = 2; $i < 4_000_000; $i = int $i * 4.236068 + 0.5) {$x += $i}
    return $x;
}

It's necessary to round the result of the multiplication, since all numbers in the sequence are integers. Unfortunately, Perl does not have a proper rounding function, only a pseudo-floor function. So we add 0.5 to the result and chop off everything after the decimal point to get the rounded result. Much better, don't you think?

I'll be posting more Project Euler problems as I complete them. Happy coding!

Leave a Reply

Theme: Esquire by Matthew Buchanan.