November 1, 2009

It looks like Project Euler is a popular way to study a language, especially if it supports functional programming. I came upon the site as I've been working with Clojure.

Here are some notes on the first problem.

I'll restate the problem 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.

A solution:

First we need a way to determine if a number is a multiple of 3 or 5. For this we remember that there is usually some sort of 'mod' function that returns 0 if a number divides by another without a remainder. Clojure has just a function, mod.

With this at the REPL we can test it out.

```
user> (mod 3 3)
0
user> (mod 10 3)
1
user> (mod 300 3)
0
```

We'll assume the same works for 5 so we'll need a function that returns true if a number is mod 3 or 5.

```
(defn mod3or5? [x]
"Return true if x is divideable by 3 or 5"
(or
(== (mod x 3) 0)
(== (mod x 5) 0)))
```

Next, we'll need some sort of list or collection of all the numbers less than 1000. Poking around with Clojure it doesn't take long to find a function called range. It takes one argument which is the maximum number and returns as list. Note, Clojure calls it a seq or sequence.

For our example, we'll do the following.

```
user> (range 1000)
(0 1 2 3 4 5 6 7 8 9 10 11 ......... 997 998 999)
user>
```

Lastly, we'll need to go through our range and filter out all the numbers that are divide-able by 3 or 5 and add them together.

The first part uses filter which applies a function to a list and returns a new list where only the values that when applied to the function return true are present.

```
user> (filter mod3or5? (range 1000))
(0 3 5 6 9 10 12 15 18 20 21 24 ..... 985 987 990 993 995 996 999)
user>
```

Lastly, we need to add these numbers up. In a functional approach we'll use reduce which will apply a function to a list as it iterates over a list. In this case we want to add so we do the following to get our solution.

```
user> (reduce + (filter mod3or5? (range 1000)))
233168
```