{-# LANGUAGE TemplateHaskell #-} module Exercise01 where import Test.QuickCheck {-H1.1a)-} myPair :: Integer -> Integer -> Integer myPair x y = ((2 ^ y) * ((2 * x) + 1)) - 1 {-H1.1b)-} --Should return y mySnd :: Integer -> Integer mySnd p = countTwoPotencies(div (p+1) ((2*(myFst p))+1)) --Helper functions: determines what potency of 2 this number is (ONLY WORKS FOR POTENCIES OF 2) countTwoPotencies :: Integer -> Integer countTwoPotencies n | n == 1 = 0 | otherwise = 1 + countTwoPotencies(div n 2) {-H1.1c)-} --Should return x myFst :: Integer -> Integer myFst p = div (divWhileEven (p+1) -1) 2 --Helper function: divides a number by two while it is still even, then returns it as soon as it is uneven divWhileEven :: Integer -> Integer divWhileEven n | mod n 2 == 1 = n | otherwise = divWhileEven(div n 2) {-H1.1d)-} prop_myPair :: Integer -> Integer -> Integer -> Property prop_myPair p x y = x >= 0 && y >= 0 && p >= 0 ==> myFst p == x && mySnd p == 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" {-WETT-} {- Helper Function This function counts how many digits the number has after the leading digit (e.g. 10 has 1 digit after, 134 has 2, 4 has 0) -} countZeroes :: Integer -> Integer countZeroes n |n < 10 = 0 |otherwise = 1 + countZeroes(div n 10) {- Helper Function This function calculates the "base" of a number - base being the "main" multiple of 10 of which they are composed. For example, the base of 200 is 100, the base of 5678 is 1000 and the base of 10^7 is 10^6 -} baseCalculator :: Integer -> Integer baseCalculator n |n >= 10^6 = 10^(count - rest) |n >= 1000 = 1000 |n < 10 = 1 |otherwise = 10 * baseCalculator(div n 10) where count = countZeroes n rest = mod count 3 {- Helper Function This function "maps" numbers to the string of their respective base. The assignments are made directly up until 10^12, after which it is possible to generate them systematically. -} expressionMapper :: Integer -> String expressionMapper n |n < 100 = "dek" |n < 1000 = "cent" |n < 10^6 = "mil" |n < 10^9 = "miliono" |n < 10^12 = "miliardo" |rest < 3 = numberToEo quot ++ "iliono" |otherwise = numberToEo quot ++ "iliardo" where count = countZeroes n quot = div count 6 rest = mod count 6 {- Helper functions: Handlers The following functions help with the formatting of different special cases e.g. the pre-appending of "unu" after 10^6 or the fact that multiples before 1000 have the quotient and the base expression together -} prefixHandler :: Integer -> Integer -> String prefixHandler n quot |quot > 1 = if n < 1000 then numberToEo quot else numberToEo quot ++ " " |n >= 10^6 = "unu " |otherwise = "" sufixHandler :: Integer -> Integer -> String sufixHandler n quot |n >= 10^6 && quot /= 1 = "j" |otherwise = "" restHandler :: Integer -> String restHandler rest |rest == 0 = "" |otherwise = " " ++ numberToEo rest {- Main function This functions processes numbers according to cases: |n < 10 : base case: only one digit to process |n == base : the number equals the base (e.g. n = 100): give out the base (with a "unu" if necessary) |quot == 1 : the number equals the base + a rest with a lower base (e.g. 15): same as previous case, together with a recursive call to process the rest |rest == 0 : the number is a multiple of the base without a rest (e.g. 30): process and prepend the quotient to express multiplicity |otherwise : the number is a multiple of the base + a lower base (e.g. 36): same as previous, but process the rest too -} numberToEo :: Integer -> String numberToEo n |n < 10 = digitToEo n |otherwise = prefixHandler n quot ++ expressionMapper n ++ sufixHandler n quot ++ restHandler rest where quot = div n base rest = mod n base base = baseCalculator n {-TTEW-}