Mark Pearl

The last few days I began to play around with problem 4 of Euler. I really enjoyed this problem since it dealt with a few functions in F# that I haven’t dealt with in the past.

Problem

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

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

Solution

So I divided the problem up into a few functions…

reverseString simply reverses a string.

isPalindrome converts a number to a string and compares the number forwards to the number in reverse.

ProductOfNumbers is the interesting one for me – basically with my initial attempt I just generated a series of numbers and their product. The issue I was having with this approach was that it is the brute force approach, and I could not rely on the first or last palindrome to be the largest palindrome. To solve the second area of my problem I added an additional field to my solution Tuple which was the sum of x & y, because the largest sum of x & Y will result in the largest product of x & Y

let ProductOfNumbers num minnum =
    (num, num)
    |> Seq.unfold(fun(x,y)->
        match y with        
        | y when y < minnum -> None        
        | y when y = x -> Some((x*y,x,y,x+y), (num,y-1))        
        | _ -> Some((x*y,x,y,x+y), (x-1,y))
        )
    |> Seq.sortBy(fun x -> 
        let _,_,_,key = x     
        -key)

Finally in the res function I filter my results so that I only have palindromes and get the first one, which will be the largest one.

let res = 
        //
        // Generate tuple combinations
        //
        ProductOfNumbers 999 100        
        //
        // Filter out only palidromes
        //
        |> Seq.filter(fun x -> 
            let a,_,_,_ = x 
            isPalidrome a)
        //
        // Display the results
        //
        |> Seq.head
        |> fun x ->         
            let a,b,c,d = x                
            Console.WriteLine(a.ToString() + " = " + b.ToString() + " x " + c.ToString())                

Whole Solution

open System

let reverseString (s:string) = new string(s |> Seq.toArray |> Array.rev)
let isPalidrome (x:int) =  x.ToString() = reverseString(x.ToString())

let ProductOfNumbers num minnum =
    (num, num)
    |> Seq.unfold(fun(x,y)->
        match y with        
        | y when y < minnum -> None        
        | y when y = x -> Some((x*y,x,y,x+y), (num,y-1))        
        | _ -> Some((x*y,x,y,x+y), (x-1,y))
        )
    |> Seq.sortBy(fun x -> 
        let _,_,_,key = x     
        -key)


let res = 
        //
        // Generate tuple combinations
        //
        ProductOfNumbers 999 100        
        //
        // Filter out only palidromes
        //
        |> Seq.filter(fun x -> 
            let a,_,_,_ = x 
            isPalidrome a)
        //
        // Display the results
        //
        |> Seq.head
        |> fun x ->         
            let a,b,c,d = x                
            Console.WriteLine(a.ToString() + " = " + b.ToString() + " x " + c.ToString())                
res

Console.ReadLine()

Conclusion

So I am aware that this does get the correct result, however I would be interested in looking at other approaches to solving this problem in F#. Any feedback / suggestions would be much appreciated.



blog comments powered by Disqus

Want to get my personal insights on what I learn as I learn it? Subscribe now!


/