bugfix
[krypto.git] / jakobsen.py
1 #!/usr/bin/env python
2
3 from itertools import combinations
4 import pickle
5 from ocesavac import ocesat
6
7 MABECEDA = ' ABCDEFGHIJKLMNOPQRSTUVWXYZ'
8
9 def nova_tabulka(zprava, abc=MABECEDA):
10     tabulka = dict()
11     for i in abc:
12         tabulka[i] = dict()
13         for j in abc:
14             tabulka[i][j] = 0
15     for i in range(len(zprava) - 1):
16         if zprava[i] in tabulka and zprava[i+1] in tabulka[zprava[i]]:
17             tabulka[zprava[i]][zprava[i+1]] += 1
18     celkem = sum(sum(tab2.values()) for tab2 in tabulka.values())
19     if celkem != 0:
20         for i in abc:
21             for j in abc:
22                 tabulka[i][j] /= float(celkem)
23     return tabulka
24
25 def vzdalenost(tab1, tab2, abc=MABECEDA):
26     rozdil = 0
27     for i in abc:
28         for j in abc:
29             rozdil += abs(tab1[i][j] - tab2[i][j])
30     return rozdil
31
32 def substituce(zprava, slovnik, abc=MABECEDA):
33     pole = []
34     for c in zprava:
35         if c in abc:
36             pole.append(slovnik[c])
37         else:
38             pole.append(c)
39     return pole
40
41 def poradi_dle_frekvence(zprava, abc=MABECEDA):
42     freq = dict()
43     for char in abc:
44         freq[char] = 0
45     for char in zprava:
46         if char in abc:
47             freq[char] += 1
48     return sorted(freq.keys(), key=freq.get, reverse=True)
49
50 class reference:
51     pass
52
53 def jakobsen(zprava, ref):
54     slovnik = dict(zip(poradi_dle_frekvence(zprava, ref.abeceda), ref.poradi))
55     tabulka = nova_tabulka(substituce(zprava, slovnik, ref.abeceda), ref.abeceda)
56     vzdal = vzdalenost(tabulka, ref.tabulka, ref.abeceda)
57
58     vzdal_old = vzdal + 1
59     while vzdal_old > vzdal:
60         vzdal_old = vzdal
61         for (x, y) in combinations(ref.abeceda, 2):
62             slovnik[x], slovnik[y] = slovnik[y], slovnik[x]
63             v1 = vzdalenost(nova_tabulka(substituce(zprava, slovnik, ref.abeceda), ref.abeceda),
64                             ref.tabulka, ref.abeceda)
65             if  v1 < vzdal:
66                 vzdal = v1
67             else:
68                 slovnik[x], slovnik[y] = slovnik[y], slovnik[x]
69
70     return '\n'.join([''.join(substituce(zprava, slovnik, ref.abeceda)),
71                       ' '.join(ref.abeceda),
72                       ' '.join([slovnik[c] for c in ref.abeceda])])
73
74 def desifruj(zprava, refs):
75     f = open(refs, 'rb')
76     ref = pickle.load(f)
77     f.close()
78     return jakobsen(zprava, ref)