« back

The First Problem I Solved Using Clojure

01 Nov 2012

Spoiler Alert! Problem one from Project Euler explained.

This week I am working on solving problems from Project Euler using Clojure. The first problem is this...

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.

The first thing I did was read through the problem and break it into a rough draft of small part in some kind of procedure order. It looked like this...

 1     for 3
 2     ;inc 
 3     * n 3
 4     ? # < 1000
 5     cond- yes- into list
 6         no - break loop
 7             add  to list
 8             same for 5
 9             add two lists
10     

I then went back to the koans to look for patterns that I was trying to create. I then also looked at the docs for methods that I thought I would want to use. After that, things were looking and feeling too complicated and I decided to come up with a new plan. It looked like this...

 1         new plan ->
 2          range  up to 1000 inclusive
 3          take the #, divide by (3 or 5) if there is no remainder, 
 4          add to multiples list,
 5          do the next number
 6 
 7              need to put this in a list or set(filter multiple-of-three (range 1000))
 8              need to put this in a list or set(filter multiple-of-five (range 1000))
 9              then
10     

By the time I got to the last line of that plan, I had a new plan...

1     new new plan -> find multiples of 2 numbers (it can take 2 args we will give 3 and 5)
2         then we will have a range 1000
3         if multiple of n
4             put into list
5         if mult of f
6             put into list
7             add up #s in list.
8     

Alright, So I started with a test...

1     (it "should return the number if the passed in number is a multiple of the second passed in number"
2            (should= 10 (multiple-of-number 10 5)))
3            
4            ;and the function
5            (defn multiple-of-number [number multiple-candidate]
6              (if (true? (= 0 (rem number multiple-candidate)))
7                number))
8     

And the next test...

 1      (it "should be able add up a list of multiples"
 2          (should= 1997 (sum-of-the-multiples 999 998)))
 3          
 4          ;and the method. 
 5          (defn sum-of-the-multiples [number1 number2]
 6            (reduce + 
 7              (filter (fn [index]
 8                        (or (multiple-of-number index number1) (multiple-of-number index number2)))
 9                (range 1 1000))))
10      

That little guy packs a big punch! Now I ended up getting the final number by passing 3 and 5 into my test as the arguments and then passing the wrong number as the argument to should. Now that I am writing this, I should really change this function to print out the answer. Let's make it better.

 1     (it "should be able add up a list of multiples"
 2         (should= "233168" (sum-of-the-multiples 3 5)))
 3         
 4         ;and the soloution
 5         (defn sum-of-the-multiples [number1 number2]
 6           (pr-str (reduce +
 7             (filter (fn [index]
 8                       (or (multiple-of-number index number1) (multiple-of-number index number2)))
 9               (range 1 1000)))))
10     

Sweet refactor! :)

comments powered by Disqus