Tuesday, May 18, 2010

Project Euler's seventeenth problem wants to know:

How many letters would be needed to write all the numbers in words from 1 to 1000?

For example, in the British style, one would write out 256 as "two hundred and fifty-six". We are told not to count spaces and hyphens so 21 letters are needed for this number.

My approach is to decompose a number into a tuple containing the number of thousands, hundreds, tens and ones in the number. However, to make things simpler for me I chose to special case all the numbers under 20 since their spelling is a irregular. That is, instead of saying something like "ten plus one" we say "eleven". It is easier to break that out at this stage in the problem.

Here is my F# code to decompose a number:

let decompose x =
    let thousands x = (x/1000)*1000
    let hundreds  x = ((x - thousands x)/100)*100
    let tens      x =
        let temp = ((x - thousands x - hundreds x)/10)*10
        match temp with
        | _ when 0 < temp && temp < 20 -> 0
        | _                            -> temp
    let ones      x = (x - thousands x - hundreds x - tens x)
    (thousands x, hundreds x, tens x, ones x)

Just to show how this works, here is the decomposition of some example numbers:

> decompose 256;;
val it : int * int * int * int = (0, 200, 50, 6)

> decompose 512;;
val it : int * int * int * int = (0, 500, 0, 12)

The next piece of the puzzle is to take a section of the decomposed number and return the number of letters used to write it out:

let letters x =
    match x with
    |    1 ->  3    // one
    |    2 ->  3    // two
    |    3 ->  5    // three
    |    4 ->  4    // four
    |    5 ->  4    // five
    |    6 ->  3    // six
    |    7 ->  5    // seven
    |    8 ->  5    // eight
    |    9 ->  4    // nine
    |   10 ->  3    // ten
    |   11 ->  6    // eleven
    |   12 ->  6    // twelve
    |   13 ->  8    // thirteen
    |   14 ->  8    // fourteen
    |   15 ->  7    // fifteen
    |   16 ->  7    // sixteen
    |   17 ->  9    // seventeen
    |   18 ->  8    // eighteen
    |   19 ->  8    // nineteen
    |   20 ->  6    // twenty
    |   30 ->  6    // thirty
    |   40 ->  5    // forty
    |   50 ->  5    // fifty
    |   60 ->  5    // sixty
    |   70 ->  7    // seventy
    |   80 ->  6    // eighty
    |   90 ->  6    // ninety
    |  100 -> 10    // one hundred
    |  200 -> 10    // two hundred
    |  300 -> 12    // three hundred
    |  400 -> 11    // four hundred
    |  500 -> 11    // five hundred
    |  600 -> 10    // six hundred
    |  700 -> 12    // seven hundred
    |  800 -> 12    // eight hundred
    |  900 -> 11    // nine hundred
    | 1000 -> 11    // one thousand
    |    _ ->  0

Now, given a decomposed number, compute the total number of letters used to write it out:

let length (a, b, c, d) =
    match (a, b, c, d) with
    | (_, _, 0, 0) -> letters a + letters b
    | (0, 0, _, _) -> letters c + letters d
    | (_, _, _, _) -> letters a + letters b + letters c + letters d + 3

Note that the 3 in the last case is to account for the word "and".

Finally, to find out how many letters are needed to write out the numbers from one to 1000:

{1..1000} |> Seq.map decompose |> Seq.map length |> Seq.sum |> printfn "count = %A"

Monday, May 17, 2010

Speaking of goofy pictures, I should mention that I used AutoDesk // LABSProject // DRAW to create the images in my previous post.
Problem 16 of Project Euler:

What is the sum of the digits of the number 21000?

This is a pretty straightforward problem to solve. I don't even get to draw any goofy pictures to make the logic clear.

The idea is to compute the number, split it into its individual digits and add them all together. Given a number n here's the F# code to extract each digit:

let rec digits n =
    seq {
        if n > 0I then
            yield n%10I
            yield! digits (n/10I)
    }

The desired answer is:

digits (2I ** 1000) |> Seq.sum |> printfn "%A"

Friday, May 14, 2010

Problem 15 of Project Euler asks:

Starting in the top left corner in a 20 by 20 grid, how many routes are there to the bottom right corner?

Without getting into complicated proofs I want to present some ideas that lead me to a solution for this problem.

First, suppose that we want to compute the number of paths from point A to point C and we know that all paths pass through point B. Say that a quick count shows there are m paths from A to B and n paths from B to C. Here is my goofy drawing showing the paths:

I think it's pretty obvious that there are mxn paths from A to C through B. Keep this in mind, it will be useful later on.

In general, when tackling a problem like this, I like to start by examining simpler versions of the same problem to see if I can come up with a general solution which I can then apply to the specific problem. I started by thinking about the problem on a 1 by 1 grid. After much thought it occurred to me that I could use a symmetry argument. If I consider all the midpoints along the line from the top right corner to the lower left corner then the number of paths from the start to the midpoint must be the same as the number of paths from the midpoint to the end. Here's a picture showing the paths to one of the midpoints in the grid:
In this diagram, the dotted line shows the axis of symmetry of the square. There are two midpoints (although I've only labelled the first). There is only one path from A to B and so there is one path from B to C. To find the total number of paths from A to C we add the number of paths from A to C through each midpoint. In this case it is 12 + 12 = 2. We are using the first idea mentioned above in this special, symmetrical, case.

Fair enough. Lets take a look at the 2 by 2 grid:
In this case we have three midpoints and I am just showing that there are two paths to the center one. By inspection we can see that there is only one path from A to the other midpoints and so the total number of path is 12 + 22 + 12 = 6. This, by the way, is a nice sanity check since it matches the answer given for a 2 by 2 grid in the statement of the problem.

I'm already starting to see a pattern here but just to really nail it down let's think about the 3 by 3 grid:
Now we have four midpoints to consider. As before, there is one path to each of the outside midpoints and we can see three paths to the each of the inside midpoints. We compute the total number of paths from A to C as 12 + 32 + 32 + 12 = 20.

Suppose we just look at the number of paths to the midpoints for each of the three cases I have presented here. Stacking them up in a provocative manner we see this:

   1 1 
  1 2 1
 1 3 3 1

To me this looks like Pascal's Triangle. And since I don't have to prove anything I'm just going to assume that it is. So, if I was to count the paths to each midpoint in a 4 by 4 grid I would see:

1 4 6 4 1

And so on. If I get the right answer then I'll know that my hunch is correct.

According to the Wikipedia article referenced above, the ith entry in the nth row of Pascal's triangle is:


So, with this formula, we have all the pieces necessary to solve this problem. To spell it out, the number of paths from the top left corner of the grid to the bottom right corner (with no backtracking) is sum of the squares of the coefficients of the nth row of Pascal's triangle. To compute this number I use a couple of helper functions. Here is a factorial:

let factorial n = Seq.fold (*) 1I {1I..n}

Note that I could have used the built in factorial function but since I am using these problems as a learning experience it makes sense to write my own (or at least it seemed to make sense at the time!).

Here's how we can compute n choose i:

let choose n i = (factorial n)/((factorial i)*(factorial (n-i)))

With this we can create a sequence consisting of the entries in the nth row of Pascal's triangle:

let pascal n =
    seq {
        for i in 0I..n -> choose n i
    }

The final step is to perform the actual computation:

pascal 20I |> Seq.map (fun i -> i*i) |> Seq.sum |> printfn "sum = %A"

Done!

Given the right insight the actual code was pretty easy.

Wednesday, May 05, 2010

Time for another Project Euler post. Problem fourteen asks you to:

Find the longest sequence using a starting number under one million.

Given a start number xn the next entry in the sequence is given by:


You can find a nice discussion of this sequence in Wikipedia as the Collatz Problem. In F# this code will generate the sequence from a given starting value:


let rec sequence n =
    seq {
        yield n;
        match n with
        | 1ul -> ()
        | _ when n%2ul = 0ul -> yield! sequence (n/2ul)
        | _ when n%2ul = 1ul -> yield! sequence (3ul*n + 1ul)
    }


Then I can create a tuple containing the sequence starting value and the sequence length as follows:


let length n =
    (sequence n |> Seq.length, n)


So when I want to find the longest sequence I can write:


seq { 1ul..999999ul} |> Seq.map length |> Seq.max |> printfn "longest = %A"


Interestingly, the Seq.max function will just use the first entry in the tuple for its comparison. This means I don't have to clutter my code with special handling to extract the length information from the sequence of tuples. Obviously I got lucky when I put together the tuple and had the length come before the seed value.