module Homework.Ch01.CreditCards where toDigits :: Integer -> [Integer] toDigits = go [] where go acc 0 = acc go acc n = go (n `mod` 10 : acc) (n `div` 10) revDigits :: [Integer] -> [Integer] revDigits = go [] where go acc (x : xs) = go (x : acc) xs go acc [] = acc toDigitsRev :: Integer -> [Integer] toDigitsRev = revDigits . toDigits doubleEveryOther :: [Integer] -> [Integer] doubleEveryOther = revDigits . go [] where go acc (first : second : rest) = go ((second * 2) : first : acc) rest go acc [last'] = last' : acc go acc [] = acc sumDigits :: [Integer] -> Integer sumDigits digits = foldDigits 0 (+) [y | x <- digits, y <- toDigits x] where foldDigits acc f (x : xs) = foldDigits (f x acc) f xs foldDigits acc _ [] = acc validateWithParens :: Integer -> Bool validateWithParens n = f n `mod` 10 == 0 where f n' = sumDigits (doubleEveryOther (toDigitsRev n')) validateWithDollars :: Integer -> Bool validateWithDollars n = f n `mod` 10 == 0 where f n' = sumDigits $ doubleEveryOther $ toDigitsRev n' validateWithCompose :: Integer -> Bool validateWithCompose n = f n `mod` 10 == 0 where f = sumDigits . doubleEveryOther . toDigitsRev