#### 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]