patternMinor
Find biggest palindrome which is the product of two 3-digit numbers
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
isPalindromeis 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^2and999^2-1at 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 _ = Falsemain = 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.