# Project Euler – Problem 4 Solution

Yan Cui

I help clients go faster for less using serverless technologies.

#### Problem

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 x 99.

Find the largest palindrome made from the product of two 3-digit numbers.

#### Solution

```open System.Linq

let isPalindromic n =
let charArray = n.ToString().ToCharArray()
let revCharArray = Array.rev charArray
charArray.SequenceEqual(revCharArray)

let numbers = [100..999]
let products = numbers |> List.collect (fun x -> numbers |> List.map (fun y -> x * y))
let maxPalindromic = products |> Seq.filter isPalindromic |> Seq.max
```

In my solution above, I first built a function to check whether a given number is palindromic by comparing the original and reversed char array representing the number and see if they’re the same, i.e. 9009 is represented by the char array [‘9′;’0′;’0′;’9’], and the reversed array is still [‘9′;’0′;’0′;’9’].

Notice how I used the Array.rev function in the isPalindromic function, it returns a new array with all the elements in reverse order. Another thing you might have noticed in this function is that I used the Enumerable.SequenceEqual Linq extension method to compare the two arrays, as I’ve mentioned before, with F# being a first class citizens of the .Net family you’re free to use whatever CLR library of your choice.

The rest of the solution might be relatively straight forward, however, you might be wondering what the List.collect function does. Like the List.map function, it applies a function to each element in the list, except that each element produces a list and all these lists are concatenated into a final list.

Now let’s see how the two differs, say we have a list of numbers from 1 to 10, and I want to find out the Cartesian product of the list multiplied by itself, i.e. 1 * 1, 1 * 2, … 1 * 10, 2 * 1, 2 * 2… 10 * 10:

```let numbers = [1..10]

// List.map returns an array of array containing results of 1 *  [1..10], 2 * [1..10], etc.
numbers |> List.map (fun x -> numbers |> List.map(fun y -> x * y));;
val it : int list list =
[[1; 2; 3; 4; 5; 6; 7; 8; 9; 10];
[2; 4; 6; 8; 10; 12; 14; 16; 18; 20];
[3; 6; 9; 12; 15; 18; 21; 24; 27; 30];
[4; 8; 12; 16; 20; 24; 28; 32; 36; 40];
[5; 10; 15; 20; 25; 30; 35; 40; 45; 50];
[6; 12; 18; 24; 30; 36; 42; 48; 54; 60];
[7; 14; 21; 28; 35; 42; 49; 56; 63; 70];
[8; 16; 24; 32; 40; 48; 56; 64; 72; 80];
[9; 18; 27; 36; 45; 54; 63; 72; 81; 90];
[10; 20; 30; 40; 50; 60; 70; 80; 90; 100]]

// List.collect returns a 1-dimensional array instead
numbers |> List.collect (fun x -> numbers |> List.map (fun y -> x * y));;
val it : int list =
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10; 2; 4; 6; 8; 10; 12; 14; 16; 18; 20; 3; 6; 9;
12; 15; 18; 21; 24; 27; 30; 4; 8; 12; 16; 20; 24; 28; 32; 36; 40; 5; 10; 15;
20; 25; 30; 35; 40; 45; 50; 6; 12; 18; 24; 30; 36; 42; 48; 54; 60; 7; 14;
21; 28; 35; 42; 49; 56; 63; 70; 8; 16; 24; 32; 40; 48; 56; 64; 72; 80; 9;
18; 27; 36; 45; 54; 63; 72; 81; 90; 10; 20; 30; 40; 50; 60; 70; 80; 90; 100]
```

1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop for quickly levelling up your serverless skills.
2. Do you want to know how to test serverless architectures with a fast dev & test loop? Check out my latest course, Testing Serverless Architectures and learn the smart way to test serverless.
3. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.
4. Join my community on Discord, ask questions, and join the discussion on all things AWS and Serverless.

### 2 thoughts on “Project Euler – Problem 4 Solution”

1. my solution:
let reverseNumber n =
let rec loop acc = function
|0 -> acc
|x -> loop (acc * 10 + x % 10) (x/10)
loop 0 n

let isPalindrome = function
| x when x = reverseNumber x -> true
| _ -> false

let max =[for a in 100 .. 999 do
for b in 100 .. 999 do yield a*b]
|> Seq.filter (fun x -> isPalindrome x)
|> Seq.max