Yesterday’s Programming Praxis problem is about the double transposition cypher. Our target is 34 lines (the length of the provided solution minus prelude code, blank lines and testing), so let’s dive in.

Our import:

`import GHC.Exts`

First up we have zipSort, which I also used in the Rail-Fence Cipher assignment:

zipSort :: Ord a => [a] -> [b] -> [b] zipSort ks = map snd . sortWith fst . zip ks

Unsort is the opposite of zipSort. It takes a list sorted with zipSort and returns it to its original state:

unsort :: Ord a => [a] -> [b] -> [b] unsort ks xs = zipSort (zipSort ks [1..length xs]) xs

With that out of the way, encrypting and decrypting becomes trivial. We zip the key with [0..] to avoid mix ups if there are identical letters in the key.

encrypt :: Ord a => [a] -> [b] -> [b] encrypt key = zipSort (cycle $ zip key [0..]) decrypt :: Ord a => [a] -> [b] -> [b] decrypt key = unsort (cycle $ zip key [0..])

And naturally we have to test if everything works ok:

main :: IO () main = do print . encrypt "STRIPE" $ encrypt "COACH" "PROGRAMMINGPRAXIS" print . decrypt "COACH" $ decrypt "STRIPE" "GNPAPARSRIMOIXMGR"

1 import and 4 lines of code. That will do nicely.