X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;ds=sidebyside;f=cadenus.py;fp=cadenus.py;h=0d3b4156e53d86739cb2648c38834880cab2fb96;hb=3d8f7067b9c3a48ef140d7cff834d18ee91f58b3;hp=0000000000000000000000000000000000000000;hpb=21c390a77d42729afa23844ef2f1295106bed3de;p=cipher-tools.git diff --git a/cadenus.py b/cadenus.py new file mode 100644 index 0000000..0d3b415 --- /dev/null +++ b/cadenus.py @@ -0,0 +1,95 @@ +from utilities import * +from language_models import * +from itertools import chain + +from logger import logger + +def make_cadenus_keycolumn(doubled_letters = 'vw', start='a', reverse=False): + """Makes the key column for a Cadenus cipher (the column down between the + rows of letters) + + >>> make_cadenus_keycolumn()['a'] + 0 + >>> make_cadenus_keycolumn()['b'] + 1 + >>> make_cadenus_keycolumn()['c'] + 2 + >>> make_cadenus_keycolumn()['v'] + 21 + >>> make_cadenus_keycolumn()['w'] + 21 + >>> make_cadenus_keycolumn()['z'] + 24 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['a'] + 1 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['b'] + 0 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['c'] + 24 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['i'] + 18 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['j'] + 18 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['v'] + 6 + >>> make_cadenus_keycolumn(doubled_letters='ij', start='b', reverse=True)['z'] + 2 + """ + index_to_remove = string.ascii_lowercase.find(doubled_letters[0]) + short_alphabet = string.ascii_lowercase[:index_to_remove] + string.ascii_lowercase[index_to_remove+1:] + if reverse: + short_alphabet = cat(reversed(short_alphabet)) + start_pos = short_alphabet.find(start) + rotated_alphabet = short_alphabet[start_pos:] + short_alphabet[:start_pos] + keycolumn = {l: i for i, l in enumerate(rotated_alphabet)} + keycolumn[doubled_letters[0]] = keycolumn[doubled_letters[1]] + return keycolumn + +def cadenus_encipher(message, keyword, keycolumn, fillvalue='a'): + """Encipher with the Cadenus cipher + + >>> cadenus_encipher(sanitise('Whoever has made a voyage up the Hudson ' \ + 'must remember the Kaatskill mountains. ' \ + 'They are a dismembered branch of the great'), \ + 'wink', \ + make_cadenus_keycolumn(doubled_letters='vw', start='a', reverse=True)) + 'antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaasuvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned' + >>> cadenus_encipher(sanitise('a severe limitation on the usefulness of ' \ + 'the cadenus is that every message must be ' \ + 'a multiple of twenty-five letters long'), \ + 'easy', \ + make_cadenus_keycolumn(doubled_letters='vw', start='a', reverse=True)) + 'systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtofarenuseieeieltarlmentieetogevesitfaisltngeeuvowul' + """ + rows = chunks(message, len(message) // 25, fillvalue=fillvalue) + columns = zip(*rows) + rotated_columns = [col[start:] + col[:start] for start, col in zip([keycolumn[l] for l in keyword], columns)] + rotated_rows = zip(*rotated_columns) + transpositions = transpositions_of(keyword) + transposed = [transpose(r, transpositions) for r in rotated_rows] + return cat(chain(*transposed)) + +def cadenus_decipher(message, keyword, keycolumn, fillvalue='a'): + """ + >>> cadenus_decipher('antodeleeeuhrsidrbhmhdrrhnimefmthgeaetakseomehetyaa' \ + 'suvoyegrastmmuuaeenabbtpchehtarorikswosmvaleatned', \ + 'wink', \ + make_cadenus_keycolumn(reverse=True)) + 'whoeverhasmadeavoyageupthehudsonmustrememberthekaatskillmountainstheyareadismemberedbranchofthegreat' + >>> cadenus_decipher('systretomtattlusoatleeesfiyheasdfnmschbhneuvsnpmtof' \ + 'arenuseieeieltarlmentieetogevesitfaisltngeeuvowul', \ + 'easy', \ + make_cadenus_keycolumn(reverse=True)) + 'aseverelimitationontheusefulnessofthecadenusisthateverymessagemustbeamultipleoftwentyfiveletterslong' + """ + rows = chunks(message, len(message) // 25, fillvalue=fillvalue) + transpositions = transpositions_of(keyword) + untransposed_rows = [untranspose(r, transpositions) for r in rows] + columns = zip(*untransposed_rows) + rotated_columns = [col[-start:] + col[:-start] for start, col in zip([keycolumn[l] for l in keyword], columns)] + rotated_rows = zip(*rotated_columns) + # return rotated_columns + return cat(chain(*rotated_rows)) + +if __name__ == "__main__": + import doctest \ No newline at end of file