module Exercise_12 where import Control.Monad (ap) import Data.List (nub, sortOn, union) import Test.QuickCheck (quickCheck) {-H12-} isPrime :: Int -> Bool isPrime n | n <= 1 = False | otherwise = primeAux (n-1) where primeAux 1 = True primeAux i = n `mod` i /= 0 && primeAux (i-1) -- returns all primes up to the passed number primes :: Int -> [Int] primes n = [i | i<-[2..n], isPrime i] {-WETT-} inf = enumFrom 1 -- to avoid parentheses -- I used the fact that Haskell sort is stable encrypt :: String -> String encrypt = map snd . sortOn (not . isPrime . fst) . zip inf decrypt :: String -> String decrypt = map fst . sortOn snd . ap zip (flip union inf . primes . length) -- if I understand it right, ap is a kind of prefix notation for <*>, and in fact -- it's just a Haskell function corresponding to S combinator. But I know (almost) -- nothing about monads, so that could be absolutely wrong. Anyway, it works! -- pointful solution, same number of tokens, but less fun: -- decrypt xs = map fst $ sortOn snd $ zip xs $ primes (length xs) `union` inf {-TTEW-}