X-Git-Url: https://git.njae.me.uk/?a=blobdiff_plain;f=cipher.py;h=6ef01c325d81a7055760d924c400f86b8b718340;hb=19a359ab34be225b4ab7df3974368a2833d45648;hp=7feaedf90fd289b9fda1da60f0dea9565e1108d1;hpb=382cdeb6aee9e799db696d84455b447e3cad778b;p=cipher-tools.git diff --git a/cipher.py b/cipher.py index 7feaedf..6ef01c3 100644 --- a/cipher.py +++ b/cipher.py @@ -1,7 +1,8 @@ import string import collections import logging -from itertools import zip_longest, cycle +from itertools import zip_longest, cycle, chain +from counts import * logger = logging.getLogger(__name__) @@ -11,6 +12,19 @@ logger.setLevel(logging.WARNING) #logger.setLevel(logging.DEBUG) +english_counts = collections.defaultdict(int) +with open('count_1l.txt', 'r') as f: + for line in f: + (letter, count) = line.split("\t") + english_counts[letter] = int(count) +normalised_english_counts = norms.normalise(english_counts) + +choices, weights = zip(*weighted_choices) +cumdist = list(itertools.accumulate(weights)) +x = random.random() * cumdist[-1] +choices[bisect.bisect(cumdist, x)] + + modular_division_table = [[0]*26 for x in range(26)] for a in range(26): for b in range(26): @@ -237,8 +251,9 @@ def affine_decipher_letter(letter, multiplier=1, adder=0, one_based=True): alphabet_start = ord('a') cipher_number = ord(letter) - alphabet_start if one_based: cipher_number += 1 - plaintext_number = ( modular_division_table[multiplier] - [(cipher_number - adder) % 26] ) + plaintext_number = ( + modular_division_table[multiplier] + [(cipher_number - adder) % 26] ) if one_based: plaintext_number -= 1 return chr(plaintext_number % 26 + alphabet_start) else: @@ -407,8 +422,20 @@ def transpositions_of(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=' ', - columnwise=False): + fillcolumnwise=False, + emptycolumnwise=False): """Enciphers using the column transposition cipher. Message is padded to allow all rows to be the same length. @@ -420,12 +447,17 @@ def column_transposition_encipher(message, keyword, fillvalue=' ', 'htleehoelr' """ transpositions = transpositions_of(keyword) + message += pad(len(message), len(transpositions), fillvalue) + if fillcolumnwise: + rows = every_nth(message, len(transpositions)) + else: + rows = chunks(mesage, len(transpositions)) columns = every_nth(message, len(transpositions), fillvalue=fillvalue) - transposed_columns = transpose(columns, transpositions) - if columnwise: - return ''.join(transposed_columns) + transposed = [transpose(r, transpositions) for r in rows] + if emptycolumnwise: + return combine_every_nth(transposed) else: - return combine_every_nth(transposed_columns) + return ''.join(chain(*transposed)) def column_transposition_decipher(message, keyword, fillvalue=' ', columnwise=False):