1 {-# OPTIONS_GHC -Wall #-}
2 module CreditCard where
4 {-| reverse list of the digits in a given number n.
13 toDigitsRev :: Integer -> [Integer]
14 toDigitsRev n | n <= 0 = []
16 | otherwise = let (d, m) = n `divMod` 10 in
18 {-| list of the digits in a given number n.
27 toDigits :: Integer -> [Integer]
28 toDigits = reverse . toDigitsRev
30 {-| double every other digit in a list (from the right).
31 >>> doubleEveryOther [8, 7, 6, 5]
33 >>> doubleEveryOther [1, 2, 3]
36 doubleEveryOther :: [Integer] -> [Integer]
37 doubleEveryOther = reverse . doubleEveryOther' . reverse
39 doubleEveryOther' :: [Integer] -> [Integer]
40 doubleEveryOther' [] = []
41 doubleEveryOther' [x] = [x]
42 doubleEveryOther' (x:y:ys) = x : 2 * y : doubleEveryOther' ys
44 doubleEveryOther'' :: [Integer] -> [Integer]
45 doubleEveryOther'' xs | even (length xs) = doubleEven xs
46 | otherwise = doubleOdd xs
47 where doubleEven [] = []
48 doubleEven [x] = [2*x]
49 doubleEven (x:y:ys) = (2*x):y:doubleEven ys
51 doubleOdd (y:ys) = y:doubleEven ys
52 {-| sum all the 'digits' in a list.
53 >>> sumDigits [16,7,12,5]
56 sumDigits :: [Integer] -> Integer
57 sumDigits xs = let pairs = map (`divMod` 10) xs in
58 sum $ map (\(x,y) -> (x + y)) pairs
59 {-| sum all the 'digits' in a list.
60 >>> sumDigits' [16,7,12,5]
64 sumDigits' :: [Integer] -> Integer
65 sumDigits' xs = foldr (\x acc -> let (q,r) = x `divMod` 10 in acc + q + r) 0 xs
68 >>> validate 4012888888881881
70 >>> validate 4012888888881882
73 validate :: Integer -> Bool
74 validate n = (== 0) ((`rem` 10) (sumDigits (doubleEveryOther (toDigits n))))
77 >>> validate' 4012888888881881
79 >>> validate' 4012888888881882
82 validate' :: Integer -> Bool
83 validate' = (== 0) . (`rem` 10) . sumDigits . doubleEveryOther . toDigits
87 type Move = (Peg, Peg)
88 hanoi :: Integer -> Peg -> Peg -> Peg -> [Move]
90 hanoi n a b c = hanoi (n - 1) a c b ++ [(a, c)] ++ hanoi (n - 1) b a c