+ >>> scytale_decipher('tcnhkfeboqrxuo iw ', 3)
+ 'thequickbrownfox '
+ >>> scytale_decipher('tubnhirfecooqkwx', 4)
+ 'thequickbrownfox'
+ >>> scytale_decipher('tubn hirf ecoo qkwx ', 5)
+ 'thequickbrownfox '
+ >>> scytale_decipher('tqcrnxhukof eibwo ', 6)
+ 'thequickbrownfox '
+ >>> scytale_decipher('tqcrnx hukof eibwo ', 7)
+ 'thequickbrownfox '
+ """
+ cols = round(len(message) / rows)
+ columns = [message[i:i+rows] for i in range(0, cols * rows, rows)]
+ return ''.join([''.join(c) for c in zip_longest(*columns, fillvalue='')])
+
+
+def transpositions_of(keyword):
+ """Finds the transpostions given by a keyword. For instance, the keyword
+ 'clever' rearranges to 'celrv', so the first column (0) stays first, the
+ second column (1) moves to third, the third column (2) moves to second,
+ and so on.
+
+ If passed a tuple, assume it's already a transposition and just return it.
+
+ >>> transpositions_of('clever')
+ (0, 2, 1, 4, 3)
+ >>> transpositions_of('fred')
+ (3, 2, 0, 1)
+ >>> transpositions_of((3, 2, 0, 1))
+ (3, 2, 0, 1)
+ """
+ if isinstance(keyword, tuple):
+ return keyword
+ else:
+ key = deduplicate(keyword)
+ transpositions = tuple(key.index(l) for l in sorted(key))
+ return transpositions
+
+def pad(message_len, group_len, fillvalue):
+ padding_length = group_len - message_len % group_len
+ if padding_length == group_len: padding_length = 0
+ padding = ''
+ for i in range(padding_length):
+ if callable(fillvalue):
+ padding += fillvalue()
+ else:
+ padding += fillvalue
+ return padding
+
+def column_transposition_encipher(message, keyword, fillvalue=' ',
+ fillcolumnwise=False,
+ emptycolumnwise=False):
+ """Enciphers using the column transposition cipher.
+ Message is padded to allow all rows to be the same length.
+
+ >>> column_transposition_encipher('hellothere', 'abcdef', fillcolumnwise=True)
+ 'hlohr eltee '
+ >>> column_transposition_encipher('hellothere', 'abcdef', fillcolumnwise=True, emptycolumnwise=True)
+ 'hellothere '
+ >>> column_transposition_encipher('hellothere', 'abcdef')
+ 'hellothere '
+ >>> column_transposition_encipher('hellothere', 'abcde')
+ 'hellothere'
+ >>> column_transposition_encipher('hellothere', 'abcde', fillcolumnwise=True, emptycolumnwise=True)
+ 'hellothere'
+ >>> column_transposition_encipher('hellothere', 'abcde', fillcolumnwise=True, emptycolumnwise=False)
+ 'hlohreltee'
+ >>> column_transposition_encipher('hellothere', 'abcde', fillcolumnwise=False, emptycolumnwise=True)
+ 'htehlelroe'
+ >>> column_transposition_encipher('hellothere', 'abcde', fillcolumnwise=False, emptycolumnwise=False)
+ 'hellothere'
+ >>> column_transposition_encipher('hellothere', 'clever', fillcolumnwise=True, emptycolumnwise=True)
+ 'heotllrehe'
+ >>> column_transposition_encipher('hellothere', 'clever', fillcolumnwise=True, emptycolumnwise=False)
+ 'holrhetlee'
+ >>> column_transposition_encipher('hellothere', 'clever', fillcolumnwise=False, emptycolumnwise=True)
+ 'htleehoelr'
+ >>> column_transposition_encipher('hellothere', 'clever', fillcolumnwise=False, emptycolumnwise=False)
+ 'hleolteher'
+ >>> column_transposition_encipher('hellothere', 'cleverly')
+ 'hleolthre e '
+ >>> column_transposition_encipher('hellothere', 'cleverly', fillvalue='!')
+ 'hleolthre!e!'
+ >>> column_transposition_encipher('hellothere', 'cleverly', fillvalue=lambda: '*')
+ 'hleolthre*e*'
+ """
+ transpositions = transpositions_of(keyword)
+ message += pad(len(message), len(transpositions), fillvalue)
+ if fillcolumnwise:
+ rows = every_nth(message, len(message) // len(transpositions))
+ else:
+ rows = chunks(message, len(transpositions))
+ transposed = [transpose(r, transpositions) for r in rows]
+ if emptycolumnwise:
+ return combine_every_nth(transposed)
+ else:
+ return ''.join(chain(*transposed))
+
+def column_transposition_decipher(message, keyword, fillvalue=' ',
+ fillcolumnwise=False,
+ emptycolumnwise=False):
+ """Deciphers using the column transposition cipher.
+ Message is padded to allow all rows to be the same length.
+
+ >>> column_transposition_decipher('hellothere', 'abcde', fillcolumnwise=True, emptycolumnwise=True)
+ 'hellothere'
+ >>> column_transposition_decipher('hlohreltee', 'abcde', fillcolumnwise=True, emptycolumnwise=False)
+ 'hellothere'
+ >>> column_transposition_decipher('htehlelroe', 'abcde', fillcolumnwise=False, emptycolumnwise=True)
+ 'hellothere'
+ >>> column_transposition_decipher('hellothere', 'abcde', fillcolumnwise=False, emptycolumnwise=False)
+ 'hellothere'
+ >>> column_transposition_decipher('heotllrehe', 'clever', fillcolumnwise=True, emptycolumnwise=True)
+ 'hellothere'
+ >>> column_transposition_decipher('holrhetlee', 'clever', fillcolumnwise=True, emptycolumnwise=False)
+ 'hellothere'
+ >>> column_transposition_decipher('htleehoelr', 'clever', fillcolumnwise=False, emptycolumnwise=True)
+ 'hellothere'
+ >>> column_transposition_decipher('hleolteher', 'clever', fillcolumnwise=False, emptycolumnwise=False)
+ 'hellothere'