module Exercise01 where import Test.QuickCheck ((==>), Property) {-H1.1a)-} myPair :: Integer -> Integer -> Integer myPair x y | x >= 0 && y >= 0 = 2^y * (2*x + 1) - 1 {-H1.1b)-} mySnd :: Integer -> Integer mySnd n = mySndHelper (n + 1) 0 mySndHelper :: Integer -> Integer -> Integer mySndHelper n xCarry -- count the divisions by two | even n = mySndHelper (div n 2) (xCarry + 1) -- as soon as only the term (2y + 1) is left, the answer is the number of divisions | odd n = xCarry prop_mySnd :: Integer -> Integer -> Property prop_mySnd x y = x >= 0 && y >= 0 ==> mySnd (myPair x y) == y {-H1.1c)-} myFst :: Integer -> Integer myFst n | n >= 0 = myFstHelper (n + 1) myFstHelper :: Integer -> Integer myFstHelper n -- when x is greater than 0, the term (2^y)(2x+1) is even | even n = myFstHelper (div n 2) -- as soon as y is 0, the term simplifies to (2x+1) and is odd | odd n = div (n - 1) 2 prop_myFst :: Integer -> Integer -> Property prop_myFst x y = x >= 0 && y >= 0 ==> myFst (myPair x y) == x {-H1.1d)-} prop_myPair :: Integer -> Integer -> Integer -> Property prop_myPair n x y = n >= 0 && x >= 0 && y >= 0 ==> n == myPair x y {-H2-} digitToEo :: Integer -> String digitToEo 0 = "nul" digitToEo 1 = "unu" digitToEo 2 = "du" digitToEo 3 = "tri" digitToEo 4 = "kvar" digitToEo 5 = "kvin" digitToEo 6 = "ses" digitToEo 7 = "sep" digitToEo 8 = "ok" digitToEo 9 = "nau" --this is the implementation for n < 10^6, it is kept only for verification numberToEoNaive :: Integer -> String numberToEoNaive n | n < 10 = digitToEo n | n == 10 = "dek" | n == 100 = "cent" | n == 1000 = "mil" | n `mod` 1000 == 0 && n < 1000000 = numberToEoNaive (n `div` 1000) ++ " " ++ numberToEoNaive 1000 | n `mod` 100 == 0 && n < 1000 = numberToEoNaive (n `div` 100) ++ numberToEoNaive 100 | n `mod` 10 == 0 && n < 100 = numberToEoNaive (n `div` 10) ++ numberToEoNaive 10 | n < 100 = numberToEoNaive (n - (n `mod` 10)) ++ " " ++ numberToEoNaive (n `mod` 10) | n < 1000 = numberToEoNaive (n - (n `mod` 100)) ++ " " ++ numberToEoNaive (n `mod` 100) | n < 1000000 = numberToEoNaive (n - (n `mod` 1000)) ++ " " ++ numberToEoNaive (n `mod` 1000) -- 169 tokens {-WETT-} unitBase :: Integer -> String unitBase 1 = "dek" unitBase 2 = "cent" unitBase 3 = "mil" unitBase unit = (if unit <= 9 then "m" else numberToEo $ div unit 6) ++ if mod unit 6 == 0 then "iliono" else "iliardo" addUnits :: Integer -> Integer -> String addUnits 0 _ = "" addUnits value 0 = digitToEo value addUnits 1 unit | unit <= 3 = unitBase unit addUnits value unit = numberToEo value ++ (if unit <= 2 then "" else " ") ++ unitBase unit ++ if value > 1 && unit > 3 then "j" else "" numberToEoHelper :: Integer -> Integer -> String numberToEoHelper 0 _ = "" numberToEoHelper n carriedUnits = unwords $ filter (/= "") [numberToEoHelper (div n divisor) nextCarriedUnits, addUnits (mod n divisor) carriedUnits] where nextCarriedUnits = if carriedUnits <= 2 then carriedUnits + 1 else carriedUnits - mod carriedUnits 3 + 3 divisor = 10 ^ (nextCarriedUnits - carriedUnits) numberToEo :: Integer -> String numberToEo n = if n < 10 then digitToEo n else numberToEoHelper n 0 {-TTEW-}