Here.
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.
This problem is pretty straightforward, but to get started, I needed to take the first step(s):
- Got the latest F# installed.
- Created an F# project.
- Created a C# xUnit.net test project (another thing I picked up at Code Camp.)
I tried to create an xUnit.net project in F#, but ran into some problem (can't remember what) and decided I was better off focusing my F# mana on the Euler problems than learning xUnit.net in F# and using F#. Doing the unit tests in C# was easy.
So, as a TDD'er, I broke the problem down into chunks I could write tests for:
- I needed a way to identify if numbers were multiples of each other:
public class Problem_001_Tests
{
[Fact] private void Numbers_are_multiples_of_themselves()
{
Assert.True(Problem001.IsMultiple(3, 3));
}
[Fact] private void Any_X_Times_Y_Is_A_Multiple_of_X()
{
Assert.True(Problem001.IsMultiple(3, 3*23));
Assert.True(Problem001.IsMultiple(23, 3 * 23));
}
}
- I implemented this in F#:
#light
namespace Euler
module Problem001
let IsMultiple n x =
x % n = 0
- Comfortable that basic math works, I wanted to try one of the features I really find appealing about F#: sequences:
[Fact] private void AllMultiplesOf3Or5Under1000ShouldInclude525()
{
Assert.True(Problem001.AllMultiplesOfThreeOrFiveLessThan(1000)
.Contains(525));
}
[Fact] private void AllMultiplesOf3Or5Under1000ShouldNotInclude200()
{
Assert.False(Problem001.AllMultiplesOfThreeOrFiveLessThan(200)
.Contains(200));
}
...
let AllMultiplesOfThreeOrFiveLessThan n =
seq {
for x in 1..n - 1 do
if IsMultiple 3 x then yield x
else if IsMultiple 5 x then yield x
}
Sequences seem a lot like IEnumerable<T> functions in C#, which I have been using a lot of.
- And finally, the answer:
[Fact] private void FunctionalAnswerSameAsImperativeAnswer()
{
int accumulator = 0;
foreach (int x in Problem001.AllMultiplesOfThreeOrFiveLessThan(1000))
accumulator += x;
int answer = Problem001.SumOfAllMultiplesOfThreeOrFiveLessThanOneThousand();
Assert.Equal(accumulator, answer);
Console.WriteLine("The answer is: {0}", answer);
}
[Fact] private void TheAnswerIs233168()
{
Assert.Equal(233168, Problem001.SumOfAllMultiplesOfThreeOrFiveLessThanOneThousand());
}
...
let SumOfAllMultiplesOfThreeOrFiveLessThanOneThousand () =
let range = AllMultiplesOfThreeOrFiveLessThan(1000)
Seq.fold (+) 0 range
I like the way you can use the "+" operator as a first class function.
So that's it. Pretty dumb. Once I'd plugged in the answer to Project Euler, I took a look around the forums. My answer is dumb and verbose compared to some of the answers in the forums. Which brings me to an interesting conundrum:
In C#, and production development in general - I consider it poor style to write code that's really "mathy" - Single letter variable names, lots of terse iteration and use of abbreviated keywords. I like to have long descriptive method names and have the "nameable" parts of an algorithm broken out into named methods.
F# takes me the other way. It appeals to the side of me that likes elimination of waste. The side that throws boxes and packaging away as soon as I get something - preferably at the store. Once you understand the above problem, it's really just a one liner (see Project Euler forums.)
The C# (maybe I should say DDD) solution shows the work: You can literally see the steps taken to get the answer - not the program's steps, but the _programmer's_ steps. I think this is very desirable in a program, and will have to make sure I don't lose this in the elegance and sleekness of F#.