Simple string encryption

For the Lisp class, we were given a simple string string string encryption, which I tried to solve in Haskell. Basically, one just breaks a string into strings of length n , and then wraps the result. Concatenating the resulting list of character lists is an encrypted string. Decoding is a bit more complicated, since the last line of input may not contain elements (incomplete columns as a result) that you need to take care of.

This is my solution in Haskell:

 import Data.List import Data.Ratio import Data.List.Split encode :: String -> Int -> String encode sn = concat . transpose $ chunk ns decode :: String -> Int -> String decode sn = take len $ encode s' rows where s' = foldr (insertAt " ") s idxs rows = ceiling (len % n) idxs = take (n-filled) [n*rows-1,(n-1)*rows-1..] filled = len - n * (rows - 1) len = length s insertAt :: [a] -> Int -> [a] -> [a] insertAt xs i ys = pre ++ xs ++ post where (pre,post) = splitAt i ys 

This does the job, but I'm not sure if this will be considered idiomatic by Haskell, as my index game doesn't seem too declarative. Could this be improved, and if so, how?

By the way, is there something similar to insertAt in Haskell 98? That is, a function that inserts an item or list with a given index into the list.

Note. This is NOT part of the homework that was supposed to happen anyway.

+7
source share
1 answer

I would do this by looking at the problems of encode and decode somewhat differently. encode splits the data into an n -column matrix, which then transfers (to the n -row matrix) and is combined into rows. decode breaks the data into a matrix of rows n , which it then transfers (to a matrix of columns n ) and concatenates the rows.

So, I would start by defining two functions: one, to make an array in the column matrix n :

 chunk:: Int -> [a] -> [[a]] chunk n as = chunk' n (length as) as where chunk' nl as | l <= n = [as] | otherwise = some : chunk' n (ln) rest where (some, rest) = splitAt n as 

and the other to partition the array into a matrix of rows n :

 slice :: Int -> [a] -> [[a]] slice n as = chunk (q+1) front ++ chunk q back where (q,r) = length as `divMod` n (front, back) = splitAt (r*(q+1)) as 

Now encoding and decoding is quite simple:

 encode :: Int -> [a] -> [a] encode = ((concat . transpose) .). chunk decode :: Int -> [a] -> [a] decode = ((concat . transpose) .). slice 
+5
source

All Articles