module Exercise01 where import Test.QuickCheck import qualified Data.Char (isSpace) import Data.List (dropWhileEnd, intercalate) {-H1.1a)-} myPair :: Integer -> Integer -> Integer myPair x y = 2^y * (2 * x + 1) -1 {-H1.1c)-} myFst :: Integer -> Integer myFst p | even (p+1) = myFst (div (p + 1) 2 - 1) | otherwise = div p 2 {-H1.1b)-} mySnd :: Integer -> Integer mySnd p = mySndHelp (div (p+1) ((2 * myFst p) + 1)) mySndHelp :: Integer -> Integer mySndHelp 1 = 0 mySndHelp x = mySndHelp (div x 2) + 1 {-H1.1d)-} prop_myPair :: Integer -> Integer -> Integer -> Property prop_myPair p x y = p >= 0 && x >= 0 && y >= 0 ==> myPair x y == p && 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-} {-MCCOMMENT it might be interesting to note, that a soloution which contains all numbers in a string and selects one by means of list magic would be quite a decent chunk shorter. However, I'm quite sure neither my harddrive nor the space I have in Bitbucket are large enough to handle such a string... Most of this code is quite ugly and I believe would best be rewritten, somthing I somehow don't really have the time for at the moment :( Anyways, enjoy this. -} --todo: find neat soloution numberToEo :: Integer -> String numberToEo n | n < 10 = digitToEo n | n >= 2000 = dropWhileEnd Data.Char.isSpace $ numberToEoH (div n $ 10^oom n) ++ " " ++ oomEo n ++ " " ++ numberToEo' (mod n $ 10^ oom n) | n >= 1000 = dropWhileEnd Data.Char.isSpace $ "mil " ++ numberToEoH (mod n 1000) | otherwise = numberToEoH n --so we don't get trailing "nul"s numberToEo' :: Integer -> String numberToEo' 0 = "" numberToEo' n = numberToEo n --helper function: converts numbers < 1000, this is also quite ugly... numberToEoH :: Integer -> String numberToEoH n = unwords $ filter (\x -> take 3 x /= "nul") $ words $ digitToEoNonUnu (div n 100) ++ "cent " ++ digitToEoNonUnu (mod (div n 10) 10) ++ "dek " ++ digitToEo (mod n 10) --helper function: drops "unu" from things like "unucent", "unudek" (because Esparanto is slightly ugly...) digitToEoNonUnu :: Integer -> String digitToEoNonUnu 1 = "" digitToEoNonUnu x = digitToEo x --convert the oom to Esperanto, this is ugly af, but should at least work (semi-)correctly - a good place to save some tokens, if future me happens to be motivated enough to suceed. oomEo :: Integer -> String oomEo n | n < 1000000 || div n (10^oom n) == 1 = oomEo' n | otherwise = oomEo' n ++ "j" oomEo' :: Integer -> String oomEo' n | a == 63 = "dekiliardo" | a == 60 = "dekiliono" | a == 3 = "mil" | a == 6 = "miliono" | a == 9 = "miliardo" | mod a 6 <= 2 = digitToEo (div a 6) ++ "iliono" | otherwise = digitToEo (div a 6) ++ "iliardo" where a = oom n --calculate the order of magnitude (to the next lowest multiple of 3) oom :: Integer -> Integer oom x = oomH x - mod (oomH x) 3 --get the highest power of 10 oomH :: Integer -> Integer oomH 1 = 0 oomH 0 = -1 oomH x = oomH (div x 10) + 1 {-TTEW-}