HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Find biggest palindrome which is the product of two 3-digit numbers

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
thenumbersproductbiggestpalindrometwofindwhichdigit

Problem

isPalindrome :: Integer -> Bool
isPalindrome n = reverse x == x
    where x = show n 

is3x3 :: Integer -> Bool
is3x3 n = any (\x -> cond1 x && cond2 x) [101..999]
    where
        cond1 x = n `mod` x == 0
        cond2 x = length (show $ n `div` x) == 3

main = print $ head [p | p <- [999^2,999^2-1..], isPalindrome p, is3x3 p]


I have some doubts about the code I wrote:

  • isPalindrome: is it ok or is it better to keep dividing by 10, storing the remainder in a list and check if list is equal to the reversed self?



  • is3x3: is it a good practice to declare functions inside functions? Is there a better way to write the function?



  • how to delete the parentheses in cond2? $ doesn't work because of ==



  • [999^2,999^2-1..]:



  • is Haskell smart and calculates 999^2 only once, subtracting 1 every time? Or does it compute 999^2-x for each xth+1 element of the list?



  • is there a better way to write this list?



  • is it better to put the end of the list (in this case 10001) or it doesn't matter in terms of performance? I know lists are lazy but ...

Solution


  • isPalindrome is ok here, no need to make it faster.



-
In functional programming functions are everywhere, even inside other functions and this is ok. Using ViewPatterns extension it is possible to rewrite is3x3 as:

is3x3 n = any cond [101..999]
    where
        cond (divMod n -> (d, 0)) = 99 < d && d <= 999
        cond _ = False


-
I don't know any readable way to rewrite cond2 without parenthesis.

  • Haskell is smart enough to calculate 999^2 and 999^2-1 at compile time. In terms of performance, if you don't specify end of the list there will be no checks for the end of the list at runtime (which is good in this case).



Using Integer is justified only for big numbers, in your case using Int is enough and could be a bit faster.

Here is another solution:

main = print $ maximum
  [ x * y :: Int
  | x  reverse $ show $ x * y
  ]

Code Snippets

is3x3 n = any cond [101..999]
    where
        cond (divMod n -> (d, 0)) = 99 < d && d <= 999
        cond _ = False
main = print $ maximum
  [ x * y :: Int
  | x <- [999, 998 .. 100]
  , y <- [x, x-1 .. 100]
  , (==) <*> reverse $ show $ x * y
  ]

Context

StackExchange Code Review Q#124625, answer score: 2

Revisions (0)

No revisions yet.