Daily Challenge #113 - Iterative Rotation Cipher

thepracticaldev profile image dev.to staff ・2 min read


Your challenge is to implement an Iterative Rotation Cipher (IRC). To complete the challenge, create an object with two methods, encode and decode.

encode will receive two arguments, a positive integer n and a string value.
decode will receive one argument - a string value.

Each method should return a string value. Encoding and decoding are done by performing a series of character and substring rotations on a string input.

Encoding: The number of rotations is determined by the value of n. The sequence of rotations is applied in the following order:
 Step 1: Remove all spaces in the string (but remember their positions)
 Step 2: Shift the order of characters in the new string to the right by n characters
 Step 3: Put the spaces back in their original positions
 Step 4: Shift the characters of each substring (separated by one or more consecutive spaces) to the right by n

Repeat this process until it has been completed n times in total.
The value n is then prepended to the resulting string with a space.

Decoding: Decoding simply reverses the encoding process.


let quote = `If you wish to make an apple pie from scratch, you must first invent the universe.`;
let solution = `10 hu fmo a,ys vi utie mr snehn rni tvte .ysushou teI fwea pmapi apfrok rei tnocsclet`;
IterativeRotationCipher.encode(10,quote) === solution; //true

/* Step-by-step breakdown:
Step 1 — remove all spaces:

Step 2 — shift the order of string characters to the right by 10:

Step 3 — place the spaces back in their original positions:
`eu niv erse .I fyou wi shtom ake anap plepiefr oms crat ch,yo umustf irs tinventth`

Step 4 — shift the order of characters for each space-separated substring to the right by 10:
`eu vni seer .I oufy wi shtom eak apan frplepie som atcr ch,yo ustfum sir htinventt`

Repeat the steps 9 more times before returning the string with `10 ` prepended.


[14,True evil is a mundane bureaucracy.],
[22,There is nothing more atrociously cruel than an adored child.]

[10 hu fmo a,ys vi utie mr snehn rni tvte .ysushou teI fwea pmapi apfrok rei tnocsclet]
[36 ws h weA dgIaa ug owh n!asrit git
msm phw teaI'e tanantwhe reos
s ther! aHeae 'gwadin
t haw n htoo ,I'i sy aohOy

Good luck!

This challenge comes from docgunthrop on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!


Editor guide
craigmc08 profile image
Craig McIlwrath

Here's my solution in Haskell:

import Data.Char (isDigit)

applyN :: Int -> (a -> a) -> a -> a
applyN n f = foldr (.) id (replicate n f)

shift :: Int -> [a] -> [a]
shift _ [] = []
shift 0 xs = xs
shift n xs = shift (n - 1) $ last xs : init xs

unshift :: Int -> [a] -> [a]
unshift _ [] = []
unshift 0 xs = xs
unshift n (x:xs) = unshift (n - 1) $ xs ++ [x]

saveSpaces :: String -> [Int]
saveSpaces [] = []
saveSpaces (' ':cs) = 0 : map (+1) (saveSpaces cs)
saveSpaces (_:cs) = map (+1) (saveSpaces cs)

restoreSpaces :: [Int] -> String -> String
restoreSpaces [] cs = cs
restoreSpaces (0:ns) cs = ' ' : restoreSpaces (map (+(-1)) ns) cs
restoreSpaces ns (c:cs) = c : restoreSpaces (map (+(-1)) ns) cs

splitAfterNumber :: String -> (Int, String)
splitAfterNumber cs = let (dgts, str) = span isDigit cs
                      in (read dgts :: Int, tail str)

encodeStep :: Int -> String -> String
encodeStep n cs = let spaces = saveSpaces cs
                  in  unwords $
                      map (shift n) $
                      words $
                      restoreSpaces spaces $
                      shift n $
                      filter (/=' ') cs

encode :: Int -> String -> String
encode n = ((show n ++ " ")++) . applyN n (encodeStep n)

decodeStep :: Int -> String -> String
decodeStep n cs = let spaces = saveSpaces cs
                  in  restoreSpaces spaces $
                      unshift n $
                      filter (/=' ') $
                      unwords $
                      map (unshift n) $
                      words cs

decode :: String -> String
decode cs = let (n, str) = splitAfterNumber cs
            in applyN n (decodeStep n) str

There's no validation of the input to decode. Also, I'm not sure if the second test provided for decode is correct. I'm not getting any English words out of it, but my decode function hasn't failed besides that test.

meave9786 profile image

Really glad for the share me this blog have to seen the clocks desktop windows 10 many users got this app and access the all setting,