1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def blocks(data, blocksize):
    """Generator that yields elements from xs in blocks."""
    assert(len(data) % blocksize == 0)
    for i in xrange(0, len(data), blocksize):
        yield data[i:i+blocksize]

key1 = list(blocks("ABCDEFGHIKLMNOPQRSTUVWXYZ", 5))
key2 = list(blocks("37FBO7T20KZUMXYHLS196QW4AVIDGNJPCRE5", 6))

def code2char(a, b, key):
    return key[a][b]

def char2code(c, key):
    c = c.upper()
    r = [c in row for row in key]
    assert any(r)
    a = r.index(True)
    b = key[a].index(c)
    return a, b

def encrypt(s, key):
    codes = map(lambda x: char2code(x,key), s)
    a, b = zip(*codes)
    d = blocks(a+b, 2)
    c = "".join(map(lambda (a,b): code2char(a, b, key), d))
    return c

def decrypt(c, key):
    d = sum(map(lambda x: char2code(x,key), c), ())
    h = len(d)/2
    a, b = d[:h], d[h:]
    codes = zip(a, b)
    s = "".join(map(lambda (a,b): code2char(a,b,key), codes))
    return s