In this kata, your task is to implement what I call **Iterative Rotation Cipher (IRC)**. To complete the task, you will create an object with two methods, `encode` and `decode`. (For non-JavaScript versions, you only need to write the two functions without the enclosing dict)

Input
The encode method will receive two arguments — a positive integer n and a string value.
The decode method will receive one argument — a string value.
Output
Each method will return a string value.
How It Works
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.
Test Example

```python
quote = 'If you wish to make an apple pie from scratch, you must first invent the universe.'
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:
'Ifyouwishtomakeanapplepiefromscratch,youmustfirstinventtheuniverse.'

Step 2 — shift the order of string characters to the right by 10:
'euniverse.Ifyouwishtomakeanapplepiefromscratch,youmustfirstinventth'

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.
'''
```

Technical Details

- Input will always be valid.
- The characters used in the strings include any combination of alphanumeric characters, the space character, the newline character, and any of the following: `_!@#$%^&()[]{}+-*/="'<>,.?:;`.

If you enjoyed this kata, be sure to check out [my other katas](https://www.codewars.com/users/docgunthrop/authored).

Source: codewars | Difficulty: EASY
Tags: String algorithms

Starter code: def encode(n,strng):
	

Solutions:
def shift(string, step):
	i = step % len(string) if string else 0
	return f'{string[-i:]}{string[:-i]}'

def encode(n, string):
	for _ in range(n):
		shifted = shift(string.replace(' ', ''), n)
		l = [len(word) for word in string.split(' ')]
		string = ' '.join((shift(shifted[sum(l[:i]):sum(l[:i + 1])], n) for i in range(len(l))))
	return f'{n} {string}'

def decode(string):
	(n, string) = (int(string.partition(' ')[0]), string.partition(' ')[2])
	for _ in range(n):
		shifted = shift(''.join((shift(word, -n) for word in string.split(' '))), -n)
		l = [len(word) for word in string.split(' ')]
		string = ' '.join((shifted[sum(l[:i]):sum(l[:i + 1])] for i in range(len(l))))
	return string


def rotate(n, s):
	if not s:
		return s
	n = -n % len(s)
	return s[n:] + s[:n]

def cipher(n, s):
	sp = [i for (i, c) in enumerate(s) if c == ' '] + [len(s)]
	s = s.split(' ')
	if n < 0:
		s = [rotate(n, w) for w in s]
	s = rotate(n, ''.join(s))
	s = [s[i + 1 - x:j - x] for (x, (i, j)) in enumerate(zip([-1] + sp, sp))]
	if n > 0:
		s = [rotate(n, w) for w in s]
	return ' '.join(s)

def encode(n, s):
	for _ in range(n):
		s = cipher(n, s)
	return f'{n} {s}'

def decode(s):
	(n, s) = s.split(' ', 1)
	n = int(n)
	for _ in range(n):
		s = cipher(-n, s)
	return s


def encode(n, strng):
	for _ in range(n):
		(wos, spa, new, a) = ('', [], '', [])
		for i in range(len(strng)):
			if strng[i] == ' ':
				spa.append(i)
			else:
				wos += strng[i]
		shifted = []
		for i in range(len(wos)):
			shifted.insert((i + n) % len(wos), wos[i])
		for i in spa:
			shifted.insert(i, ' ')
		for i in [i for i in ''.join(shifted).split(' ')]:
			tem = []
			for j in range(len(i)):
				tem.insert((j + n) % len(i), i[j])
			a.append(''.join(tem))
		strng = ' '.join(a)
	return '{} {}'.format(n, strng)

def decode(strng):
	n = int(strng.split(' ')[0])
	strng = strng[len(str(n)) + 1:]
	for _ in range(n):
		(a, spa) = ([], [])
		for i in range(len(strng)):
			if strng[i] == ' ':
				spa.append(i)
		for i in [i for i in strng.split(' ')]:
			tem = []
			for j in range(len(i)):
				tem.insert((j - n) % len(i), i[j])
			a.append(''.join(tem))
		(wos, shifted) = (''.join(a), [])
		for i in range(len(wos)):
			shifted.insert((i - n) % len(wos), wos[i])
		for i in spa:
			shifted.insert(i, ' ')
		strng = ''.join(shifted)
	return strng


def encode(n, cleartext):

	def rotate_right(sequence, n):
		n %= len(sequence) or 1
		return sequence[-n:] + sequence[:-n]
	for _ in range(n):
		letters = iter(rotate_right([c for c in cleartext if c != ' '], n))
		cleartext = ''.join((c if c == ' ' else next(letters) for c in cleartext))
		cleartext = ' '.join((rotate_right(word, n) for word in cleartext.split(' ')))
	return f'{n} {cleartext}'

def decode(ciphertext):

	def rotate_left(sequence, n):
		n %= len(sequence) or 1
		return sequence[n:] + sequence[:n]
	(n, ciphertext) = ciphertext.split(' ', 1)
	n = int(n)
	for _ in range(n):
		ciphertext = ' '.join((rotate_left(word, n) for word in ciphertext.split(' ')))
		letters = iter(rotate_left([c for c in ciphertext if c != ' '], n))
		ciphertext = ''.join((c if c == ' ' else next(letters) for c in ciphertext))
	return ciphertext


(SPACE, NULL_STR) = (' ', '')

def rotate(n, s):
	if not s:
		return NULL_STR
	if SPACE in s:
		return SPACE.join((rotate(n, word) for word in s.split(SPACE)))
	else:
		n %= len(s)
		return s[-n:] + s[:-n]

def cipher(n, s):
	spaces = [idx for (idx, char) in enumerate(s) if char == SPACE]
	for _ in range(abs(n)):
		if n < 0:
			s = rotate(n, s)
		s = s.replace(SPACE, NULL_STR)
		s = rotate(n, s)
		for idx in spaces:
			s = s[:idx] + SPACE + s[idx:]
		if n > 0:
			s = rotate(n, s)
	return s

def encode(n, s):
	return str(n) + SPACE + cipher(n, s)

def decode(s):
	(n, s) = s.split(SPACE, 1)
	n = int(n)
	return cipher(-n, s)


def encode(n, strng):
	new_strng = strng.split(' ')
	for i in range(n):
		strng = ''.join(strng.split(' '))
		strng = strng[-n:] + strng[:-n]
		index_0 = 0
		for i in range(len(new_strng)):
			index = len(new_strng[i]) + index_0
			new_strng[i] = strng[index_0:index]
			index_0 = index
		strng = ''
		for i in new_strng:
			change = n % len(i) if len(i) != 0 else i.count(' ')
			strng += i[-change:] + i[:-change] + ' '
		strng = strng[:-1]
	return f'{n} ' + strng

def decode(strng):
	i = 0
	num = ''
	while strng[i].isdigit():
		num += strng[i]
		i += 1
	num = int(''.join(num))
	strng = strng[len(str(num)) + 1:]
	new_strng = strng.split(' ')
	strng = ''.join(strng.split(' '))
	for i in range(num):
		index_0 = 0
		for i in range(len(new_strng)):
			index = len(new_strng[i]) + index_0
			new_strng[i] = strng[index_0:index]
			index_0 = index
		strng = ''
		for i in new_strng:
			change = num % len(i) if len(i) != 0 else i.count(' ')
			strng += i[change:] + i[:change]
		strng = strng[num:] + strng[:num]
	index_0 = 0
	for i in range(len(new_strng)):
		index = len(new_strng[i]) + index_0
		new_strng[i] = strng[index_0:index]
		index_0 = index
	return ' '.join(new_strng)


from collections import deque
from itertools import chain, count

def _code(n, s, sign):
	(non_space, offset) = ([], count())
	slice_points = [0] + [i - (0 if c != ' ' else next(offset)) for (i, c) in enumerate(s) if c == ' ' or non_space.append(c)] + [len(s)]
	slices = [slice(start, end) for (start, end) in zip(slice_points, slice_points[1:])]
	ops = ([slice(None)] * (sign == 1) + slices + [slice(None)] * (sign == -1)) * n
	for op in ops:
		d = deque(non_space[op])
		d.rotate(sign * n)
		non_space[op] = d
	return ' '.join((''.join(non_space[x]) for x in slices))

def encode(n, s):
	ciphered = _code(n, s, 1)
	return f'{n} {ciphered}'

def decode(s):
	(n, s) = s.split(' ', 1)
	return _code(int(n), s, -1)


import re
from collections import deque

def encode(n, s):
	s = s.replace('\n', '`')
	for i in range(n):
		(pos, s) = (get_pos(s), deque(s.replace(' ', '')))
		deque.rotate(s, n)
		s = rotate(set_pos(s, pos), n, 1)
	return str(n) + ' ' + s.replace('`', '\n')

def decode(s):
	(n, s) = (re.search('^\\d+', s).group(), s.replace('\n', '`'))
	(s, n) = (s[len(n) + 1:], int(n))
	for i in range(n):
		(pos, s) = (get_pos(s), deque(''.join(deque(rotate(s, n, -1))).replace(' ', '')))
		deque.rotate(s, -n)
		s = ''.join(set_pos(s, pos))
	return s.replace('`', '\n')
get_pos = lambda s: [l for (l, j) in enumerate(s) if j == ' ']

def rotate(s, n, c):
	li = []
	for k in re.findall('(.+?)(\\s+)|(.+$)', ''.join(s)):
		t = deque(k[0] or k[-1])
		deque.rotate(t, n * c)
		li.append(''.join(t) + k[1])
	return ''.join(li)

def set_pos(s, position):
	for pos in position:
		s.insert(pos, ' ')
	return s


def encode(n, s):
	for i in range(n):
		s = ''.join(space(re(''.join([decore(e, n) for e in space(re(decore(s.replace(' ', ''), n)), ws(s)).split(' ')])), ws(s)))
	return str(n) + ' ' + s

def decode(s):
	(n, s) = s.split(' ', 1)
	(n, sps) = (int(n), ws(s))
	for i in range(n):
		s = ''.join(space(re(decore(''.join([decore(e, -n) for e in s.split(' ')]), -n)), sps))
	return s

def space(stg, arr):
	for i in arr:
		stg.insert(i, ' ')
	return ''.join(stg)

def decore(code, key):
	l = len(code) or 1
	i = key % l
	return code[-i:] + code[:-i]
ws = lambda s: [i for (i, e) in enumerate(s) if e == ' ']
re = lambda l: [e for e in l]


def rotate(n, s):
	i = -n % len(s) if len(s) > 0 else 1
	return s[i:] + s[:i]

def cipher(n, s):
	sp = [i for (i, c) in enumerate(s) if c == ' '] + [len(s)]
	s = s.split(' ')
	if n < 0:
		s = [rotate(n, w) for w in s]
	s = rotate(n, ''.join(s))
	s = [s[i + 1 - x:j - x] for (x, (i, j)) in enumerate(zip([-1] + sp, sp))]
	if n > 0:
		s = [rotate(n, w) for w in s]
	return ' '.join(s)

def encode(n, strng):
	s = strng
	for _ in range(n):
		s = cipher(n, s)
	return '{} {}'.format(n, s)

def decode(strng):
	(n, s) = strng.split(' ', 1)
	n = int(n)
	for _ in range(n):
		s = cipher(-n, s)
	return s