## Project Euler in F# – Problem 55

As in the last post, in the description of Project Euler problem 55 there is a detailed step-by-step solution of the problem itself and we just have to write the F# code to perform the tasks.

The only thing that I really had to understand is the definition of *Lychrel numbers*:

If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.

Not all numbers produce palindromes so quickly. For example,

349 + 943 = 1292,

1292 + 2921 = 4213

4213 + 3124 = 7337That is, 349 took three iterations to arrive at a palindrome.

Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).

Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.

How many Lychrel numbers are there below ten-thousand?

As usual, it is suggested to break down the problem into little pieces that can be easily solved with a few lines of code each.

First, we need a function to reverse an integer and another one to check whether a number is palindromic, i.e. it is equal to its reverse.

Then we define a function that will be used during each iteration to take a number and sum it with its reverse. This new number is the one that will be checked next for being a palindrome inside the *isLychrel* function.

If we found a palindrome then the number under testing is not a *Lychrel*, otherwise we can start the next iteration up to a maximum of 50 times. If we hit this limit then we can conclude the number is a *Lychrel*.

We have now all the pieces required to answer the original question. Just take all numbers smaller then 10000, filter the *Lychrel* ones and count them:

#light let reverse n = n.ToString().ToCharArray() |> Array.rev |> Array.map (fun x -> x.ToString()) |> Array.reduce_left (^) |> bigint.Parse let isPalindromic n = n = reverse n let reverseAndAdd n = n + reverse n let isLychrel n = let rec isLychrelIter n i = match i with | 50 -> true | _ -> let r = reverseAndAdd n if isPalindromic r then false else isLychrelIter r (i+1) isLychrelIter n 1 let answer = [1I .. 10000I] |> Seq.filter (fun x -> isLychrel x) |> Seq.length

MattDecember 18th, 2008 - 06:14

Nice work!

3 quick things:

You can extend the String module with a “reverse” method since string implements Seq:

module String =

let reverse (s : string) =

new string(s |> Array.of_seq |> Array.rev)

Then your reverse method can be written more concisely:

let reverse (n : Math.BigInt) =

n |> string |> String.reverse |> bigint.Parse

Also, for the filter at the end, you can just write it as:

|> Seq.filter isLychrel