X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=cipher.py;h=20d144a710e2a27a63f830ad1426e8afd9561bee;hb=cdb525dcf24c28a5e1963560c657cca3c24498f1;hp=2ce1c929c7f06f5f081ec70802be5832b01ca03b;hpb=743cd32d0fbed8a9b316abd7a6bb0bbeb53473e3;p=cipher-tools.git diff --git a/cipher.py b/cipher.py index 2ce1c92..20d144a 100644 --- a/cipher.py +++ b/cipher.py @@ -2,6 +2,7 @@ import string import collections import norms import logging +import math from itertools import zip_longest from segment import segment @@ -304,6 +305,46 @@ def keyword_decipher(message, keyword, wrap_alphabet=0): cipher_translation = ''.maketrans(cipher_alphabet, string.ascii_lowercase) return message.lower().translate(cipher_translation) +def scytale_encipher(message, rows): + """Enciphers using the scytale transposition cipher. + Message is padded with spaces to allow all rows to be the same length. + + >>> scytale_encipher('thequickbrownfox', 3) + 'tcnhkfeboqrxuo iw ' + >>> scytale_encipher('thequickbrownfox', 4) + 'tubnhirfecooqkwx' + >>> scytale_encipher('thequickbrownfox', 5) + 'tubn hirf ecoo qkwx ' + >>> scytale_encipher('thequickbrownfox', 6) + 'tqcrnxhukof eibwo ' + >>> scytale_encipher('thequickbrownfox', 7) + 'tqcrnx hukof eibwo ' + """ + if len(message) % rows != 0: + message += ' '*(rows - len(message) % rows) + row_length = round(len(message) / rows) + slices = [message[i:i+row_length] for i in range(0, len(message), row_length)] + return ''.join([''.join(r) for r in zip_longest(*slices, fillvalue='')]) + +def scytale_decipher(message, rows): + """Deciphers using the scytale transposition cipher. + Assumes the message is padded so that all rows are the same length. + + >>> 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 caesar_break(message, metric=norms.euclidean_distance, target_frequencies=normalised_english_counts, message_frequency_scaling=norms.normalise): """Breaks a Caesar cipher using frequency analysis