Shiyan12

Задача 2

Dec 27th, 2019
160
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.75 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3.  
  4. import re
  5.  
  6. def find_all(s1, s2):
  7.     res = []
  8.     st = 0
  9.     st = s2.find(s1, st)
  10.     while st != -1:
  11.         res.append(st)
  12.         st += len(s1)
  13.         st = s2.find(s1, st)
  14.     return res
  15.  
  16. # делители числа n
  17. def get_factors(n):
  18.     res = []
  19.     for i in range(1, n + 1):
  20.         if n % i == 0:
  21.             res.append(i)
  22.     return res
  23.  
  24. def decrypt(c, k):
  25.     n = 26
  26.     t = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  27.     k *= len(c) // len(k) + 1
  28.     m = ''
  29.     for i in range(len(c)):
  30.         cj = t.find(c[i])
  31.         kj = t.find(k[i])
  32.         mj = (cj + n - kj) % n
  33.         m += t[mj]
  34.     return m
  35.  
  36. def v_decrypt(dictionary):
  37.     s1 = input()
  38.      
  39.     # избавляемся от всех лишних символов в строке
  40.     s2 = ''
  41.     for c1 in s1:
  42.         if c1.isalpha():
  43.             s2 += c1
  44.            
  45.     # приводим всю строку к одному регистру
  46.     s2 = s2.upper()
  47.      
  48.     # рассматриваем 3-граммы, 4-граммы и 5-граммы
  49.     grs = set()
  50.     for n in [3, 4, 5]:
  51.         for i in range(len(s2) - n + 1):
  52.             gr = s2[i:i + n]
  53.             if s2.count(gr) > 1:
  54.                 grs.add(gr)
  55.     grs = list(grs)
  56.      
  57.     # определяем расстояния между n-граммами
  58.     ds = set()
  59.     for gr in grs:
  60.         d = find_all(gr, s2)
  61.         for i in range(1, len(d)):
  62.             for j in range(i):
  63.                 ds.add(d[i] - d[j])
  64.      
  65.     # находим делители этих чисел
  66.     c = {}
  67.     for d in ds:
  68.         fs = get_factors(d)
  69.         fs.remove(1)
  70.         for f in fs:
  71.             c[f] = c.get(f, 0) + 1
  72.     list_c = list(c.items())
  73.     list_c.sort(key=lambda c: -c[1])
  74.     c = dict(list_c)
  75.      
  76.     # буквы по убыванию частоты встречаемости в английском языке
  77.     en = 'ETAOINSHRDLCUMWFGYPBVKJXQZ'
  78.      
  79.     lens = set()
  80.      
  81.     f = open(dictionary, 'r')
  82.     lines = []
  83.     for line in f:
  84.         lens.add(len(line.strip()))
  85.         lines.append(line.strip())
  86.            
  87.     p = re.compile(r"[A-Za-z]+")
  88.     w1 = p.search(s1).group(0)
  89.    
  90.     # выделение символов
  91.     for k in c.keys():
  92.         cs = []
  93.         for i in range(k):
  94.             s3 = s2[i::k]
  95.             mx_o = -1
  96.             cs.append([])
  97.             for j in range(ord('A'), ord('Z') + 1):
  98.                 s4 = decrypt(s3, chr(j))
  99.                 nu = list(en)
  100.                 nu.sort(key=lambda elem: (-s4.count(elem), -en.find(elem)))
  101.                 nu = ''.join(nu)
  102.                 o = len(set(en[:6]) & set(nu[:6]))
  103.                 o += len(set(en[-6:]) & set(nu[-6:]))
  104.                 if o == mx_o:
  105.                     cs[-1].append(chr(j))            
  106.                 if o > mx_o:
  107.                     mx_o = o
  108.                     cs[-1] = [chr(j)]
  109.         ks = []
  110.         queue = ['']
  111.         while queue:
  112.             v = queue.pop(0)
  113.             if len(v) < len(cs):
  114.                 for w in cs[len(v)]:
  115.                     queue.append(v + w)
  116.             else:
  117.                 m = decrypt(s2, v)
  118.                 w2 = m[:len(w1)]
  119.                 if w2 in lines:
  120.                     print(v.lower())
  121.                     i = 0
  122.                     res = ''
  123.                     for c2 in s1:
  124.                         if c2.isalpha():
  125.                             if c2.islower():
  126.                                 res += m[i].lower()
  127.                             else:
  128.                                 res += m[i]
  129.                             i += 1
  130.                         else:
  131.                             res += c2
  132.                     print(res)
  133.                     quit()
Add Comment
Please, Sign In to add comment