Fixed accent removal
[cipher-tools.git] / cipher.py
index 7feaedf90fd289b9fda1da60f0dea9565e1108d1..3e42da109840697938fe9fd16ca95f09a234574b 100644 (file)
--- a/cipher.py
+++ b/cipher.py
@@ -1,8 +1,8 @@
 import string
 import collections
 import logging
-from itertools import zip_longest, cycle
-
+from itertools import zip_longest, cycle, chain
+from language_models import *
 
 logger = logging.getLogger(__name__)
 logger.addHandler(logging.FileHandler('cipher.log'))
@@ -237,8 +237,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,38 +408,55 @@ 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.
-
-    >>> column_transposition_encipher('hellothere', 'clever')
-    'hleolteher'
-    >>> column_transposition_encipher('hellothere', 'cleverly', fillvalue='!')
-    'hleolthre!e!'
-    >>> column_transposition_encipher('hellothere', 'clever', columnwise=True)
-    'htleehoelr'
     """
+    # >>> column_transposition_encipher('hellothere', 'clever')
+    # 'hleolteher'
+    # >>> column_transposition_encipher('hellothere', 'cleverly', fillvalue='!')
+    # 'hleolthre!e!'
+    # >>> column_transposition_encipher('hellothere', 'clever', columnwise=True)
+    # '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):
     """Deciphers using the column transposition cipher.
     Message is padded to allow all rows to be the same length.
-
-    >>> column_transposition_decipher('hleolteher', 'clever')
-    'hellothere'
-    >>> column_transposition_decipher('hleolthre!e!', 'cleverly', fillvalue='?')
-    'hellothere!!'
-    >>> column_transposition_decipher('htleehoelr', 'clever', columnwise=True)
-    'hellothere'
     """
+    # >>> column_transposition_decipher('hleolteher', 'clever')
+    # 'hellothere'
+    # >>> column_transposition_decipher('hleolthre!e!', 'cleverly', fillvalue='?')
+    # 'hellothere!!'
+    # >>> column_transposition_decipher('htleehoelr', 'clever', columnwise=True)
+    # 'hellothere'
+    # """
     transpositions = transpositions_of(keyword)
     if columnwise:
         columns = chunks(message, int(len(message) / len(transpositions)))