In [1]:
def readFile( filename ):
    f = open( filename )
    text = f.read()
    f.close()
    return text

def writeFile( filename, text ):
    f = open( filename, "w" )
    f.write( text )
    f.close()

def filterText( text ):
    
    output = ""
    wasSpace = False
    
    for ch in text.upper():
            
        if ch >= 'A' and ch <= 'Z':
        
            # je to zaciatok dalsieho slova?
            if wasSpace:
                output = output + " "
                wasSpace= False;

            output = output + ch
            
        else:
            wasSpace = True;
    
    return output
In [2]:
message = readFile('TXT/spolu_ascii.txt')
print(message[:500])
Uvod
V dnesnom svete technologie napreduju kazdym dnom coraz rychlejsie. Toto sa tyka aj
webovych aplikacii. V sucasnosti si uz aj bezny uzivatel webovych aplikacii dokaze vsimnut,
ze sa nespravaju jednotlive webove aplikacie rovnako, ale rozdielne. Pri niektorych webovych
aplikaciach sa po prekliknuti na hypertextovy odkaz nacita cela stranka, pri inych sa zobrazi
iba notifikacny obrazok nahravania (loader) a nacita sa len cast stranky. Pri dalsich webovych
aplikaciach sa moze stat, ze ked uziv
In [3]:
message = filterText(message)
print(message[:500])
UVOD V DNESNOM SVETE TECHNOLOGIE NAPREDUJU KAZDYM DNOM CORAZ RYCHLEJSIE TOTO SA TYKA AJ WEBOVYCH APLIKACII V SUCASNOSTI SI UZ AJ BEZNY UZIVATEL WEBOVYCH APLIKACII DOKAZE VSIMNUT ZE SA NESPRAVAJU JEDNOTLIVE WEBOVE APLIKACIE ROVNAKO ALE ROZDIELNE PRI NIEKTORYCH WEBOVYCH APLIKACIACH SA PO PREKLIKNUTI NA HYPERTEXTOVY ODKAZ NACITA CELA STRANKA PRI INYCH SA ZOBRAZI IBA NOTIFIKACNY OBRAZOK NAHRAVANIA LOADER A NACITA SA LEN CAST STRANKY PRI DALSICH WEBOVYCH APLIKACIACH SA MOZE STAT ZE KED UZIVATEL STLAC
In [4]:
alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ "

def countChars(message):
    msg = message.upper()
    multiplicities = [ msg.count(i) for i in alphabet ]
    return multiplicities

def getProbabilities(message):
    multiplicities = countChars(message)
    total = sum(multiplicities)
    probabilities = [ float(n) / float(total) for n in multiplicities ]
    return probabilities

def printProbabilities(probabilities):
    for i in range(0, len(alphabet)):
        print("%c\t%.4f" % (alphabet[i], probabilities[i]))
In [5]:
print(countChars(message))
[508338, 75505, 149015, 158310, 407599, 19213, 18274, 119692, 313009, 79648, 161369, 215884, 161827, 273597, 441790, 149340, 1338, 240567, 244333, 254847, 162514, 198028, 4531, 5174, 122648, 134933, 889419]
In [6]:
probabilities = getProbabilities(message)
printProbabilities(probabilities)
A	0.0922
B	0.0137
C	0.0270
D	0.0287
E	0.0740
F	0.0035
G	0.0033
H	0.0217
I	0.0568
J	0.0145
K	0.0293
L	0.0392
M	0.0294
N	0.0496
O	0.0802
P	0.0271
Q	0.0002
R	0.0437
S	0.0443
T	0.0462
U	0.0295
V	0.0359
W	0.0008
X	0.0009
Y	0.0223
Z	0.0245
 	0.1614
In [7]:
def sortProbabilities(probabilities):
    array = []
    for i in range(0, len(alphabet)):
        tuple = (probabilities[i], alphabet[i])
        array.append(tuple)
    array.sort(reverse=True)
    return array
In [8]:
print(sortProbabilities(probabilities))
[(0.16139732181256172, ' '), (0.09224492817845582, 'A'), (0.08016887743973497, 'O'), (0.0739644497964158, 'E'), (0.056799792115109, 'I'), (0.04964794214644779, 'N'), (0.046245496522972766, 'T'), (0.04433758648109456, 'S'), (0.04365419393613419, 'R'), (0.03917512378550837, 'L'), (0.03593490676936064, 'V'), (0.02949040256284907, 'U'), (0.029365736955204943, 'M'), (0.02928262655010886, 'K'), (0.028727528888124323, 'D'), (0.02709979890185387, 'P'), (0.027040823177713637, 'C'), (0.024485450416658953, 'Z'), (0.022256168044158118, 'Y'), (0.02171976115013187, 'H'), (0.014453226080988731, 'J'), (0.01370142169602569, 'B'), (0.003486463347404034, 'F'), (0.0033160688705804048, 'G'), (0.0009388935283125212, 'X'), (0.0008222123263981511, 'W'), (0.0002427985196911777, 'Q')]
In [9]:
import matplotlib
import numpy as np
import matplotlib.pyplot as plt

def showProbabilities(probabilities):
    index = np.arange(len(alphabet))
    yy = [y for y in probabilities]
    plt.bar(index, yy, 0.8)
    plt.xticks(index, [letter for letter in alphabet])
    plt.title('Probabilities')
    plt.show()
In [10]:
showProbabilities(probabilities)
In [11]:
def spocitajVyskyt(text, pocetZnakov=2):
    pocetnosti = {}
    for i in range(len(text)-pocetZnakov):
        s = text[i:i+pocetZnakov]
        pocetnosti[s] = pocetnosti.get(s, 0) + 1
    return pocetnosti

def spocitajDvojice(text):
    pocet = {}
    for i in range(len(text)-1):
        s = text[i:i+2]
        pocet[s] = pocet.get(s, 0) + 1
    return pocet
In [12]:
dvojice = spocitajDvojice(message)
print(sorted(dvojice.items(), key=lambda it: it[1], reverse=True))
[('A ', 157486), ('E ', 126020), (' S', 108486), (' P', 96147), ('O ', 89498), ('I ', 76107), (' N', 72537), (' V', 71297), (' A', 67569), ('U ', 61446), ('Y ', 61109), ('ST', 60919), ('NA', 60901), ('NE', 59957), (' Z', 57339), ('OV', 55247), ('AL', 53576), (' T', 51406), ('PO', 50774), ('PR', 49548), ('TO', 49043), ('L ', 47505), ('M ', 46848), ('RA', 44459), ('IE', 43384), ('LA', 43188), (' M', 42799), ('CH', 42256), ('NI', 42045), ('RE', 39942), ('EN', 39848), (' K', 39505), ('VA', 39402), ('RO', 38616), ('KO', 37526), (' D', 37157), ('HO', 36789), ('RI', 36542), (' O', 36390), ('TA', 35638), ('TE', 34632), ('SA', 34058), ('ED', 33977), ('T ', 33795), ('OM', 33474), ('AN', 33463), ('AT', 32098), ('LI', 31945), ('OR', 31909), (' H', 31780), ('CI', 31556), ('VE', 31531), (' C', 31006), ('LE', 30514), ('OD', 30409), ('TI', 29481), ('AK', 28733), ('NO', 28252), ('DO', 27656), ('ZA', 27532), ('SI', 27259), ('OL', 27157), ('EL', 26643), ('V ', 26536), ('ER', 26082), ('LO', 26025), ('AC', 25840), (' B', 24942), ('AR', 24839), ('JE', 24768), (' R', 24701), ('VY', 24166), ('ME', 24147), ('IA', 23867), (' J', 23317), ('H ', 23280), ('J ', 23278), ('AD', 22901), ('AS', 22881), ('KA', 22752), ('OS', 22597), ('IL', 22443), ('VO', 22426), ('MI', 21926), ('OZ', 21811), ('DE', 21515), ('AV', 21284), ('IT', 21223), ('MA', 21146), ('ON', 20786), ('EJ', 20617), ('TR', 20438), ('ET', 20337), ('IN', 19967), ('ES', 19799), ('AM', 19580), (' U', 19541), ('DA', 19364), ('K ', 19301), ('S ', 19257), ('IC', 18903), ('OB', 18831), ('NY', 18503), ('ZE', 18326), ('SK', 18237), ('HA', 18217), ('VI', 18210), ('OC', 17606), ('AZ', 17441), ('N ', 17409), ('EM', 16915), ('D ', 16896), (' I', 16063), ('MO', 15902), ('Z ', 15679), ('IS', 15667), ('CE', 15561), ('AJ', 15425), ('SL', 15028), ('RY', 15016), ('BO', 14953), ('KE', 14894), ('SE', 14785), ('ZI', 14637), ('OT', 14588), ('KY', 14512), ('TU', 14049), ('SO', 14042), ('PA', 13870), ('CO', 13826), ('KT', 13749), ('YC', 13417), ('OK', 13314), ('KU', 13044), ('DI', 12983), ('DN', 12956), ('MU', 12884), ('EH', 12794), ('IK', 12784), (' L', 12744), ('CA', 11800), ('IM', 11789), ('NU', 11764), ('EC', 11633), ('OU', 11359), ('HL', 11115), ('US', 11024), ('BY', 10992), ('SP', 10821), ('ZN', 10733), ('UT', 10338), ('YS', 10122), ('RU', 10058), ('UC', 9953), ('ZO', 9875), ('YM', 9693), ('R ', 9302), ('EK', 9092), ('NT', 9085), ('UZ', 9052), ('EB', 9039), ('OJ', 9038), ('UD', 9031), ('IV', 8989), ('OH', 8833), ('TY', 8639), ('LU', 8624), (' F', 8612), ('KR', 8393), ('VS', 8367), ('RR', 8297), ('CK', 8270), ('EZ', 8219), ('AP', 8153), ('BA', 7963), ('BU', 7912), ('JA', 7830), ('UJ', 7738), ('AB', 7705), ('JU', 7704), ('CN', 7515), ('DU', 7430), ('TV', 7406), ('PE', 7198), ('SU', 7135), ('VN', 7127), ('UP', 7071), ('KL', 7034), ('PI', 6992), ('C ', 6986), ('UR', 6980), ('TN', 6881), ('OP', 6859), ('BE', 6855), ('ID', 6750), ('AH', 6713), ('LN', 6704), ('BR', 6661), (' E', 6405), ('DR', 6403), ('PL', 6376), ('EV', 6328), ('ZD', 6301), ('DY', 5975), ('RN', 5864), ('UL', 5798), ('HR', 5788), ('RM', 5782), ('EP', 5708), ('DL', 5610), ('BL', 5510), ('UK', 5445), ('YT', 5399), ('IZ', 5346), ('SV', 5151), ('IO', 5086), ('HE', 5044), ('SM', 5006), ('MY', 4970), ('BI', 4948), ('VR', 4793), ('LK', 4700), ('SN', 4671), ('NC', 4613), ('NS', 4542), ('HU', 4501), ('UM', 4480), ('DZ', 4440), ('TK', 4415), ('LY', 4392), ('FO', 4267), ('UN', 4239), ('ZV', 4228), ('DV', 4149), ('HY', 4027), ('NK', 3954), ('MN', 3861), ('RT', 3807), ('CU', 3803), ('VZ', 3770), ('RC', 3725), ('ZR', 3715), ('RV', 3633), ('ZU', 3541), ('VU', 3529), (' G', 3497), ('RS', 3303), ('TL', 3292), ('RK', 3271), ('ND', 3267), ('IU', 3252), ('GR', 3215), ('DS', 3206), ('FI', 3195), ('HN', 3175), ('PU', 3140), ('ZM', 3068), ('AG', 3004), ('VL', 2948), ('YH', 2948), ('NG', 2942), ('IB', 2939), ('SY', 2930), ('ZL', 2899), ('JS', 2847), ('IR', 2796), ('FU', 2795), ('ZH', 2795), ('OG', 2777), (' W', 2764), ('IP', 2683), ('YV', 2659), ('FE', 2628), ('YK', 2622), ('PN', 2568), ('GI', 2550), ('GO', 2518), ('EA', 2513), ('UV', 2507), ('YZ', 2467), ('P ', 2453), ('II', 2439), ('GE', 2429), ('OF', 2416), ('BN', 2403), ('JN', 2375), ('UB', 2351), ('JI', 2313), ('YP', 2310), ('UH', 2298), ('MP', 2286), ('YB', 2272), ('B ', 2271), ('ZY', 2219), ('AU', 2208), ('GA', 2190), ('DP', 2158), ('ZK', 2156), ('EX', 2150), ('LM', 2106), ('LS', 2069), ('IH', 2037), ('X ', 2011), ('RD', 1962), ('DK', 1947), ('KN', 1934), ('KC', 1922), ('NN', 1919), ('JO', 1888), ('EY', 1880), ('EO', 1879), ('SC', 1873), ('AI', 1857), ('HI', 1856), ('LL', 1844), ('PY', 1826), ('HC', 1821), (' X', 1818), ('G ', 1812), ('NF', 1790), ('CT', 1776), ('FA', 1720), ('ZB', 1701), ('JM', 1692), ('KD', 1657), ('RZ', 1652), ('PS', 1597), ('TT', 1594), ('MB', 1588), ('MR', 1560), ('EU', 1545), ('RG', 1512), ('IG', 1508), ('FR', 1505), ('F ', 1501), ('EF', 1498), ('ZP', 1454), ('JT', 1446), ('IJ', 1439), ('DM', 1430), ('YN', 1422), ('KV', 1392), ('HV', 1391), ('YR', 1382), ('SS', 1348), ('TH', 1338), ('OO', 1323), ('CL', 1295), ('RH', 1294), ('ZS', 1288), ('HT', 1280), ('XI', 1269), ('GU', 1265), ('TM', 1225), ('CS', 1214), ('DC', 1213), ('VC', 1184), ('IF', 1168), ('MS', 1152), ('WE', 1139), ('YL', 1138), ('EG', 1133), (' Q', 1125), ('EE', 1121), ('LT', 1107), ('ML', 1091), ('VD', 1090), ('RB', 1087), ('UA', 1078), ('YO', 1075), ('BS', 1039), ('ZZ', 1031), ('LH', 1005), ('KI', 996), ('Q ', 993), ('TS', 992), ('TC', 971), ('YU', 957), ('ZT', 953), ('OY', 925), ('BJ', 924), ('VK', 905), ('AO', 888), ('CR', 880), ('AF', 873), ('VT', 833), ('KM', 808), ('LF', 794), ('DT', 786), ('WI', 763), ('RP', 758), ('NZ', 755), ('FL', 752), ('JD', 735), ('BD', 720), ('MC', 709), ('PP', 707), ('DB', 705), ('PT', 704), ('BC', 674), ('LB', 657), ('PK', 647), ('W ', 640), ('LC', 630), ('HM', 623), ('CV', 614), ('NH', 613), ('SH', 599), ('VP', 598), ('YD', 596), ('LD', 586), ('AX', 582), ('YJ', 550), ('NV', 548), ('MT', 543), ('DD', 541), ('JV', 531), ('UI', 513), ('WO', 506), ('JH', 504), ('GL', 495), ('CY', 495), ('LG', 493), ('MK', 493), ('UF', 491), ('PC', 475), ('BB', 474), (' Y', 472), ('DH', 460), ('RL', 458), ('KF', 458), ('SR', 455), ('VH', 434), ('EW', 431), ('GM', 407), ('CG', 402), ('KZ', 400), ('AW', 393), ('XP', 391), ('LZ', 390), ('WA', 381), ('JL', 375), ('XA', 369), ('SF', 368), ('IX', 360), ('GN', 359), ('JC', 357), ('EI', 354), ('ZJ', 346), ('LV', 339), ('OW', 329), ('HK', 314), ('UE', 311), ('DG', 310), ('WH', 309), ('JB', 304), ('YA', 303), ('FT', 298), ('BZ', 293), ('ZC', 277), ('XT', 273), ('OI', 269), ('KH', 269), ('QU', 268), ('HS', 266), ('TP', 265), ('PH', 230), ('WW', 225), ('MZ', 225), ('BT', 221), ('WS', 218), ('BK', 217), ('BM', 215), ('AY', 214), ('JK', 213), ('LP', 211), ('JP', 207), ('CM', 206), ('GG', 204), ('NL', 186), ('SB', 186), ('GP', 183), ('TB', 181), ('TW', 180), ('TD', 179), ('OE', 172), ('ZG', 172), ('KS', 171), ('BV', 165), ('CC', 164), ('MM', 162), ('GY', 162), ('WN', 161), ('XU', 160), ('FY', 157), ('MF', 156), ('NM', 154), ('NB', 152), ('RF', 151), ('OA', 150), ('XE', 149), ('CP', 140), ('XO', 131), ('UO', 130), ('FF', 125), ('CB', 118), ('JR', 112), ('TZ', 112), ('XN', 111), ('UG', 109), ('GV', 108), ('XY', 108), ('OX', 107), ('NP', 106), ('AE', 102), ('MD', 99), ('DF', 97), ('FD', 93), ('YE', 90), ('PM', 87), ('VB', 86), ('TF', 81), ('JZ', 80), ('NJ', 79), ('AA', 77), ('GH', 74), ('GT', 74), ('KK', 73), ('GS', 71), ('UX', 67), ('CD', 65), ('GB', 65), ('VM', 64), ('HP', 63), ('SW', 61), ('XB', 58), ('WL', 55), ('GD', 54), ('BH', 49), ('NR', 49), ('IQ', 49), ('YG', 48), ('PD', 46), ('HD', 46), ('SZ', 45), ('EQ', 44), ('RW', 43), ('XS', 39), ('CZ', 39), ('LR', 38), ('DJ', 37), ('SD', 36), ('UU', 36), ('JJ', 35), ('MH', 35), ('PG', 34), ('YF', 30), ('PF', 29), ('FS', 28), ('XK', 27), ('SG', 26), ('IY', 26), ('FM', 25), ('WK', 24), ('QI', 24), ('YI', 24), ('SQ', 23), ('HG', 23), ('KB', 23), ('FV', 22), ('DX', 22), ('HF', 21), ('JQ', 21), ('AQ', 21), ('FG', 21), ('MG', 20), ('WP', 20), ('HB', 20), ('UY', 20), ('QL', 19), ('MV', 19), ('DW', 19), ('KP', 18), ('XC', 18), ('WR', 18), ('KX', 18), ('JX', 18), ('FN', 18), ('QM', 18), ('BP', 17), ('VJ', 17), ('BG', 16), ('FQ', 16), ('GJ', 16), ('FC', 15), ('PV', 15), ('XM', 15), ('HZ', 14), ('RJ', 14), ('KW', 14), ('CF', 13), ('CQ', 13), ('WY', 12), ('PB', 12), ('BW', 12), ('WF', 12), ('XH', 12), ('TJ', 11), ('RX', 11), ('WT', 10), ('JF', 10), ('KG', 10), ('WC', 10), ('SJ', 10), ('YY', 9), ('WU', 9), ('HH', 9), ('LW', 9), ('GF', 9), ('LJ', 9), ('FK', 9), ('RQ', 8), ('WD', 8), ('IW', 8), ('HW', 7), ('UW', 7), ('CJ', 7), ('NW', 7), ('FP', 6), ('PW', 6), ('OQ', 6), ('FB', 6), ('QR', 6), ('XJ', 6), ('XZ', 6), ('GC', 6), ('TG', 6), ('XX', 6), ('ZF', 5), ('YW', 5), ('SX', 4), ('XD', 4), ('VF', 4), ('VV', 4), ('FH', 4), ('FW', 4), ('XR', 4), ('WM', 4), ('QO', 4), ('JG', 4), ('WB', 3), ('VG', 3), ('MJ', 3), ('GX', 3), ('PZ', 3), ('NQ', 3), ('XL', 3), ('PJ', 3), ('QJ', 2), ('DQ', 2), ('NX', 2), ('QW', 2), ('TQ', 2), ('FZ', 2), ('GW', 2), ('HJ', 2), ('XF', 2), ('YX', 1), ('GQ', 1), ('JY', 1), ('XV', 1), ('UQ', 1), ('TX', 1), ('CX', 1), ('GZ', 1), ('KJ', 1), ('FJ', 1), ('WQ', 1), ('BX', 1), ('WV', 1), ('WX', 1), ('WJ', 1), ('GK', 1), ('ZW', 1), ('VQ', 1), ('XW', 1), ('MQ', 1), ('ZX', 1), ('QA', 1), ('MW', 1), ('QK', 1)]
In [13]:
def spocitajTrojice(text):
    pocet = {}
    for i in range(len(text)-2):
        s = text[i:i+3]
        pocet[s] = pocet.get(s, 0) + 1
    return pocet
In [14]:
trojice = spocitajTrojice(message)
In [15]:
len(trojice)
Out[15]:
9020
In [16]:
27**3
Out[16]:
19683
In [17]:
def spocitajStvorice(text):
    pocet = {}
    for i in range(len(text)-3):
        s = text[i:i+4]
        pocet[s] = pocet.get(s, 0) + 1
    return pocet
In [18]:
stvorice = spocitajStvorice(message)
In [19]:
print(len(stvorice))
58637
In [20]:
len(stvorice)/27**4
Out[20]:
0.11033586042476963
In [21]:
def spocitajPatice(text):
    pocet = {}
    for i in range(len(text)-4):
        s = text[i:i+5]
        pocet[s] = pocet.get(s, 0) + 1
    return pocet

patice = spocitajPatice(message)
print(len(patice))
233229
In [22]:
from math import log

def spocitajEntropiu(ntice):
    entropy = 0.0
    n = sum(ntice.values())
    for i in ntice.values():
        p = i / n
        entropy = entropy - p * log(p, 2)
    return entropy
In [23]:
print(spocitajEntropiu(dvojice))
print(spocitajEntropiu(trojice))
print(spocitajEntropiu(stvorice))
print(spocitajEntropiu(patice))
print(spocitajEntropiu(trojice)-spocitajEntropiu(dvojice))
print(spocitajEntropiu(stvorice)-spocitajEntropiu(trojice))
print(spocitajEntropiu(patice)-spocitajEntropiu(stvorice))
7.757263355442856
10.842667119297145
13.37433736326111
15.452749922345593
3.0854037638542895
2.5316702439639656
2.078412559084482
In [24]:
for i in range(2,20):
    ntice = spocitajVyskyt(message, i)
    print(i,len(ntice),spocitajEntropiu(ntice))
2 691 7.757263338412117
3 9020 10.842667208090251
4 58637 13.374337713217786
5 233229 15.452750487797122
6 657663 17.18697916361552
7 1333423 18.57529504906668
8 2088772 19.620975950802507
9 2781342 20.380628967270322
10 3362185 20.924202188174117
11 3824199 21.308417822930004
12 4178777 21.577090845162353
13 4444206 21.764010725482514
14 4641273 21.895568692490592
15 4788265 21.989385595087906
16 4899030 22.057964724498458
17 4983992 22.109332096317477
18 5049965 22.148863251066928
19 5101992 22.17985182841475
In [25]:
xx = [item for item in dvojice.items() if item[0].startswith('B')]
print(sorted(xx, key=lambda it: it[1], reverse=True))
[('BO', 14953), ('BY', 10992), ('BA', 7963), ('BU', 7912), ('BE', 6855), ('BR', 6661), ('BL', 5510), ('BI', 4948), ('BN', 2403), ('B ', 2271), ('BS', 1039), ('BJ', 924), ('BD', 720), ('BC', 674), ('BB', 474), ('BZ', 293), ('BT', 221), ('BK', 217), ('BM', 215), ('BV', 165), ('BH', 49), ('BP', 17), ('BG', 16), ('BW', 12), ('BX', 1)]
In [26]:
yy = [item for item in trojice.items() if item[0].startswith('BO')]
print(sorted(yy, key=lambda it: it[1], reverse=True))
[('BOL', 7228), ('BO ', 2435), ('BOR', 1029), ('BOV', 732), ('BOU', 554), ('BOD', 549), ('BOJ', 397), ('BOK', 381), ('BOM', 368), ('BOC', 283), ('BOH', 272), ('BOZ', 243), ('BOT', 184), ('BOO', 139), ('BOS', 60), ('BON', 44), ('BOI', 12), ('BOP', 11), ('BOX', 10), ('BOG', 7), ('BOY', 6), ('BOA', 3), ('BOB', 3), ('BOE', 2), ('BOW', 1)]
In [27]:
def getIndexOfCoincidence(message):
    multiplicities = countChars(message)
    n = sum(multiplicities)
    return float(sum([ ni * (ni-1) for ni in multiplicities ])) / float((n * (n - 1)))
In [28]:
print(getIndexOfCoincidence(message))
0.06785153438951882
In [29]:
def ctoi( c ):
    return ord(c) - 65

def itoc( i ):
    return chr(i + 65)

def caesarEncrypt( plainText, key ):
    output = ""
    for ch in plainText.upper():
        if ch >= 'A' and ch <= 'Z':
            output = output + itoc( (ctoi(ch) + key) % 26 )
        else:
            output = output + ch
    return output

def caesarDecrypt( cipherText, key ):
    decipherKey = 26 - key
    return caesarEncrypt( cipherText, decipherKey)
In [30]:
encrypted = filterText(readFile('TXT/viegenere_encrypted.txt'))
print(encrypted)
DNUWQDFQPTAEAHYHGEOSOONRBAFSJRJKTBSCARWLKEHAAGRQSWZWJHYHNCSEACLWDFLZACMHCTZWUKVUTTZSPCMHGBSCARKKTCJMOHJZTRWLKCYDGDLGAOKVDSZWOOPVIOZWNRRXVHLWNRRUIEJKWMJVWEHMPMFXIHWEPVVUTPAWOCEWWEKZAZWDCDDWWJVHBTZWNSROXTLDAOEGIHWQHZTRBESYWWEVWEEWWBKBDUCFKKKKTCJMOHNRJLVYAHJRUTTMPHYHVIJDOVVVPYKLKVVUHEDXSSCOXFLZAMCOROEWWURLCIDDAOKHBNGOWBUVWEKWPHFZDRCSJRRWTEESHZWLGSLSJRCDHTOWHZTRBEKMLDVUIIEWPVVZDMSFOOZGVOQGQOEGVELGJSFWWEELDSIHEIWKERRUTSSQPVVBKEUGISRJPIFFKKKKTGAJHKVQIAFVOVVODOCWZOEGIHWJAKRVCOLZEBXEJTLZARZVWEKKKPRFZSZWYODHPNVKWMJVWEFGKHYHNAAFPQFPTAYSEBERIOFWKTVPHAQKPVVPDTZWNBFWDNWGBSDVPYKKDSNHALUGISRJPIFGNBFWROEWWURLCSSAZHYHLOESJWCOWANWKBVIDRKMLDVUQULQKITDCTAXPVVBPIFLYCDHHAAVPVVJXRDTQHZFPNKSUGJKTGGQKIRQSBJAJUKKTBWKPCWHBBWKPCIZDRKLOOPVIHWYEFCLKESLASDDALSFZMFXRAFLDOMHDNWLEZCWWALKYCDHPGSAJKVOATZWSCDDCSZWSOJGDNWSJRJKTTGGGVVUHPAFJWEJIOLZARFRGTGKLWEDCDSKOVVVEAFKDSJDCGEQZOIWTRZSWHVIXVWXEJVSXEKLKRRBBYVSNHVUWASLATZYTFANADZHHTGVWMKKTKAFCKRVROEAJUURLNLZAGKUTELSJRYHWESJZVVUHIFYXIKZWALKDSJDCGZWYCLOSNLZAOIVDHWKPCGSTDSFZGRLSWZSPKRVIHSLUCLZTRWKEBXLCGEQCCFGLOESJHYHLOESJKRVPSZSISUWDLWLDWDKTAJODOKKTRVSQUYWTRZSZPVHCDGAJUJRHHWKWBXLCSLWWRFIIHSLIMUDGTWJDOJSJNXARSWLKEKCAWEVIOVSUAPGPRLWNVRVEUFXEJVIXVWKGSZQHTGVWMJWPRKGIWEHHAAVPVVNXNYAJSMHGHWSNRKHALGXWBPRCELZWHTRJLVVKHYDITZWJVVVPIVDKCBBDUZWNSZZPNLSSWWHPNVAHZDDGRQQKIIGPUYZPSIEJTDGKYPRJHWJAGRBHHWWHSMHCMGFPVJRJTGXPVVBTAJKDSJKPLDZWJVDALKZAZZNTSLGAOKDCDSDHHYHVOOFOGYHAICWOHFJTTSFZOCOIHWUKAGDCYKZAZZNTSLGGSVSQULLDSCDHTEGJHYRUTZWUSRUHHWDHVRYTTGKLWEIXVWKGSZQHENWNMUDNAFVETJKTDGFPWJKPLDCEZCKTRSDHFZJWTKSUGKKTWGEWBWRGSZWPVFXVHLODOKDVRSFZARUGISYAHYDIWSKWBUDHFGJPVVIXVWKGSZQHWZWJHYHIIEWYODHIHWJARSHELWFPMFILAQKKTXHITAFCCLWDFALWBUOXKWDESJWWEVZWJVIDRYGPHVQPLDSXCLWXTOWHZJRIHWQSSIHBAJJESUDCDXGNSCHKEFEKBKKHTZWCWIOWAVSHZJKTLACARKRTALSJRROATZWCCNQHSZWHWBHSTGYAHRQSADDPVVFDMHSJMJKTLACARKRZEWHXIKZWEFLDSKLBEOSOUVWIIFYKJVUHHWTAURQIOLZEBBDQOMLPVVVZEAFOOEGIOOGJRVUXFZWDOUHBIFEEBUEJTFGPCEHLOJVZWUKTSSQWPFXIEESJRJKTTZGQUYWWEVODCCONFGJCCKWTNWEDCNHKEJLDSCDHTVSUCWWWEDSOHDRCTZZAHRNTSZWNHFDGOGEOVVGCENWNGVWTYWKKBSHUOJWPVVUTWSKJCKKXNYAJWKEJTSKLWEQXNYODSVOPNVSOHFRAAFVOOPVWEFGSAPGTAJZAFVBDUDDXSJKJTAFPCDRGRGOSWKKHOEWRWTWJADKWBUVDMWXHOODCDAXUCLKPVWFPGGXCFANAGBHXNKTUHYHCIYZPMFXGHWSZZCJDOXXWBUDLAQZAKVQIATGQHYLHBMKEBVVHWWDHGYHLAKLDOKIGIYZPSEHSSZWZOCZPYKTASEVJCZSCOKOTSKYEFCWWALKDSULSNLKKALFWAKCJCNKDWLGODZQPNVODOKZPSKZAHFGDTGEKFIRLWALDBFRCELGYCDHCIYZDSIWDHWDLVVUHHWKWHURLNGFWGKRDLAFPVVNXTUZABRQSLSODCNVWEVAZQIBWOOWRSIDALGXWGLGSEFKDSYHPRVSOCIWDFSCJCTNXNYDKKURLNGFPVVGDOJKDSLSEEVSJRFSTDALWBUZWALKDCLOSSZWOSVEJTSKIOCOAILLHSSOPCCLDWEJLILZWZFQVTSAHHYDILGGGSUXEALZAFILVHLUQFZRJSSFZHYDISSAZKYDIAJWUCLDRRQAJUWRGWZSPGKKPTLGUCLVPYKKDSEHKEJQKIDLCDLZWHJDXDTMPHVOAMWODOKBDUJWWQIBXNYXKFKKPTOGJHURBEFGCCFGXFAVKGRBHSZWUCLGDNLCJCNWWALLDOKVPIVSJRKZXRDWZHYDISLSEZIRJNVOAZCVPYKKDSKKPTOGJHURCOZSNAZIIHSLZCEWSOFGCCFGPNVKDSLSEEVSJRKRADSTKIKWWEHAAGRQSTZWOYVLCSSFZSMHGYLZEBXWWIKAOKYDIIDDZCJDNSLZAZZWILWTHOTNIHAFCWCOROEWPCPRJROAJRFZTVWJUAFUCIFYWBUWPKWLDSWOPXSFZPILCGALODLQPTFACVKZWALKUCLUEAQKWMJVWELZWHCRDKWVKIKRUTZWYCIQTRGXPVRWHEQWOOEGIHSLOOZGXLDYEJVBDULZNSVJJEKKAGVYTRQFEUYWIOYMAGJPNNSEAOEGXFQGQVRYTNLYQSJVTDALXSWRGELZAAFQIHKMLMFXHHSDHPVPXNWOAZCVWELZKIXKISZWZPVVJRWLKULHHSLZWHJQPMWTATFUTTZWICEWWWSKQDROARAYDHJDNSKZAWRJGEWSHZILVHLLDOKVPYKSJRCDLHGOPVRWIWAJHSUWWALKPOZOLEDDPVVQTXLVWMYHGHMKXOEGIOGCDSILCTGLDSIRDMSFZHYHGEOSOHYHULSPWBUWWEVSUGWRDDFGSHYHGEKLDSWOPXKSUGYHPNVABHYDIAAFPGGXCUHLDWJQXGZLKTWJDEKQKIIKTAVSJRKKTNZWSSEWDULSJRCRRKWVPVVGDOJZARYDGDDQCCEHLHWFPVVUTWSKWYERRKAFCOXDXNKLPVVZXNVGSGYHJPHWZOEGHHWGLSULIAFVPVVUTSMJASERJGZOWGKKTLALPZVRADLZEBXVXTLAJUFQIHWDARXHLHWJAGKKTFDSTGRBHHWZAFVLIBWKWMJVWESFZGYHVANWEHKRWIEOAZCFDMWLDSVYTNAFCOBQDCCAJUTDBESYWWEWDTZWSWEGDWKZAIGSTDSFZGYHDPWVEHRQSTZWNSNDHTZWHWKWAEGDZHYLCGOAPVWLKEKCAWEVDFXDWLFQWIKSNAYHGEALXSJDNSZWWBUKTGSNAWKWDHWJJCNZWALKIMEDBEKSUGYHLHSLEGKKPTTAHZJDNSKZABFRIHSLWWEWHAQKDSRQSHWLSWIOTDZAOHRLAIKLDOKQTDKSUGJKTNGGPVRWPIFLOOPVWESFZVVWLIJDARYLHTSAHKVOAIKLDOKPPRCKWMJVWEFGKHYDIAAFPGRBHHWSJRYHIWAJHSUKXSLSEZYDGDWJWBUDLAQZATCHLWWDHKYHCHWJDIJEPNVUWAVLCTZWNSNHGELZATZYTSCWEBJUTAVQBCIKXMAKASZVWAFLDOMHIOCAHZPRJTGFEUYWBYVWWFJDNSZWUCLOAHSNAMFXGFGGZOEGNOMJBZRAXNLZAAFUCIFYOOPVWESFZONDNHWYKSJZTLDWRSIBSAQLDSWOPXSFZHYHUOGVSSIHQRGMCVKDCDWNAFPGPYLZWHKKTRWDEHKOTBDSYYZPEELMOSUWDCGEAAFUCIFYOOEGTVWFEBXVPNVSHZKKTDSQPVVJXRDKWHKUNIFYPCKKXNCGBBRPTSLGOOPWDILODSELICSEAOKQXGZLXIKVWEFWRSIKXTGFPVVUXGZLKBVDCDSKEHXRITGOWFUVIHWWJRFIIHWEKBKKIHWAIDVWQEYSJHFODOCKKAROXCWXQZRQSTZSPHNLGLWVPVRWHTSAHTRVIEJSJRWDHTWJAOTKIIEWOVVJPVWSCIVVHALDWGKLICSEAHFWWEDSOHUDNBMLKBVWWEAELSKFPMWSPBZJWTSDKBXZXTZLDSWLKEKCAWEVPNVLDOKVPIVODOKDXNLQKIXRIMQFWAVBTTAKPVRWCIUGZSDXHSSQOGYHCOGLWWEWIHSLOOPVXSLZWHJDBMDWOOPVHHWFKCKDXNLLDOKVPYKSSSCOXSLZWHDHIHMKWZVPHAQKOVVQDOLSEBKWWALFAWKKTRLZWHJDNSLZABKKPTDGKYJDIHWJSWKKIHSLOSPHHLACAOTRPLGXEFVDCDLZWHJDNSOGIOEWWEJWOCEONTGEKFIRLNAYDHRQSTZWJMFXALTWIWEHPNVSSOPLIFDWSKVOASZWBSCWIHSLDCIUXDZGSSMHGSZWDSRUSTZWGWEJROEAJURODNYLDSGDHSSYAWEKTCSEAOEGLHWFDSJHTSLZATZYTSCWEBJKTSSQOGRBHHWOAZCPNDWSNGRBHHWAZCEWHEWTQHNKPTQGQZCKPVWQKIIVZEAFOFVDSYLGICIUDWFACVKDHWWDHOEGPSAJAQBRCIKZWBKKPVWLKYZOAYGMEZCKPVWKQDGHGIFZAFVWDNAYDHJRIHWQXFFXVHLKQDGHGAFVWBFWWEJKPCFOUOJZEARQSDGOJHYHIWGKWHNHALZWDOUQIESLABSXIAEGQHYIJLGJOCNKTNZWOHFSHAFVXSXLCSLGHOLJWWZSPWJLISSQOGYHPWZQOOPVWEAOWGFXIAZMJHZQVTGVWMRQSIYGPONDNTGSLZRFTIFLDSNRDDAVJSMHGSWWJPVIDRWSJRKKTRWOWGRQDLVUDOCNEILSJRZKTAJVWYZQSOXSOCIWDFSZQADLCGKGEUFWDFXEUVFEQYSFZWNHCTJACVKTJIWLPCKKTPALWBULAOGCARURLNOWHZNKPTKZKICGIHWJAPVEJTLZATLQCIWKPZZWILWTHOTNIHAFCMFXTVWJOSKHNEKGJOEGLHSLSOJWWALVKWEJQULLDOKKPDSDEHKOTSHAJBZQVWZWAZRQSTZSPKRVHPAFJWEJLOFVAFWXAFSKPOEGIWAJHWEJIHSLOHRLAAFVWGKKPTKHWBKKPTKSJUELBMQFEADBCOLEUBRPTSLGIHZWIOLOAZCZWEFLDSXLGLZWWFUWWIKKDSWHATSKETJKTCGMHRYDKEBMIDVGDULGBVVUHKAFBCIMDYTMPGYHSIVFPGRBPWGJZBVAIDSQPVRWIHWJAZZWILWLDWEJAOGCARJRBADAYSWXAWZWJVVFPMWXKFKKTFDSTOEGLHWFJWXKICSEAGYHWESJZHYDIKFGYYZQVAYSEBJWIHWOEBURLPSFAGJKTOHWZHYHLIFVKKRQSTZSPQFPTRAYDHZQDNLZAZVGVELZWHNDHGJAJBZQVFJGISRUIOWSNOEGDOLZWHJWPIDOWGKZXRDAJUIRJNVKKTRVIWZSPGDBCAEWPVRWHAQKWGKKPTYSRSYHGTZWOYVLCSAKPVRWHODGICEVWEKSUGGUTTWFZWEJIOTWWTVDGDFGKHRLCTLZWHJDNSSFZHYDICSEATLUIHWJEBKRIHWJKCDZTLDAOHYDIZWTARVHHAQKOVVDVAAFJCFWPIFLOOPVIHWAIDVWPNVLDSEWWALDWIXKTDSFZHNLGLWVPVRWHTSAHHZOAYGMYCLOSNLZWFUONSWWEHKDZELAISNRBAFLDOKVPYKFALKJJEKKWBUBDUJWIWEHPNVLDOKVIRWLYVVGDULLDOKVQLSUGVRQSSSLDSIZTLDKDSSDRKWVWGKHEOJLSCRQSSZWHCFNTDSLEHRQSTZWJGYHAAMYDSURJTSFZGRBHSZWLCZQIIFYDSIIXNYWNOKLINAEIMELBMQFKHPRJRFSISJWDMLAPHFWLEDDSVVQIHSLDSRUSHWJPVRWVANWWBRZUUDKDFZHZAFVWKRBIHSLBZVZXNLGPVVGPRCSJRJKTNWNAFJDLILSJMDRGE
In [31]:
print(getIndexOfCoincidence(encrypted))
0.04456591982118284
In [32]:
prob2 = getProbabilities(encrypted)
printProbabilities(prob2)
A	0.0481
B	0.0194
C	0.0329
D	0.0536
E	0.0398
F	0.0330
G	0.0410
H	0.0547
I	0.0363
J	0.0374
K	0.0579
L	0.0498
M	0.0117
N	0.0227
O	0.0410
P	0.0308
Q	0.0193
R	0.0363
S	0.0615
T	0.0351
U	0.0232
V	0.0492
W	0.0805
X	0.0183
Y	0.0230
Z	0.0434
 	0.0000
In [33]:
showProbabilities(prob2)
In [34]:
def showProbabilities2(probabilities1, probabilities2):
    index = np.arange(len(alphabet))
    xx = [x for x in alphabet]
    yy1 = [y for y in probabilities1]
    yy2 = [y for y in probabilities2]
    plt.bar(index, yy1, 0.35)
    plt.bar(index + 0.4, yy2, 0.35)
    plt.xticks(index, [letter for letter in alphabet])
    plt.title('Probabilities')
    plt.show()
In [35]:
showProbabilities2(probabilities,prob2)
In [36]:
pom1 = probabilities.copy()
pom1.sort(reverse=True)
pom2 = prob2.copy()
pom2.sort(reverse=True)
showProbabilities2(pom1,pom2)
In [37]:
decrypted = caesarDecrypt(encrypted, 3)
prob2 = getProbabilities(decrypted)
showProbabilities2(probabilities,prob2)
In [38]:
print(decrypted)
AKRTNACNMQXBXEVEDBLPLLKOYXCPGOGHQYPZXOTIHBEXXDONPTWTGEVEKZPBXZITACIWXZJEZQWTRHSRQQWPMZJEDYPZXOHHQZGJLEGWQOTIHZVADAIDXLHSAPWTLLMSFLWTKOOUSEITKOORFBGHTJGSTBEJMJCUFETBMSSRQMXTLZBTTBHWXWTAZAATTGSEYQWTKPOLUQIAXLBDFETNEWQOYBPVTTBSTBBTTYHYARZCHHHHQZGJLEKOGISVXEGORQQJMEVESFGALSSSMVHIHSSREBAUPPZLUCIWXJZLOLBTTROIZFAAXLHEYKDLTYRSTBHTMECWAOZPGOOTQBBPEWTIDPIPGOZAEQLTEWQOYBHJIASRFFBTMSSWAJPCLLWDSLNDNLBDSBIDGPCTTBBIAPFEBFTHBOORQPPNMSSYHBRDFPOGMFCCHHHHQDXGEHSNFXCSLSSLALZTWLBDFETGXHOSZLIWBYUBGQIWXOWSTBHHHMOCWPWTVLAEMKSHTJGSTBCDHEVEKXXCMNCMQXVPBYBOFLCTHQSMEXNHMSSMAQWTKYCTAKTDYPASMVHHAPKEXIRDFPOGMFCDKYCTOLBTTROIZPPXWEVEILBPGTZLTXKTHYSFAOHJIASRNRINHFQAZQXUMSSYMFCIVZAEEXXSMSSGUOAQNEWCMKHPRDGHQDDNHFONPYGXGRHHQYTHMZTEYYTHMZFWAOHILLMSFETVBCZIHBPIXPAAXIPCWJCUOXCIALJEAKTIBWZTTXIHVZAEMDPXGHSLXQWTPZAAZPWTPLGDAKTPGOGHQQDDDSSREMXCGTBGFLIWXOCODQDHITBAZAPHLSSSBXCHAPGAZDBNWLFTQOWPTESFUSTUBGSPUBHIHOOYYVSPKESRTXPIXQWVQCXKXAWEEQDSTJHHQHXCZHOSOLBXGRROIKIWXDHRQBIPGOVETBPGWSSREFCVUFHWTXIHAPGAZDWTVZILPKIWXLFSAETHMZDPQAPCWDOIPTWPMHOSFEPIRZIWQOTHBYUIZDBNZZCDILBPGEVEILBPGHOSMPWPFPRTAITIATAHQXGLALHHQOSPNRVTQOWPWMSEZADXGRGOEETHTYUIZPITTOCFFEPIFJRADQTGALGPGKUXOPTIHBHZXTBSFLSPRXMDMOITKSOSBRCUBGSFUSTHDPWNEQDSTJGTMOHDFTBEEXXSMSSKUKVXGPJEDETPKOHEXIDUTYMOZBIWTEQOGISSHEVAFQWTGSSSMFSAHZYYARWTKPWWMKIPPTTEMKSXEWAADONNHFFDMRVWMPFBGQADHVMOGETGXDOYEETTEPJEZJDCMSGOGQDUMSSYQXGHAPGHMIAWTGSAXIHWXWWKQPIDXLHAZAPAEEVESLLCLDVEXFZTLECGQQPCWLZLFETRHXDAZVHWXWWKQPIDDPSPNRIIAPZAEQBDGEVORQWTRPOREETAESOVQQDHITBFUSTHDPWNEBKTKJRAKXCSBQGHQADCMTGHMIAZBWZHQOPAECWGTQHPRDHHQTDBTYTODPWTMSCUSEILALHASOPCWXORDFPVXEVAFTPHTYRAECDGMSSFUSTHDPWNETWTGEVEFFBTVLAEFETGXOPEBITCMJCFIXNHHQUEFQXCZZITACXITYRLUHTABPGTTBSWTGSFAOVDMESNMIAPUZITUQLTEWGOFETNPPFEYXGGBPRAZAUDKPZEHBCBHYHHEQWTZTFLTXSPEWGHQIXZXOHOQXIPGOOLXQWTZZKNEPWTETYEPQDVXEONPXAAMSSCAJEPGJGHQIXZXOHOWBTEUFHWTBCIAPHIYBLPLRSTFFCVHGSREETQXRONFLIWBYYANLJIMSSSWBXCLLBDFLLDGOSRUCWTALREYFCBBYRBGQCDMZBEILGSWTRHQPPNTMCUFBBPGOGHQQWDNRVTTBSLAZZLKCDGZZHTQKTBAZKEHBGIAPZAEQSPRZTTTBAPLEAOZQWWXEOKQPWTKECADLDBLSSDZBKTKDSTQVTHHYPERLGTMSSRQTPHGZHHUKVXGTHBGQPHITBNUKVLAPSLMKSPLECOXXCSLLMSTBCDPXMDQXGWXCSYARAAUPGHGQXCMZAODODLPTHHELBTOTQTGXAHTYRSAJTUELLAZAXURZIHMSTCMDDUZCXKXDYEUKHQREVEZFVWMJCUDETPWWZGALUUTYRAIXNWXHSNFXQDNEVIEYJHBYSSETTAEDVEIXHIALHFDFVWMPBEPPWTWLZWMVHQXPBSGZWPZLHLQPHVBCZTTXIHAPRIPKIHHXICTXHZGZKHATIDLAWNMKSLALHWMPHWXECDAQDBHCFOITXIAYCOZBIDVZAEZFVWAPFTAETAISSREETHTEROIKDCTDHOAIXCMSSKUQRWXYONPIPLAZKSTBSXWNFYTLLTOPFAXIDUTDIDPBCHAPVEMOSPLZFTACPZGZQKUKVAHHROIKDCMSSDALGHAPIPBBSPGOCPQAXITYRWTXIHAZILPPWTLPSBGQPHFLZLXFIIEPPLMZZIATBGIFIWTWCNSQPXEEVAFIDDDPRUBXIWXCFISEIRNCWOGPPCWEVAFPPXWHVAFXGTRZIAOONXGRTODTWPMDHHMQIDRZISMVHHAPBEHBGNHFAIZAIWTEGAUAQJMESLXJTLALHYARGTTNFYUKVUHCHHMQLDGEROYBCDZZCDUCXSHDOYEPWTRZIDAKIZGZKTTXIIALHSMFSPGOHWUOATWEVAFPIPBWFOGKSLXWZSMVHHAPHHMQLDGEROZLWPKXWFFEPIWZBTPLCDZZCDMKSHAPIPBBSPGOHOXAPQHFHTTBEXXDONPQWTLVSIZPPCWPJEDVIWBYUTTFHXLHVAFFAAWZGAKPIWXWWTFITQELQKFEXCZTZLOLBTMZMOGOLXGOCWQSTGRXCRZFCVTYRTMHTIAPTLMUPCWMFIZDXILAINMQCXZSHWTXIHRZIRBXNHTJGSTBIWTEZOAHTSHFHORQWTVZFNQODUMSOTEBNTLLBDFEPILLWDUIAVBGSYARIWKPSGGBHHXDSVQONCBRVTFLVJXDGMKKPBXLBDUCNDNSOVQKIVNPGSQAXIUPTODBIWXXCNFEHJIJCUEEPAEMSMUKTLXWZSTBIWHFUHFPWTWMSSGOTIHRIEEPIWTEGNMJTQXQCRQQWTFZBTTTPHNAOLXOXVAEGAKPHWXTOGDBTPEWFISEIIALHSMVHPGOZAIEDLMSOTFTXGEPRTTXIHMLWLIBAAMSSNQUISTJVEDEJHULBDFLDZAPFIZQDIAPFOAJPCWEVEDBLPLEVERIPMTYRTTBSPRDTOAACDPEVEDBHIAPTLMUHPRDVEMKSXYEVAFXXCMDDUZREIATGNUDWIHQTGABHNHFFHQXSPGOHHQKWTPPBTARIPGOZOOHTSMSSDALGWXOVADAANZZBEIETCMSSRQTPHTVBOOHXCZLUAUKHIMSSWUKSDPDVEGMETWLBDEETDIPRIFXCSMSSRQPJGXPBOGDWLTDHHQIXIMWSOXAIWBYUSUQIXGRCNFETAXOUEIETGXDHHQCAPQDOYEETWXCSIFYTHTJGSTBPCWDVESXKTBEHOTFBLXWZCAJTIAPSVQKXCZLYNAZZXGRQAYBPVTTBTAQWTPTBDATHWXFDPQAPCWDVEAMTSBEONPQWTKPKAEQWTETHTXBDAWEVIZDLXMSTIHBHZXTBSACUATICNTFHPKXVEDBXIUPGAKPWTTYRHQDPKXTHTAETGGZKWTXIHFJBAYBHPRDVEIEPIBDHHMQQXEWGAKPHWXYCOFEPITTBTEXNHAPONPETIPTFLQAWXLEOIXFHIALHNQAHPRDGHQKDDMSOTMFCILLMSTBPCWSSTIFGAXOVIEQPXEHSLXFHIALHMMOZHTJGSTBCDHEVAFXXCMDOYEETPGOVEFTXGEPRHUPIPBWVADATGTYRAIXNWXQZEITTAEHVEZETGAFGBMKSRTXSIZQWTKPKEDBIWXQWVQPZTBYGRQXSNYZFHUJXHXPWSTXCIALJEFLZXEWMOGQDCBRVTYVSTTCGAKPWTRZILXEPKXJCUDCDDWLBDKLJGYWOXUKIWXXCRZFCVLLMSTBPCWLKAKETVHPGWQIATOPFYPXNIAPTLMUPCWEVERLDSPPFENODJZSHAZATKXCMDMVIWTEHHQOTABEHLQYAPVVWMBBIJLPRTAZDBXXCRZFCVLLBDQSTCBYUSMKSPEWHHQAPNMSSGUOAHTEHRKFCVMZHHUKZDYYOMQPIDLLMTAFILAPBIFZPBXLHNUDWIUFHSTBCTOPFHUQDCMSSRUDWIHYSAZAPHBEUOFQDLTCRSFETTGOCFFETBHYHHFETXFASTNBVPGECLALZHHXOLUZTUNWONPQWPMEKIDITSMSOTEQPXEQOSFBGPGOTAEQTGXLQHFFBTLSSGMSTPZFSSEXIATDHIFZPBXECTTBAPLERAKYJIHYSTTBXBIPHCMJTPMYWGTQPAHYUWUQWIAPTIHBHZXTBSMKSIALHSMFSLALHAUKINHFUOFJNCTXSYQQXHMSOTZFRDWPAUEPPNLDVEZLDITTBTFEPILLMSUPIWTEGAYJATLLMSEETCHZHAUKIIALHSMVHPPPZLUPIWTEAEFEJHTWSMEXNHLSSNALIPBYHTTXICXTHHQOIWTEGAKPIWXYHHMQADHVGAFETGPTHHFEPILPMEEIXZXLQOMIDUBCSAZAIWTEGAKPLDFLBTTBGTLZBLKQDBHCFOIKXVAEONPQWTGJCUXIQTFTBEMKSPPLMIFCATPHSLXPWTYPZTFEPIAZFRUAWDPPJEDPWTAPORPQWTDTBGOLBXGROLAKVIAPDAEPPVXTBHQZPBXLBDIETCAPGEQPIWXQWVQPZTBYGHQPPNLDOYEETLXWZMKATPKDOYEETXWZBTEBTQNEKHMQNDNWZHMSTNHFFSWBXCLCSAPVIDFZFRATCXZSHAETTAELBDMPXGXNYOZFHWTYHHMSTIHVWLXVDJBWZHMSTHNADEDFCWXCSTAKXVAEGOFETNUCCUSEIHNADEDXCSTYCTTBGHMZCLRLGWBXONPADLGEVEFTDHTEKEXIWTALRNFBPIXYPUFXBDNEVFGIDGLZKHQKWTLECPEXCSUPUIZPIDELIGTTWPMTGIFPPNLDVEMTWNLLMSTBXLTDCUFXWJGEWNSQDSTJONPFVDMLKAKQDPIWOCQFCIAPKOAAXSGPJEDPTTGMSFAOTPGOHHQOTLTDONAISRALZKBFIPGOWHQXGSTVWNPLUPLZFTACPWNXAIZDHDBRCTACUBRSCBNVPCWTKEZQGXZSHQGFTIMZHHQMXITYRIXLDZXOROIKLTEWKHMQHWHFZDFETGXMSBGQIWXQINZFTHMWWTFITQELQKFEXCZJCUQSTGLPHEKBHDGLBDIEPIPLGTTXISHTBGNRIIALHHMAPABEHLQPEXGYWNSTWTXWONPQWPMHOSEMXCGTBGILCSXCTUXCPHMLBDFTXGETBGFEPILEOIXXCSTDHHMQHETYHHMQHPGRBIYJNCBXAYZLIBRYOMQPIDFEWTFLILXWZWTBCIAPUIDIWTTCRTTFHHAPTEXQPHBQGHQZDJEOVAHBYJFASDARIDYSSREHXCYZFJAVQJMDVEPFSCMDOYMTDGWYSXFAPNMSOTFETGXWWTFITIATBGXLDZXOGOYXAXVPTUXTWTGSSCMJTUHCHHQCAPQLBDIETCGTUHFZPBXDVETBPGWEVAFHCDVVWNSXVPBYGTFETLBYROIMPCXDGHQLETWEVEIFCSHHONPQWPMNCMQOXVAEWNAKIWXWSDSBIWTEKAEDGXGYWNSCGDFPORFLTPKLBDALIWTEGTMFALTDHWUOAXGRFOGKSHHQOSFTWPMDAYZXBTMSOTEXNHTDHHMQVPOPVEDQWTLVSIZPXHMSOTELADFZBSTBHPRDDRQQTCWTBGFLQTTQSADACDHEOIZQIWTEGAKPPCWEVAFZPBXQIRFETGBYHOFETGHZAWQIAXLEVAFWTQXOSEEXNHLSSASXXCGZCTMFCILLMSFETXFASTMKSIAPBTTXIATFUHQAPCWEKIDITSMSOTEQPXEEWLXVDJVZILPKIWTCRLKPTTBEHAWBIXFPKOYXCIALHSMVHCXIHGGBHHTYRYARGTFTBEMKSIALHSFOTIVSSDARIIALHSNIPRDSONPPPIAPFWQIAHAPPAOHTSTDHEBLGIPZONPPWTEZCKQAPIBEONPQWTGDVEXXJVAPROGQPCWDOYEPWTIZWNFFCVAPFFUKVTKLHIFKXBFJBIYJNCHEMOGOCPFPGTAJIXMECTIBAAPSSNFEPIAPORPETGMSOTSXKTTYOWRRAHACWEWXCSTHOYFEPIYWSWUKIDMSSDMOZPGOGHQKTKXCGAIFIPGJAODB
In [ ]: