module AnswersExam where import Test.QuickCheck import Data.Char import Data.List import Data.Maybe import Text.Show.Functions ------------------------------------------------------------------------------------ -- 1. -- a. (+.), (-.) :: Char -> Int -> Char x +. k = chr ((ord x + k) `mod` 256) x -. k = chr ((ord x - k + 256) `mod` 256) -- b. encryptC :: Int -> String -> String encryptC k s = [ x +. k | x <- s ] decryptC :: Int -> String -> String decryptC k s = [ x -. k | x <- s ] -- c. prop_EncryptDecryptC k s = decryptC k (encryptC k s) == s -- d. instance Arbitrary Char where arbitrary = do x <- choose (0,255) return (chr x) coarbitrary = coarbitrary . ord -- e. common :: String -> String common = take 10 . map snd . reverse . sort . map (\cs -> (length cs, head cs)) . group . sort -- f. crack :: FilePath -> String -> IO String crack file message = do txt <- readFile file let cs = common txt score s = length [ c | c <- s, c `elem` cs ] let k = head . map snd . reverse . sort $ [ (score s', k) | k <- [0..255], let s' = decryptC k message ] return (decryptC k message) -- g. encryptV :: [Int] -> String -> String encryptV key s = [ x +. k | (x,k) <- s `zip` cycle key ] decryptV :: [Int] -> String -> String decryptV key s = [ x -. k | (x,k) <- s `zip` cycle key ] prop_EncryptDecryptV key s = not (null key) ==> decryptV key (encryptV key s) == s ------------------------------------------------------------------------------------ -- 2. someReplies = [ [(1,"very good"), (3,"bad"), (4,"okay")] , [(2,"good"), (3,"bad"), (4,"good"), (5,"difficult")] , [(4,"okay"), (5,"very difficult")] ] -- a. aReply :: Reply aReply = [(1,"very good"), (3,"bad"), (4,"okay")] type Reply = [(Int,String)] someReplies :: [Reply] -- b. validReply :: Reply -> Bool validReply ans = qs == nub qs where qs = [ q | (q,_) <- ans ] -- c. questions :: [Reply] -> [Int] questions = sort . nub . map fst . concat -- d. answers :: Int -> [Reply] -> [String] answers q rs = [ a | r <- rs, (q',a) <- r, q == q' ] -- e. summary :: [Reply] -> [(Int,[(Int,String)])] summary rs = [ (q, counts (answers q rs)) | q <- questions rs ] where counts = reverse . sort . map (\as -> (length as, head as)) . group . sort -- f. summarize :: [Reply] -> IO () summarize rs = putStr $ unlines $ [ "Q" ++ show q ++ ": " ++ unwords [ show (n*100 `div` tot) ++ "% " ++ s | (n,s) <- ans ] | (q,ans) <- summary rs , let tot = sum [ n | (n,_) <- ans ] ] -- g. mild :: [Reply] -> [Reply] mild rs = [ [ (q, unwords [ w | w <- words a, w /= "very" ]) | (q,a) <- r ] | r <- rs ] ------------------------------------------------------------------------------------ -- 3. type Var = String data Prop = Var Var | And Prop Prop | Not Prop | Bool Bool deriving ( Eq, Show ) -- a. orr, impl :: Prop -> Prop -> Prop x `orr` y = Not (Not x `And` Not y) x `impl` y = Not x `orr` y -- b. vars :: Prop -> [Var] vars (Var s) = [s] vars (p `And` q) = vars p `union` vars q vars (Not p) = vars p vars (Bool b) = [] -- c. prop_VarsUnique p = nub xs == xs where xs = vars p -- e. instance Arbitrary Prop where arbitrary = sized arbProp where arbProp n = frequency [ (1, do s <- elements ["x","y","z"] return (Var s)) , (1, do b <- arbitrary return (Bool b)) , (n, do p <- arbProp (n `div` 2) q <- arbProp (n `div` 2) return (p `And` q)) , (n, do p <- arbProp (n-1) return (Not p)) ] -- f. type Env = Var -> Bool eval :: Env -> Prop -> Bool eval env (Var v) = env v eval env (p `And` q) = eval env p && eval env q eval env (Not p) = not (eval env p) eval env (Bool b) = b -- f'. simplify :: Prop -> Prop simplify (Not p) = simp (Not (simplify p)) simplify (p `And` q) = simp (simplify p `And` simplify q) simplify p = p simp :: Prop -> Prop simp (Bool False `And` q) = Bool False simp (p `And` Bool False) = Bool False simp (Bool True `And` q) = q simp (p `And` Bool True) = p simp (Not (Not p)) = p simp (Not (Bool b)) = Bool (not b) simp p = p -- g. prop_SimplifySame env p = eval env p == eval env (simplify p) prop_SimplifySimple p = not (simple p') || p' `elem` [ Bool False, Bool True ] where p' = simplify p simple :: Prop -> Bool simple (Bool _) = True simple (p `And` q) = simple p || simple q simple (Not p) = simple p simple (Var s) = False -- h. set :: Var -> Bool -> Env -> Env set x b env y | x == y = b | otherwise = env y allEnvs :: [Var] -> [Env] allEnvs [] = [ undefined ] allEnvs (x:xs) = [ set x b env | env <- allEnvs xs, b <- [False,True] ] valid :: Prop -> Bool valid p = and [ eval env p' | env <- allEnvs (vars p') ] where p' = simplify p -- i. prop_Sound p env = valid p ==> eval env p ------------------------------------------------------------------------------------