kosmeticke upravy
[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         tabulka[zprava[i]][zprava[i+1]] += 1
17     celkem = sum(sum(tab2.values()) for tab2 in tabulka.values())
18     for i in abc:
19         for j in abc:
20             tabulka[i][j] /= float(celkem)
21     return tabulka
22
23 def vzdalenost(tab1, tab2, abc=MABECEDA):
24     rozdil = 0
25     for i in abc:
26         for j in abc:
27             rozdil += abs(tab1[i][j] - tab2[i][j])
28     return rozdil
29
30 def substituce(zprava, slovnik, abc=MABECEDA):
31     pole = []
32     for c in zprava:
33         if c in abc:
34             pole.append(slovnik[c])
35         else:
36             pole.append(c)
37     return pole
38
39 def poradi_dle_frekvence(zprava, abc=MABECEDA):
40     freq = dict()
41     for char in abc:
42         freq[char] = 0
43     for char in zprava:
44         if char in abc:
45             freq[char] += 1
46     return sorted(freq.keys(), key=freq.get, reverse=True)
47
48 class reference:
49     pass
50
51 def jakobsen(zprava, ref):
52     slovnik = dict(zip(poradi_dle_frekvence(zprava, ref.abeceda), ref.poradi))
53     tabulka = nova_tabulka(substituce(zprava, slovnik, ref.abeceda), ref.abeceda)
54     vzdal = vzdalenost(tabulka, ref.tabulka, ref.abeceda)
55
56     vzdal_old = vzdal + 1
57     while vzdal_old > vzdal:
58         vzdal_old = vzdal
59         for (x, y) in combinations(ref.abeceda, 2):
60             slovnik[x], slovnik[y] = slovnik[y], slovnik[x]
61             v1 = vzdalenost(nova_tabulka(substituce(zprava, slovnik, ref.abeceda), ref.abeceda),
62                             ref.tabulka, ref.abeceda)
63             if  v1 < vzdal:
64                 vzdal = v1
65             else:
66                 slovnik[x], slovnik[y] = slovnik[y], slovnik[x]
67     return slovnik
68     
69
70 def desifruj(zprava, mezery=True):
71     if mezery:
72         f = open('ref')
73     else:
74         f = open('bref')
75     ref = pickle.load(f)
76     f.close()
77     slovnik = jakobsen(ocesat(zprava, mezery), ref)
78     return '\n'.join([''.join(substituce(zprava, slovnik, ref.abeceda)),
79                       ' '.join(ref.abeceda),
80                       ' '.join([slovnik[c] for c in ref.abeceda])])