Project Euler in F# – Problem 36
A number (in general a word) is palindromic when it can be read in the same way from left to right and in the opposite direction, i.e. it is "symmetrical".
According to the definition, a number can be palindromic when written in base10 and not palindromic in base2, but there are some numbers that are palindromic in both bases.
In Project Euler Problem 36 we have to find all these numbers between 1 and 1 million:
The decimal number, 585 = 10010010012 (binary), is palindromic in both bases.
Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2.
(Please note that the palindromic number, in either base, may not include leading zeros.)
To solve this problem we need two helper functions, one to check whether a number is palindromic and another one to convert a number from base10 to base2:
#light
open Microsoft.FSharp.Math
let isPalindromic n =
let chars = n.ToString().ToCharArray()
chars = Array.rev chars
let toBinary (n : BigInt) =
let rec toBinary1 a v =
match v with
| 0I -> a
| _ ->
let q,r = BigInt.DivMod (v,2I)
toBinary1 (r.ToString()::a) q
toBinary1 [] n |> List.reduce_left (^) |> BigInt.Parse
let euler36 = [1I .. 1000000I] |>
List.filter isPalindromic |>
List.filter (fun x -> x |> toBinary |> isPalindromic) |>
List.reduce_left (+)
The first function checks if a number is palindromic by converting it into an array of digits and checking if this array is equal to its reverse one.
Then we have the toBinary function that is based itself on an inner function called (with a lot of originality) toBinary1.
This recursive function uses the list a to store the remainders of the repeated divisions by 2, until the original number is over.
These digits, converted as strings, are joined with ^, the string concatenation operator and eventually the result is converted to a BigInt.
To find the answer to the problem we start with the list of all numbers between 1 and 1 million and take (filter) only the elements which are palindromic in base10.
After this first step, we filter the list again, this time keeping only those numbers that are palindromic when converted to base2.
The last step is the easiest, we only need to sum the numbers left to get the answer to the problem.
Project Euler in F# – Problem 16
This time we are gonna "cheat".
As in Problem 20 we have to sum the digits of a number, so we can just copy and paste the whole code and edit a single line to have a working solution.
The problem says:
2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 2^1000?
The only difference between this exercise and the last one is the number to evaluate.
However, as for the factorial, F# already provides us with a native function for the powers of a numbers, so the final code will be:
#light
open Microsoft.FSharp.Math.BigInt
let rec digits n =
match n with
| n when n < 10I -> n
| n ->
let x, y = divmod n 10I
y + digits x
let answer = digits (pow 2I 1000I)
If you compare this exercise with the last one, you can see that we actually changed one line, i.e. line 11.
Do you really want me to explain this code?
Project Euler in F# – Problem 20
Project Euler's Problem 20 was trickier than I expected.
I'm quite sure that there is a smart solution, but there is also a "dumb" one and this is the one I'm going to present you.
The problem says:
n! means n × (n ? 1) × ... × 3 × 2 × 1
Find the sum of the digits in the number 100!
Evaluating the factorial is straightforward in any functional language, but it is even easier in F# since the language already provides us with the factorial function.
As usual, let's show the code and then analyze it:
#light
open Microsoft.FSharp.Math.BigInt
let rec digits n =
match n with
| n when n < 10I -> n
| n ->
let x, y = divmod n 10I
y + digits x
let answer = digits (factorial 100I)
The open directive at line 2 permits the use of the BigInt namespace, which is needed when working with very large numbers.
Then we have the code to sum the digits of a number, which is easily implemented with pattern matching.
The algorithm is based on the modulus operator, since taking the last digit of a number is equivalent to taking the remainder of the number itself divided by 10 (in a base 10 system).
Hence, we take the last digit and recursively apply the same function to the rest of the number, until there is only one digit left, i.e. the number is less than 10.
This operation is done by the divmod function, which returns the integer quotient and the remainder as a couple (x, y).
You may have noticed that there is a capital "I" after each number. That letter stands for Big Integer and is used to distinguish them from normal integers.
It's done, we just have to apply the digits function to the output of factorial 100I.
Why did I call this solution "dumb"?
Because I had to compute 100! (which is a number with 158 digits) and then sum its digits, but this solution is not feasible if the number becomes much larger.
I think that there should be some mathematical trick to do the same job, but I don't know it.
Does anybody have a different approach to suggest?


