homework #1 solution.
authorRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Mon, 15 Dec 2014 14:52:05 +0000 (20:22 +0530)
committerRamakrishnan Muthukrishnan <ram@rkrishnan.org>
Mon, 15 Dec 2014 14:52:27 +0000 (20:22 +0530)
hw1/01-intro.pdf [new file with mode: 0644]
hw1/credit-card.hs [new file with mode: 0644]

diff --git a/hw1/01-intro.pdf b/hw1/01-intro.pdf
new file mode 100644 (file)
index 0000000..e791a68
Binary files /dev/null and b/hw1/01-intro.pdf differ
diff --git a/hw1/credit-card.hs b/hw1/credit-card.hs
new file mode 100644 (file)
index 0000000..9663af5
--- /dev/null
@@ -0,0 +1,90 @@
+{-# OPTIONS_GHC -Wall #-}
+module CreditCard where
+
+{-| reverse list of the digits in a given number n.
+>>> toDigitsRev 1234
+[4,3,2,1]
+>>> toDigitsRev 0
+[]
+>>> toDigitsRev (-20)
+[]
+-}
+
+toDigitsRev :: Integer -> [Integer]
+toDigitsRev n | n <= 0 = []
+           | n < 10 = [n]
+           | otherwise = let (d, m) = n `divMod` 10 in
+                         m : toDigitsRev d
+{-| list of the digits in a given number n.
+>>> toDigits 1234
+[1,2,3,4]
+>>> toDigits 0
+[]
+>>> toDigits (-10)
+[]
+-}
+
+toDigits :: Integer -> [Integer]
+toDigits = reverse . toDigitsRev
+
+{-| double every other digit in a list (from the right).
+>>> doubleEveryOther [8, 7, 6, 5]
+[16,7,12,5]
+>>> doubleEveryOther [1, 2, 3]
+[1,4,3]
+ -}
+doubleEveryOther :: [Integer] -> [Integer]
+doubleEveryOther = reverse . doubleEveryOther' . reverse
+    where
+      doubleEveryOther' :: [Integer] -> [Integer]
+      doubleEveryOther' [] = []
+      doubleEveryOther' [x] = [x]
+      doubleEveryOther' (x:y:ys) = x : 2 * y : doubleEveryOther' ys
+
+doubleEveryOther'' :: [Integer] -> [Integer]
+doubleEveryOther'' xs | even (length xs) = doubleEven xs
+                      | otherwise = doubleOdd xs
+                      where doubleEven [] = []
+                            doubleEven [x] = [2*x]
+                            doubleEven (x:y:ys) = (2*x):y:doubleEven ys
+                            doubleOdd [] = []
+                            doubleOdd (y:ys) = y:doubleEven ys
+{-| sum all the 'digits' in a list.
+>>> sumDigits [16,7,12,5]
+22
+-}
+sumDigits :: [Integer] -> Integer
+sumDigits xs = let pairs = map (`divMod` 10) xs in
+               sum $ map (\(x,y) -> (x + y)) pairs
+{-| sum all the 'digits' in a list.
+>>> sumDigits' [16,7,12,5]
+22
+-}
+
+sumDigits' :: [Integer] -> Integer
+sumDigits' xs = foldr (\x acc -> let (q,r) = x `divMod` 10 in acc + q + r) 0 xs
+
+{-| validate
+>>> validate 4012888888881881
+True
+>>> validate 4012888888881882
+False
+-}
+validate :: Integer -> Bool
+validate n = (== 0) ((`rem` 10) (sumDigits (doubleEveryOther (toDigits n))))
+
+{-| validate'
+>>> validate' 4012888888881881
+True
+>>> validate' 4012888888881882
+False
+-}
+validate' :: Integer -> Bool
+validate' = (== 0) . (`rem` 10) . sumDigits . doubleEveryOther . toDigits
+
+-- tower of hanoi
+type Peg = String
+type Move = (Peg, Peg)
+hanoi :: Integer -> Peg -> Peg -> Peg -> [Move]
+hanoi 0 _ _ _ = []
+hanoi n a b c = hanoi (n - 1) a c b ++ [(a, c)] ++ hanoi (n - 1) b a c