A few days ago, I presented a solution for Project Euler problem four that I didn't really like. The challenge of problem four is to write a function that determines whether a number is a palindrome, that is, whether it reads the same backward as forward. When presented with that challenge, I took an approach that I feel is a bit of a cop-out: converting the number to a string, reversing the string and comparing the result. This felt somehow wrong because I'm not really solving the problem in a mathematical way. So, I'm declaring a mulligan. Below is a new function which properly performs the math necessary to reverse a base-10 number.
let reverse n =
let rec loop x res =
if x = 0 then res
else loop (x/10) (res*10 + (x%10))
loop n 0
let isPalindrome n =
n = reverse n
Our original list comprehension below still works properly with the new isPalindrome function.
[ for x in 100..999
for y in 100..999
when isPalindrome(x*y) -> x*y ] |> toLargest
This solution is twice as fast as the original string-based solution. In addition, I'd argue that the tail-recursive loop is at least four times as beautiful.