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
| import random, math
eng_freq = {'e':.127,'t':.091,'a':.082,'o':.075,'i':.070,'n':.067, 's':.063,'h':.061,'r':.060,'d':.043,'l':.040}
def score_word(word): clean = word.rstrip('!.,?:').lower() s = sum(eng_freq.get(c, 0) * 2 for c in clean) common = {'the':5,'and':5,'was':5,'not':5,'too':5,'you':5,'this':5, 'it':5,'as':5,'is':5,'congratulations':10,'decrypted':10, 'successfully':10,'difficult':10,'keyword':10,'solution':10} return s + common.get(clean, 0)
def solve_sa(digraphs, chars, words, n_iter=100000, n_restarts=20): best_mapping, best_score = None, -1 for _ in range(n_restarts): m = dict(zip(digraphs, random.sample(chars, len(digraphs)))) sc = sum(score_word(decode(m, w)) for w in words) t = 5.0 for _ in range(n_iter): d1, d2 = random.sample(digraphs, 2) m[d1], m[d2] = m[d2], m[d1] ns = sum(score_word(decode(m, w)) for w in words) if ns > sc or random.random() < math.exp((ns - sc) / max(t, 0.01)): sc = ns if sc > best_score: best_score, best_score = sc, dict(m) else: m[d1], m[d2] = m[d2], m[d1] t *= 0.99995 return best_mapping
|