Here's my solution, written to be easy to understand:
http://gist.github.com/636465
Would it have worked if I'd coded
sum [ n
| n <- [1..]
, n < 1000
, n `isMultipleOf` 3 || n `isMultipleOf` 5
]
?
The way I wrote it is to generate candidates and test, but you don't
have to do it that way.
Here are Ian's solutions:
http://gist.github.com/636525
sol1 *generates* the multiples of 3 with [3,6,..end] instead of testing.
That's good. Why waste time?
sol4 uses accumulators and avoids lists. Lists are expensive.
sol5 uses the fact that there is a pattern to the multiples of 5 that we
want to skip, e.g., we want 5 and 10, but not 15, do want 20 and 25, but
not 30.
sol7 is the real breakthrough. Ian realized that
3 + 6 + 9 + ... + n = 3 (1 + 2 + 3 + ... + n/3).
From Gauss, we know that
1 + 2 + ... + n = n (n+1) / 2.
So it's possible to write a direct formula. sol7 uses that formula and
sum the 3s, sum the 5s, and subtract off the 15s.
So, there are a lot of ways to do these. I definitely learned a lot
doing them different ways.