Well, this is really a little more complicated and more mathematically than Haskell, so let's look at a possible solution (assuming a decimal system).
The idea is to use div and mod to get the highest and lowest digit of a number. Remember that you can write
(q,r) = n `divMod` m
to get the numbers q and r , so that q * m + r = n with 0 <= r < q . For m = 10 it will be convenient to obtain (for positive n ):
- in
q all but the last digits - in
r last digit
note : I have had this wrong for some time - I hope this is right now - the extreme cases are really complicated.
palindrome :: Integer -> Bool palindrome n = palin n (digits n) where palin x dgts | x < 0 = False | x == 0 = True | x < 10 = dgts == 1 | otherwise = q == x `mod` 10 && palin inner (dgts-2) where inner = r `div` 10 (q,r) = x `divMod` size size = 10^(dgts-1) digits :: Integer -> Integer digits x | x < 10 = 1 | otherwise = 1 + digits (x `div` 10)
Obviously, I did not know the size of your problem, so digits will look for the number of digits:
- digits 5445 = 4
- digits 123 = 3
- ...
The edges include the following:
| x < 0 = False | x == 0 = True | x < 10 = digits == 1
- Obvious negative numbers should not be palindromes
- if all digits are 0, then this is a palindrome
- single-digit numbers are palindromes, if we really only look at length 1 (this was bad for me, since
inner a type like 1011 is one nubmer number 1 )
The rest are based on these observations:
x div 10^(digits-1) = highest digit ( 5445 div 1000 = 5 )x mod 10^(digits-1) = everything, but the highest digit ( 5445 mod 1000 = 445 )x mod 10 = lowest digit ( 5445 mod 10 = 5 )number div 10 = delete the lowest digit ( 5445 div 10 = 544 )
To be safe, you can check it with Quickcheck:
Let me use Quickcheck to test it (should be a good example: D)
module Palindrome where import Test.QuickCheck main :: IO () main = do checkIt palindrome palindrome :: Integer -> Bool palindrome n = palin n (digits n) where palin x dgts | x < 0 = False | x == 0 = True | x < 10 = dgts == 1 | otherwise = q == x `mod` 10 && palin inner (dgts-2) where inner = r `div` 10 (q,r) = x `divMod` size size = 10^(dgts-1) digits :: Integer -> Integer digits x | x < 10 = 1 | otherwise = 1 + digits (x `div` 10) checkIt :: (Integer -> Bool) -> IO () checkIt p = quickCheckWith more (\n -> n < 0 || pn == (reverse (show n) == show n)) where more = stdArgs { maxSuccess = 10000, maxSize = 999999 }
It looks fine:
runghc Palindrom.hs +++ OK, passed 10000 tests.
source share