InterruptDB + AffineSolver

This commit is contained in:
relikd
2021-01-21 02:23:04 +01:00
parent 2cf95914b6
commit 8932ed8fc3
7 changed files with 947 additions and 104 deletions

68
HeuristicLib.py Executable file
View File

@@ -0,0 +1,68 @@
#!/usr/bin/env python3
import re
from RuneText import RuneText
from NGrams import NGrams
def normalized_probability(int_prob):
total = sum(int_prob)
return [x / total for x in int_prob] # math.log(x / total, 10)
RUNES = 'ᚠᚢᚦᚩᚱᚳᚷᚹᚻᚾᛁᛄᛇᛈᛉᛋᛏᛒᛖᛗᛚᛝᛟᛞᚪᚫᚣᛡᛠ'
re_norune = re.compile('[^' + RUNES + ']')
PROB_INT = [0] * 29
for k, v in NGrams.load().items():
PROB_INT[RUNES.index(k)] = v
PROB_NORM = normalized_probability(PROB_INT)
K_r = 1 / 29 # 0.034482758620689655
K_p = sum(x ** 2 for x in PROB_INT) # 0.06116195419412538
#########################################
# Probability : Count runes and do simple frequency analysis
#########################################
class Probability(object):
def __init__(self, numstream):
self.prob = [0] * 29
for r in numstream:
self.prob[r] += 1
self.N = len(numstream)
def IC(self):
X = sum(x * (x - 1) for x in self.prob)
return X / ((self.N * (self.N - 1)) / 29)
def friedman(self):
return (K_p - K_r) / (self.IC() - K_r)
def similarity(self):
probs = normalized_probability(self.prob)
return sum((x - y) ** 2 for x, y in zip(PROB_NORM, probs))
@staticmethod
def IC_w_keylen(nums, keylen):
val = sum(Probability(nums[x::keylen]).IC() for x in range(keylen))
return val / keylen
#########################################
# load page and convert to indices for faster access
#########################################
def load_indices(fname, interrupt, maxinterrupt=None, minlen=None, limit=None):
with open(fname, 'r') as f:
data = RuneText(re_norune.sub('', f.read()))['index'][:limit]
if maxinterrupt is not None:
# incl. everything up to but not including next interrupt
# e.g., maxinterrupt = 0 will return text until first interrupt
for i, x in enumerate(data):
if x != interrupt:
continue
if maxinterrupt == 0:
if minlen and i < minlen:
continue
return data[:i]
maxinterrupt -= 1
return data

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import itertools # product, compress, combinations import itertools # product, compress, combinations
import bisect # bisect_left, insort import bisect # bisect_left, insort
import lib as LIB
######################################### #########################################
@@ -26,6 +27,31 @@ class GuessVigenere(object):
return found return found
#########################################
# GuessAffine : Find greatest common affine key
#########################################
class GuessAffine(object):
def __init__(self, nums):
self.nums = nums
def guess(self, keylength, score_fn): # minimize score_fn
found = []
for offset in range(keylength):
candidate = (None, None)
best = 9999999
for s in range(29):
for t in range(29):
shifted = [LIB.affine_decrypt(x, (s, t))
for x in self.nums[offset::keylength]]
score = score_fn(shifted)
if score < best:
best = score
candidate = (s, t)
found.append(candidate)
return found
######################################### #########################################
# SearchInterrupt : Hill climbing algorithm for interrupt detection # SearchInterrupt : Hill climbing algorithm for interrupt detection
######################################### #########################################
@@ -39,6 +65,9 @@ class SearchInterrupt(object):
def to_occurrence_index(self, interrupts): def to_occurrence_index(self, interrupts):
return [self.stops.index(x) + 1 for x in interrupts] return [self.stops.index(x) + 1 for x in interrupts]
def from_occurrence_index(self, interrupts):
return [self.stops[x - 1] for x in interrupts]
def join(self, interrupts=[]): # rune positions, not occurrence index def join(self, interrupts=[]): # rune positions, not occurrence index
ret = [] ret = []
i = -1 i = -1
@@ -145,7 +174,7 @@ class SearchInterrupt(object):
current = update current = update
continue # did optimize, so retry with same level continue # did optimize, so retry with same level
level += 1 level += 1
print() print('.')
# find equally likely candidates # find equally likely candidates
if self.single_result: if self.single_result:
return best, [current] return best, [current]

74
InterruptDB.py Executable file
View File

@@ -0,0 +1,74 @@
#!/usr/bin/env python3
import os
from HeuristicSearch import SearchInterrupt
from HeuristicLib import load_indices, Probability
class InterruptDB(object):
DB_NAME = 'data/interruptDB.txt'
def __init__(self, data, interrupt):
self.iguess = SearchInterrupt(data, interrupt)
self.stop_count = len(self.iguess.stops)
def make(self, keylen):
def fn(x):
return Probability.IC_w_keylen(x, keylen)
score, intrpts = self.iguess.sequential(fn, startAt=0, maxdepth=99)
# score, intrpts = self.iguess.genetic(fn, topDown=False, maxdepth=4)
# score, intrpts = fn(self.iguess.join()), [[]] # without interrupts
for i, skips in enumerate(intrpts):
intrpts[i] = self.iguess.to_occurrence_index(skips)
return score, intrpts
@staticmethod
def load():
if not os.path.isfile(InterruptDB.DB_NAME):
return {}
ret = {}
with open(InterruptDB.DB_NAME, 'r') as f:
for line in f.readlines():
if line.startswith('#'):
continue
line = line.rstrip()
name, irpc, score, irp, kl, nums = [x for x in line.split('|')]
val = [int(irpc), float(score), int(irp), int(kl)]
val.append([int(x) for x in nums.split(',')] if nums else [])
try:
ret[name].append(val)
except KeyError:
ret[name] = [val]
return ret
@staticmethod
def write(fname, score, irpchr, irpmax, keylen, nums):
nums = ','.join(map(str, nums))
with open(InterruptDB.DB_NAME, 'a') as f:
t = f'{fname}|{irpmax}|{score:.5f}|{irpchr}|{keylen}|{nums}\n'
f.write(t)
def populate_db(irp_chars=range(1), startkeylen=1, maxkeylen=32):
oldDB = InterruptDB.load()
oldValues = {k: set((a, b, c) for a, _, b, c, _ in v)
for k, v in oldDB.items()}
for name in [
# '0_welcome', 'jpg107-167', '0_warning', '0_wisdom',
'p0-2', 'p3-7', 'p8-14', 'p15-22', 'p23-26',
'p27-32', 'p33-39', 'p40-53', 'p54-55'
]:
fname = f'pages/{name}.txt'
print('load:', fname)
for irp in irp_chars: # interrupt rune index
data = load_indices(fname, irp, maxinterrupt=20)
db = InterruptDB(data, irp)
irp_count = db.stop_count
print('analyze interrupt:', irp, 'count:', irp_count)
for keylen in range(startkeylen, maxkeylen + 1):
if (irp_count, irp, keylen) in oldValues.get(name, []):
print(f'{keylen}: skipped.')
continue
score, interrupts = db.make(keylen)
print(f'{keylen}: {score:.4f}, solutions: {len(interrupts)}')
for x in interrupts:
InterruptDB.write(name, score, irp, irp_count, keylen, x)

View File

@@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from RuneRunner import RuneRunner from RuneRunner import RuneRunner
from RuneText import Rune, RuneText from RuneText import Rune, RuneText
import lib as LIB
######################################### #########################################
@@ -137,3 +138,38 @@ class SequenceSolver(RuneSolver):
def __str__(self): def __str__(self):
return super().__str__() + f'\nf(x): {self.FN}' return super().__str__() + f'\nf(x): {self.FN}'
#########################################
# AffineSolver : Decrypt runes with an array of (s, t) affine keys
#########################################
class AffineSolver(RuneSolver):
def __init__(self):
super().__init__()
self.current_key_pos = 0
self.reset()
def reset(self):
super().reset()
self.KEY_DATA = [] # the key material
self.KEY_INVERT = False # ABCD -> ZYXW
def run(self, data=None):
self.current_key_pos = 0
super().run(data=data)
def rotate_key(self):
self.current_key_pos = (self.current_key_pos + 1) % len(self.KEY_DATA)
def cipher(self, rune, context):
r_idx = rune.index
if self.KEY_INVERT:
r_idx = 28 - r_idx
r_idx = LIB.affine_decrypt(r_idx, self.KEY_DATA[self.current_key_pos])
self.rotate_key()
return Rune(i=r_idx)
def __str__(self):
return super().__str__() + \
f'\nkey: {self.KEY_DATA}\nkey invert: {self.KEY_INVERT}'

665
data/interruptDB.txt Normal file
View File

@@ -0,0 +1,665 @@
# file-name | number of interrupts | score | interrupt-rune (index) | key length | interrupts (starting with index 1 for first occurrence)
0_welcome|25|1.17420|0|1|
jpg107-167|5|1.13036|0|1|
0_warning|1|1.85685|0|1|
0_wisdom|5|1.52270|0|1|
p0-2|34|0.98839|0|1|
p3-7|26|1.00438|0|1|
p8-14|66|0.99935|0|1|
p15-22|72|1.00056|0|1|
p23-26|37|0.99396|0|1|
p27-32|52|0.99140|0|1|
p33-39|40|0.99644|0|1|
p40-53|125|1.00174|0|1|
p54-55|6|0.98082|0|1|
0_welcome|14|1.70031|0|8|1,4,5,6,7,11,12,14
0_welcome|14|1.70031|0|8|1,4,5,6,7,10,12,14
0_welcome|14|1.70031|0|8|1,3,5,6,7,11,12,14
0_welcome|14|1.70031|0|8|1,3,5,6,7,10,12,14
0_welcome|14|1.74248|0|12|4,5,6,8,11,12,14
0_welcome|14|1.74248|0|12|4,5,6,8,10,12,14
0_welcome|14|1.74248|0|12|3,5,6,8,11,12,14
0_welcome|14|1.74248|0|12|3,5,6,8,10,12,14
jpg107-167|5|1.19072|0|8|1,2,3
jpg107-167|5|1.25971|0|9|1,4,5
jpg107-167|5|1.19196|0|10|1,3,4,5
jpg107-167|5|1.17869|0|11|1,3,4,5
jpg107-167|5|1.09583|0|12|4
jpg107-167|5|2.14768|0|13|2,3
p0-2|20|1.02741|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p0-2|20|1.09547|0|2|2,3,5,6,8,10,11,12,14,17,18,19,20
p0-2|20|1.14150|0|3|1,2,5,7,9,11,14,15,16,17,18,19,20
p0-2|20|1.13231|0|4|3,4,6,9,11,12,13,14
p0-2|20|1.16489|0|5|1,2,3,4,5,9,12,13,19
p0-2|20|1.16355|0|6|1,2,5,7,8,11,14,15,16,17,18,19,20
p0-2|20|1.26817|0|7|1,3,5,6,7,9,11,13,14,15,17,18,19
p0-2|20|1.16853|0|8|2,5,6,7,10,14,15,16,17,18,19
p0-2|20|1.24714|0|9|1,2,3,7,8,13,14,15,16,17
p0-2|20|1.21659|0|10|1,2,3,4,5,9,12,13,19
p0-2|20|1.28945|0|11|1,3,5,6,10,11,12,13,14,15,16,17,18,19,20
p0-2|20|1.29341|0|12|1,2,5,8,9,10,13,14,15,16,18,19,20
p0-2|20|1.22812|0|13|1,3,4,5,7,8,9,10,11,12,13,14,15,16,19,20
p0-2|20|1.34456|0|14|1,4,5,6,8,12,13,14,16,17,20
p0-2|20|1.29400|0|15|1,3,4,5,7,9,13,14,15,16,17
p0-2|20|1.25527|0|16|1,4,6,7,12,13,14,15,16,17,19,20
p0-2|20|1.38448|0|17|1,2,5,6,8,9,12,15,16,17,19
p0-2|20|1.36640|0|18|1,2,5,8,9,10,13,14,15,16,18,19,20
p0-2|20|1.36640|0|18|1,2,4,8,9,10,13,14,15,16,18,19,20
p0-2|20|1.27259|0|19|2,4,5,6,7,8,10,11,12,18,19,20
p0-2|20|1.27259|0|19|2,3,5,6,7,8,9,11,12,18,19,20
p0-2|20|1.30972|0|20|1,2,3,4,5,9,12,13,17
p0-2|20|1.36319|0|21|1,4,5,6,7,12,14,15,16,20
p0-2|20|1.36319|0|21|1,3,4,6,7,12,14,15,16,20
p0-2|20|1.35038|0|22|1,2,4,5,6,9,10,12
p0-2|20|1.36594|0|23|1,2,4,5,6,7,8,9,11,13,14,15,16,17,18,19
p0-2|20|1.37714|0|24|5,7,8,10,13,15,16,17,18,19,20
p0-2|20|1.37039|0|25|2,3,4,5,6,12,15,18
p0-2|20|1.33846|0|26|1,2,3,4,5,7,8,9,10,11,13,14,15,16,17,18,20
p0-2|20|1.32597|0|27|2,3,7,11,12,14,15,16,17
p0-2|20|1.45607|0|28|2,3,5,6,8,9,11,13,14,15,17,18,20
p0-2|20|1.49231|0|29|5,7,8,10,11,14,17
p0-2|20|1.31545|0|30|1,2,7,8,10,11
p0-2|20|1.40837|0|31|2,3,4,5,6,7,8,12,13,15,18,20
p0-2|20|1.39740|0|32|1,2,3,4,5,6,7,8,9,10,11,12,13,14
p3-7|20|1.03220|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p3-7|20|1.07427|0|2|1,4,6,7,8,11,13,15,16,18,19,20
p3-7|20|1.11940|0|3|1,2,3,6,10,11,12,13,14,15,16,17,18,19,20
p3-7|20|1.08906|0|4|1,4,6,7,8,9,10,11,13,15,16,20
p3-7|20|1.11979|0|5|1,2,3,4,5,6,9,13,20
p3-7|20|1.12579|0|6|1,4,6,11,13,15,17,18,19,20
p3-7|20|1.12094|0|7|1,2,3,7,9,10,11,12,13,20
p3-7|20|1.14217|0|8|3,4,5,6,7,9,10,14,16,17,20
p3-7|20|1.20440|0|9|1,2,5,7,12,14,15,16,17,18,19,20
p3-7|20|1.15763|0|10|3,4,7,8,10,11,12,13,15,16,17,18,19,20
p3-7|20|1.16279|0|11|2,6,9,11,14,15,16,17,18,19,20
p3-7|20|1.21542|0|12|1,4,6,11,13,15,17,20
p3-7|20|1.20188|0|13|4,5,6,7,8,14,17,18,20
p3-7|20|1.15334|0|14|1,2,4,5,14,16,17,18,19,20
p3-7|20|1.22557|0|15|1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p3-7|20|1.24515|0|16|3,4,5,6,7,9,10,13,15,16,20
p3-7|20|1.19192|0|17|1,2,3,5,8,9,10,11,12,13,15,16,17,18,19,20
p3-7|20|1.19192|0|17|1,2,3,5,8,9,10,11,12,13,14,16,17,18,19,20
p3-7|20|1.22136|0|18|1,2,3,5,6,7,9,11,13,15,16,18,19,20
p3-7|20|1.15375|0|19|2,4,6,7,8,10,13
p3-7|20|1.23523|0|20|3,4,5,8,9,10,11,16,20
p3-7|20|1.15873|0|21|1,2,3,7,13,14,15,16,17,18,19
p3-7|20|1.24170|0|22|1,4,5,9,10,11,12,13,16,20
p3-7|20|1.28268|0|23|1,2,7,8,9,18,20
p3-7|20|1.29784|0|24|2,4,5,7,8,9,10,13,16,17
p3-7|20|1.29831|0|25|4,6,7,8,9,10,12,14,20
p3-7|20|1.29831|0|25|3,6,7,8,9,10,12,14,20
p3-7|20|1.34493|0|26|2,3,6,7,8,14,17,18
p3-7|20|1.31854|0|27|1,2,5,6,8,9,10,11,13,14,17,18,19
p3-7|20|1.21213|0|28|1,3,4,7,9,12,13,14
p3-7|20|1.22641|0|29|1,2,3,4,6,7,9,10,11,15,16,17,18,19,20
p3-7|20|1.33157|0|30|3,4,5,8,9,10,11,15,20
p3-7|20|1.22996|0|31|1,3,5,7,8,9,12,16,17,18,19
p3-7|20|1.32281|0|32|2,4,5,6,7,9,13,15,16,17,18,19
p8-14|20|1.02738|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p8-14|20|1.07560|0|2|3,4,7,9,10,12,13,14,15,17,19,20
p8-14|20|1.07560|0|2|3,4,7,9,10,11,13,14,15,17,19,20
p8-14|20|1.07481|0|3|1,3,4,5,6,8,9,10,13,14,18,19,20
p8-14|20|1.10625|0|4|1,2,4,6,8,9,12,13,14,16,17,18,19,20
p8-14|20|1.10625|0|4|1,2,4,6,8,9,11,13,14,16,17,18,19,20
p8-14|20|1.12535|0|5|2,3,6,7,10,15,20
p8-14|20|1.12321|0|6|3,4,5,6,8,9,10,12,13,18,19,20
p8-14|20|1.12321|0|6|3,4,5,6,8,9,10,12,13,17,19,20
p8-14|20|1.12321|0|6|3,4,5,6,8,9,10,11,13,18,19,20
p8-14|20|1.12321|0|6|3,4,5,6,8,9,10,11,13,17,19,20
p8-14|20|1.15344|0|7|1,3,7,8,12,13,18
p8-14|20|1.15344|0|7|1,3,7,8,11,13,18
p8-14|20|1.13589|0|8|1,3,4,6,7,9,10,12,13,14,15,16,18,20
p8-14|20|1.13589|0|8|1,3,4,6,7,9,10,11,13,14,15,16,18,20
p8-14|20|1.10142|0|9|3,4,5,6,7,8,12,13,15,16,19,20
p8-14|20|1.10142|0|9|3,4,5,6,7,8,11,13,15,16,19,20
p8-14|20|1.16123|0|10|1,2,3,9,10,12,15
p8-14|20|1.16123|0|10|1,2,3,9,10,11,15
p8-14|20|1.20399|0|11|1,2,5,6,7,9,10,11,12,16,18,19,20
p8-14|20|1.16824|0|12|1,3,5,7,8,9,10,13,14,16,17,18,19
p8-14|20|1.16412|0|13|1,5,7,9,10,11,12,13,14,15,16,17,18,19,20
p8-14|20|1.21675|0|14|1,3,4,8,11,12,18
p8-14|20|1.16470|0|15|2,3,4,6,12,14,19,20
p8-14|20|1.16470|0|15|2,3,4,6,11,14,19,20
p8-14|20|1.17824|0|16|1,2,4,6,7,9,10,11,12,14,19
p8-14|20|1.26731|0|17|1,2,4,5,7,8,9,10,11,12,15,18,19
p8-14|20|1.26731|0|17|1,2,3,5,7,8,9,10,11,12,15,18,19
p8-14|20|1.22772|0|18|2,3,4,5,6,7,8,12,13,15,16,20
p8-14|20|1.22772|0|18|2,3,4,5,6,7,8,11,13,15,16,20
p8-14|20|1.15869|0|19|3,7,10,11,12,13,14,15,20
p8-14|20|1.22905|0|20|2,4,10,11,12,16
p8-14|20|1.24550|0|21|1,2,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20
p8-14|20|1.31938|0|22|1,3,4,5,7,9,10,13,14,17,18,20
p8-14|20|1.27574|0|23|1,2,3,4,5,7,9,10,11,12,13,15,16,17,18,19,20
p8-14|20|1.27208|0|24|1,3,4,5,8,13,14,16,17,18,19
p8-14|20|1.26316|0|25|1,2,3,4,5,6,7,8,11,12,14,15,19,20
p8-14|20|1.24512|0|26|5,8,10,12,14,15,17,18,19
p8-14|20|1.24512|0|26|5,8,10,11,14,15,17,18,19
p8-14|20|1.25495|0|27|3,6,7,8,10,13,15,17,20
p8-14|20|1.24241|0|28|2,8,10,13,18
p8-14|20|1.28830|0|29|1,2,3,4,5,6,7,8,9,11,12,13,15,16,17,18,19,20
p8-14|20|1.25836|0|30|2,3,4,10,12,13,16
p8-14|20|1.25836|0|30|2,3,4,10,11,13,16
p8-14|20|1.32680|0|31|2,3,4,5,6,7,8,9,10,12,13,17
p8-14|20|1.32680|0|31|2,3,4,5,6,7,8,9,10,11,13,17
p8-14|20|1.37200|0|32|3,4,5,9,14,15,16,17,19
p15-22|20|1.03321|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p15-22|20|1.08294|0|2|1,4,5,6,7,8,9,10,11,14,15,16,17,18,19,20
p15-22|20|1.11161|0|3|7,10,11,14,15,17,19,20
p15-22|20|1.12694|0|4|1,4,7,8,9,10,11,14,17,18,19,20
p15-22|20|1.17689|0|5|1,9,13,14,15,16,17,18,20
p15-22|20|1.18447|0|6|4,5,6,7,10,11,14,15,16,19,20
p15-22|20|1.16426|0|7|1,2,3,4,7,10,11,12,15,18,19,20
p15-22|20|1.16426|0|7|1,2,3,4,7,9,11,12,15,18,19,20
p15-22|20|1.20551|0|8|1,4,7,8,9,10,11,13,17,18,19,20
p15-22|20|1.12313|0|9|1,2,3,4,5,6,7,13,14,15,16,17,18,19
p15-22|20|1.22689|0|10|1,9,11,12,13,14,17,18,19
p15-22|20|1.20322|0|11|1,3,4,5,6,7,8,9,10,11,13,14,15,16,17,20
p15-22|20|1.20322|0|11|1,2,4,5,6,7,8,9,10,11,13,14,15,16,17,20
p15-22|20|1.33634|0|12|1,2,3,4,5,6,7,9,11,16,19
p15-22|20|1.33634|0|12|1,2,3,4,5,6,7,9,11,15,19
p15-22|20|1.27214|0|13|1,4,8,9,10,11,12,14,15,16,17,19
p15-22|20|1.20764|0|14|1,4,7,9,11,12,17,18,19,20
p15-22|20|1.20314|0|15|2,4,6,7,10,11,12,13,14,16,18,20
p15-22|20|1.20314|0|15|2,4,6,7,10,11,12,13,14,16,18,19
p15-22|20|1.22649|0|16|1,4,7,8,9,10,11,13,17,18,19
p15-22|20|1.23966|0|17|2,5,6,10,12,13,14,15,16,19,20
p15-22|20|1.20700|0|18|1,2,3,4,7,9,10,11,12,14,15,16,18,20
p15-22|20|1.31661|0|19|1,3,4,6,7,8,10,12,13,16,17,18,19,20
p15-22|20|1.24893|0|20|1,3,4,5,7,8,9,15,16,18,20
p15-22|20|1.24294|0|21|1,2,4,5,6,7,10,11,14,15,18,19,20
p15-22|20|1.26797|0|22|8,11,13,14,15,16,17,20
p15-22|20|1.23749|0|23|2,3,5,7,8,9,10,11,12,14,18,19,20
p15-22|20|1.44576|0|24|1,2,3,4,5,6,7,10,11,16,19
p15-22|20|1.44576|0|24|1,2,3,4,5,6,7,10,11,15,19
p15-22|20|1.34316|0|25|1,2,3,4,5,9,12,13,15,16,17,18,19
p15-22|20|1.30761|0|26|1,4,8,9,10,11,12,14,19,20
p15-22|20|1.21623|0|27|4,5,8,9,10,11,13,15,16,18
p15-22|20|1.29515|0|28|1,4,6,9,10,11,16,19,20
p15-22|20|1.29515|0|28|1,4,6,9,10,11,15,19,20
p15-22|20|1.28137|0|29|1,2,4,6,7,8,18,19,20
p15-22|20|1.35448|0|30|1,2,4,5,8,10,11,12,14,15,16,19,20
p15-22|20|1.35448|0|30|1,2,4,5,8,10,11,12,13,15,16,19,20
p15-22|20|1.28629|0|31|1,4,6,10,13,14,15,17,20
p15-22|20|1.28629|0|31|1,4,6,10,13,14,15,16,20
p15-22|20|1.30593|0|32|1,5,7,9,12,14,18,19
p23-26|20|1.01750|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p23-26|20|1.05069|0|2|1,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20
p23-26|20|1.07639|0|3|4,7,9,10,13,14,15,16,17,19,20
p23-26|20|1.08017|0|4|2,3,4,5,6,7,8,9,11,13,17,20
p23-26|20|1.09749|0|5|4,6,7,9,11,20
p23-26|20|1.10653|0|6|1,2,4,5,8,9,10,15,18,20
p23-26|20|1.12660|0|7|1,2,3,4,6,8,9,10,11,12,13,14,15,16,20
p23-26|20|1.12015|0|8|4,7,8,9,11,16,19,20
p23-26|20|1.15687|0|9|2,3,4,5,10,11,14,15,17,20
p23-26|20|1.15687|0|9|2,3,4,5,10,11,13,15,17,20
p23-26|20|1.15155|0|10|4,6,8,9,11,20
p23-26|20|1.14671|0|11|2,4,10,12,13,18
p23-26|20|1.17836|0|12|4,6,7,10,15,17,18
p23-26|20|1.17998|0|13|3,4,5,6,7,8,13,14,15,16,17,18,19
p23-26|20|1.27340|0|14|1,3,6,7,8,9,10,11,12,13,14,15
p23-26|20|1.23419|0|15|2,3,4,5,7,8,11,15,17,20
p23-26|20|1.22483|0|16|1,2,7,8,10,11,15,17,18,20
p23-26|20|1.25740|0|17|2,6,9,10,11,12,13,14,19
p23-26|20|1.19365|0|18|5,6,8,10,11,12,13,14,16,20
p23-26|20|1.28342|0|19|1,2,3,6,7,8,9,10,11,12,13,14,15,16,17,18,19
p23-26|20|1.24064|0|20|4,5,6,9,11,20
p23-26|20|1.22244|0|21|1,2,4,5,6,7,8,9,10,11,13,14,15,16,18
p23-26|20|1.20660|0|22|1,2,4,11,12,13,15,16,17,19
p23-26|20|1.24165|0|23|1,2,3,4,5,6,7,8,9,13,14,15,16,18,19,20
p23-26|20|1.26178|0|24|4,6,8,10,13,17,18,20
p23-26|20|1.28908|0|25|1,2,3,4,5,7,9,10,11,12,15,18,20
p23-26|20|1.37480|0|26|2,4,5,6,7,8,9,10,15,16,17,18,19
p23-26|20|1.27444|0|27|1,2,5,7,15,19
p23-26|20|1.37525|0|28|4,5,8,9,10,11,13,14,15,16,17,18,19,20
p23-26|20|1.35329|0|29|1,2,7,10,11,15,20
p23-26|20|1.33391|0|30|2,3,4,5,7,8,11,15,17,20
p23-26|20|1.34269|0|31|1,6,7,9,10,11,12,14,16,17,18,19,20
p23-26|20|1.34269|0|31|1,6,7,9,10,11,12,13,16,17,18,19,20
p23-26|20|1.32161|0|32|4,9,12,14,15,16,18,20
p23-26|20|1.32161|0|32|4,9,11,14,15,16,18,20
p27-32|20|1.02674|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p27-32|20|1.09852|0|2|1,2,3,5,7,10,11,14,17,18,19,20
p27-32|20|1.11652|0|3|2,3,4,5,6,7,9,10,12,13,14,15,16,17,19,20
p27-32|20|1.12887|0|4|1,3,4,8,9,11,14,15,18,19,20
p27-32|20|1.11581|0|5|1,2,4,7,8,9,10,15,18,19
p27-32|20|1.17275|0|6|1,2,7,8,9,11,12,13,15,16,17,18,20
p27-32|20|1.13075|0|7|1,8,12,20
p27-32|20|1.13789|0|8|1,2,3,4,7,8,11,14,15,16,17,18,19,20
p27-32|20|1.22319|0|9|2,3,4,5,6,7,9,11,12,13,14,15,16,17,19,20
p27-32|20|1.15284|0|10|1,2,3,6,7,9,11,13,16,18
p27-32|20|1.18031|0|11|1,2,3,4,5,6,8,9,10,12,13,14,15,16,18,20
p27-32|20|1.24226|0|12|2,3,7,8,10,13,15,17,18,19
p27-32|20|1.43591|0|13|1,3,8,9,13,15,16,17,18,19,20
p27-32|20|1.24169|0|14|5,6,8,12,13,14,15,16,17,18,19,20
p27-32|20|1.28360|0|15|1,2,5,6,9,10,11,12,13,15,18,20
p27-32|20|1.26968|0|16|1,2,8,11,12,13,15
p27-32|20|1.25300|0|17|2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19
p27-32|20|1.31212|0|18|3,7,8,11,12,13,14,15,16,17,18,19,20
p27-32|20|1.35188|0|19|1,2,7,9,10,12,13,15,19
p27-32|20|1.23995|0|20|3,4,5,6,7,8,9,10,11,12,14,15,17,20
p27-32|20|1.33331|0|21|2,5,6,8,9,11,13,14,18,20
p27-32|20|1.28236|0|22|1,2,3,4,5,6,7,9,10,12,13,14,15,16,17,18,19,20
p27-32|20|1.34843|0|23|3,4,5,6,8,9,10,11,12,13,16,17,18,20
p27-32|20|1.31080|0|24|1,2,4,5,7,8,14,15,16,17
p27-32|20|1.41929|0|25|2,4,5,8,9,10,15,18,20
p27-32|20|1.41929|0|25|2,4,5,8,9,10,15,17,20
p27-32|20|1.49913|0|26|1,2,4,5,6,10,12,13,17,18,19,20
p27-32|20|1.26371|0|27|2,3,4,5,6,7,10,11,12,13,14,15,16,18,19,20
p27-32|20|1.40523|0|28|1,2,7,8,9,10,11,12,13,14,17,18,19,20
p27-32|20|1.40523|0|28|1,2,7,8,9,10,11,12,13,14,16,18,19,20
p27-32|20|1.35531|0|29|2,4,5,7,12,16,17,19,20
p27-32|20|1.37564|0|30|1,2,6,8,9,11,12,13,16,17
p27-32|20|1.42207|0|31|3,10,11,12,16,17,18,19
p27-32|20|1.47450|0|32|2,4,5,6,7,8,9,10,11,12,13,15
p33-39|20|1.01311|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p33-39|20|1.03706|0|2|1,2,4,7,8,9,12,13,14,16,18,19,20
p33-39|20|1.04607|0|3|1,2,7,8,9,10,11,12,13,14,15,16,17,19,20
p33-39|20|1.05383|0|4|1,6,9,10,11,15,16,17,18,19
p33-39|20|1.07528|0|5|1,2,5,6,9,10,11,12,13,14,15,16,20
p33-39|20|1.05553|0|6|1,2,3,6,7,8,10,13,15,16,18,19
p33-39|20|1.09023|0|7|1,2,3,4,6,14,16,17,18,20
p33-39|20|1.08582|0|8|2,3,7,8,9,10,11,12,13,14,16,18,19,20
p33-39|20|1.09219|0|9|2,3,4,5,7,10,11,13,15,18,20
p33-39|20|1.09375|0|10|2,3,4,11,12,13,14,15,16,20
p33-39|20|1.11703|0|11|2,3,4,6,7,10,14,17,18
p33-39|20|1.07502|0|12|1,6,9,10,11,15,16,17,18,19
p33-39|20|1.12352|0|13|3,5,7,10,11,12,13,14,16,19
p33-39|20|1.09918|0|14|1,2,10,11,12,14,16,18
p33-39|20|1.14921|0|15|1,2,12,13,14,15,16,20
p33-39|20|1.14805|0|16|1,4,7,8,9,10,19
p33-39|20|1.15133|0|17|5,6,7,8,9,10,15,16
p33-39|20|1.14625|0|18|1,2,4,5,6,9,11,13,15,16,18,19,20
p33-39|20|1.16930|0|19|3,4,5,10,14,15,16,17,18
p33-39|20|1.14019|0|20|1,7,10,11,12,13,14,17,18
p33-39|20|1.12186|0|21|1,2,3,10,14,15,16,18,20
p33-39|20|1.18371|0|22|2,3,4,6,7,10,14,17,18
p33-39|20|1.17155|0|23|3,5,7,8,9,11,12,13,14,18,19,20
p33-39|20|1.17441|0|24|1,7,8,9,10,11,12,15,18,19,20
p33-39|20|1.19543|0|25|1,2,3,4,6,7,8,9,10,11,15,16,20
p33-39|20|1.15368|0|26|1,2,3,5,8,10,11,12,13,14,16,19
p33-39|20|1.16843|0|27|1,2,3,5,6,8,11,12,15,17,18,19
p33-39|20|1.14560|0|28|1,2,3,4,5,6,10,12,13,14,16,17,19,20
p33-39|20|1.26516|0|29|1,2,4,5,7,8,9,11,12,14,15,16,17,18
p33-39|20|1.18732|0|30|2,3,4,5,9,18,19,20
p33-39|20|1.18732|0|30|1,3,4,5,9,18,19,20
p33-39|20|1.18543|0|31|1,4,5,6,7,8,9,10,11,16,17,20
p33-39|20|1.20787|0|32|1,2,3,7,20
p40-53|20|1.02399|0|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p40-53|20|1.08031|0|2|1,3,4,5,6,7,9,12,13,14,15,16,19,20
p40-53|20|1.12599|0|3|1,2,3,4,6,7,8,9,10,12,14,15,16,17,18,19,20
p40-53|20|1.13207|0|4|1,3,5,8,9,12,14,16,19,20
p40-53|20|1.19210|0|5|1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19
p40-53|20|1.16456|0|6|3,6,7,8,13,14,15,18,20
p40-53|20|1.18063|0|7|1,5,7,8,12,13,14,16,17,19,20
p40-53|20|1.18063|0|7|1,5,6,8,12,13,14,16,17,19,20
p40-53|20|1.17301|0|8|1,2,3,7,9,11,14,15,19
p40-53|20|1.17301|0|8|1,2,3,6,9,11,14,15,19
p40-53|20|1.17827|0|9|1,2,4,7,8,14,15,16,17,18,20
p40-53|20|1.31729|0|10|1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19
p40-53|20|1.21193|0|11|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
p40-53|20|1.30736|0|12|3,5,6,8,13,14,15,18,20
p40-53|20|1.24640|0|13|2,5,6,7,9,14,18,20
p40-53|20|1.23326|0|14|2,3,10,12,13,18,20
p40-53|20|1.28387|0|15|1,2,3,4,7,8,9,10,11,14,17,18,19,20
p40-53|20|1.28621|0|16|1,2,3,6,9,10,14,15,19
p40-53|20|1.22196|0|17|2,9,10,11,15,16,20
p40-53|20|1.22196|0|17|2,8,10,11,15,16,20
p40-53|20|1.29467|0|18|1,3,4,5,6,7,9,12,19,20
p40-53|20|1.18831|0|19|1,2,4,8,17,19,20
p40-53|20|1.40879|0|20|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,20
p40-53|20|1.28088|0|21|1,3,12,13,15,16,17,19
p40-53|20|1.25541|0|22|1,2,6,16,17,18
p40-53|20|1.40086|0|23|1,2,4,5,6,8,9,14,17,18
p40-53|20|1.33411|0|24|3,5,6,8,13,14,15,19,20
p40-53|20|1.33757|0|25|1,2,3,4,5,11,12,13,15,16,17,18,19
p40-53|20|1.41701|0|26|2,4,5,7,12,14,16,20
p40-53|20|1.36980|0|27|1,3,4,5,6,14,15,16,17,18,19
p40-53|20|1.36471|0|28|1,5,8,10,12,13,15,17,18,19
p40-53|20|1.28333|0|29|1,2,3,4,5,6,12,13,14,16,17
p40-53|20|1.37635|0|30|1,2,3,4,5,8,9,10,11,14,17,18,19,20
p40-53|20|1.35834|0|31|1,3,4,5,7,10,12,13,14,15,16,17
p40-53|20|1.35834|0|31|1,3,4,5,6,10,12,13,14,15,16,17
p40-53|20|1.36303|0|32|1,2,3,7,9,10,12,13,19,20
p40-53|20|1.36303|0|32|1,2,3,6,9,10,12,13,19,20
p54-55|6|1.03746|0|2|1,2,4,5,6
p54-55|6|1.07281|0|3|1,3,5
p54-55|6|1.09878|0|4|1,2,4
p54-55|6|1.06062|0|5|4,5
p54-55|6|1.09873|0|6|1,3,6
p54-55|6|1.06063|0|7|1
p54-55|6|1.24998|0|8|1,2,4
p54-55|6|1.05182|0|9|1,3,5
p54-55|6|1.08925|0|10|4,5,6
p54-55|6|1.05905|0|11|5
p54-55|6|1.12840|0|12|1,4,5
p54-55|6|1.10142|0|13|3
p54-55|6|1.09938|0|14|1
p54-55|6|1.07569|0|15|
p54-55|6|1.48604|0|16|1,2,4
p54-55|6|1.12024|0|17|1
p54-55|6|1.16569|0|18|1,3,5
p54-55|6|1.26284|0|19|1,2,3,4,5,6
p54-55|6|1.09613|0|20|1,2,6
p54-55|6|1.31823|0|21|2,3,4,5,6
p54-55|6|1.20713|0|22|1,2,5
p54-55|6|1.15002|0|23|2,6
p54-55|6|1.35198|0|24|1,2,4
p54-55|6|1.21678|0|25|3,5,6
p54-55|6|1.25396|0|26|3
p54-55|6|1.27912|0|27|1,3,5
p54-55|6|1.16753|0|28|
p54-55|6|1.21212|0|29|1
p54-55|6|1.24983|0|30|4,5,6
p54-55|6|1.20054|0|31|2,3,4,5,6
p54-55|6|1.20054|0|31|1,2,3,4,5,6
p54-55|6|1.57587|0|32|2,3
p0-2|20|1.02407|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p0-2|20|1.04697|1|2|3,4,5,6,7,8,10,11,12,13,14,15,16,17,18,20
p0-2|20|1.06981|1|3|2,4,5,6,7,8,9,11,12,13,15,16,17,18,19,20
p0-2|20|1.09958|1|4|3,4,5,7,8,9,10,11,12,13,14,17,18,20
p0-2|20|1.11567|1|5|1,3,4,6,7,9,10,12,13,15,19,20
p0-2|20|1.10132|1|6|3,4,5,6,11,12,13,14,15,20
p0-2|20|1.13492|1|7|8,9,10,12,13,15,16,17,19,20
p0-2|20|1.17054|1|8|1,3,6,10,11,12,13,14,17,18,19
p0-2|20|1.14420|1|9|1,2,4,5,6,7,8,9,12,13,14
p0-2|20|1.17102|1|10|1,2,3,4,6,8,10,12,13,15
p0-2|20|1.13132|1|11|1,2,3,4,6,7,8,14,16,17,18
p0-2|20|1.17298|1|12|2,4,5,6,7,8,9,11,12,13,14,15,18,19
p0-2|20|1.12382|1|13|4,6,8,9,10,11,12,13,14,15,16,17,20
p0-2|20|1.12382|1|13|4,5,8,9,10,11,12,13,14,15,16,17,20
p0-2|20|1.16162|1|14|1,2,3,4,5,6,7,9,12,15,16,17,19
p0-2|20|1.11027|1|15|1,2,3,4,5,8,11,13,14,15,16,17,18,19,20
p0-2|20|1.16261|1|16|2,4,5,6,7,8,10,11,12,14,15,16,17,20
p0-2|20|1.14835|1|17|1,2,3,4,6,8,11,12,14,15,16,17,18,19,20
p0-2|20|1.13921|1|18|1,8,9,11,13,15
p0-2|20|1.11525|1|19|3,4,5,6,9,10,11,12,14,17,19
p0-2|20|1.21673|1|20|2,4,7,8,11,12,14,15,16,18,19
p0-2|20|1.24634|1|21|8,9,11,12,13,15,16,17,19,20
p0-2|20|1.17596|1|22|1,5,6,12,14,16,17,18
p0-2|20|1.18545|1|23|2,4,10,11,17,18,20
p0-2|20|1.21885|1|24|1,3,6,10,11,12,13,14,17,18,20
p0-2|20|1.25831|1|25|1,2,4,5,8,9,10,12,13,15,19
p0-2|20|1.15806|1|26|1,2,3,8,12,18,20
p0-2|20|1.16636|1|27|1,2,3,4,5,6,7,8,10,11,12,14,15
p0-2|20|1.22692|1|28|1,2,3,8,10,12,13,14,15,16,17,19,20
p0-2|20|1.21217|1|29|1,2,5,6,8,9,11,12,13,14,15,16,17,18,19,20
p0-2|20|1.18605|1|30|3,4,6,7,11,13,14,18
p0-2|20|1.18605|1|30|3,4,6,7,11,13,14,17
p0-2|20|1.22297|1|31|1,2,3,5,6,7,10,13,15,16,17,18
p0-2|20|1.18155|1|32|1,2,3,4,5,6,7,9,11,13,14,15,16,17,18,20
p3-7|20|1.03121|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p3-7|20|1.08830|1|2|1,2,5,8,9,10,11,12,13,16,17,18,19,20
p3-7|20|1.08776|1|3|1,2,3,4,5,6,9,10,14,15,16,17,18,19
p3-7|20|1.12896|1|4|1,2,5,6,7,8,9,10,13,16,17,18,19,20
p3-7|20|1.11574|1|5|1,2,5,10,16,18
p3-7|20|1.12661|1|6|1,2,3,4,6,7,9,10,13,16,17,18,19,20
p3-7|20|1.09847|1|7|3,5,6,7,8,9,18
p3-7|20|1.14314|1|8|1,2,5,6,7,8,9,12,13,16,17,18,19,20
p3-7|20|1.14698|1|9|1,2,3,5,6,7,9,10,12,13,14,16,17,18,19,20
p3-7|20|1.15070|1|10|2,3,7,11,16,18,20
p3-7|20|1.17667|1|11|7,9,10,11,12,13,15,16,18,20
p3-7|20|1.19611|1|12|1,2,3,4,5,7,9,10,13,16,17,18,19,20
p3-7|20|1.17290|1|13|2,4,5,6,12,15,16,18,20
p3-7|20|1.13563|1|14|1,2,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p3-7|20|1.17231|1|15|1,2,3,4,5,6,7,10,16,18,19
p3-7|20|1.21156|1|16|1,2,9,12,13,16,17,18,19,20
p3-7|20|1.19136|1|17|1,2,3,4,6,7,8,9,10,11,12,16,17,19,20
p3-7|20|1.18367|1|18|2,9,13,14,16,20
p3-7|20|1.18471|1|19|3,6,8,10,11,12,13,14
p3-7|20|1.24049|1|20|2,9,10,13,19,20
p3-7|20|1.16758|1|21|4,5,6,7,8,9,10,11,12,14,15,16,17,18
p3-7|20|1.21398|1|22|1,3,4,7,9,10,11,14,15,18,20
p3-7|20|1.27246|1|23|2,3,5,15,16,19
p3-7|20|1.26091|1|24|2,3,4,6,7,9,10,14,18,20
p3-7|20|1.26091|1|24|2,3,4,5,7,9,10,14,18,20
p3-7|20|1.23294|1|25|1,3,4,5,6,7,8,13,15,16,17,18,19,20
p3-7|20|1.27796|1|26|1,2,5,7,10,11,12,13,14,20
p3-7|20|1.20406|1|27|1,3,4,5,6,7,10,11,12,13,14,16,19,20
p3-7|20|1.22499|1|28|1,2,5,6,7,8,11,12
p3-7|20|1.18379|1|29|1,2,7,9,10,12,13,14,15,16,17,18,19,20
p3-7|20|1.26032|1|30|1,2,3,4,5,6,7,10,11,13,15,18,19,20
p3-7|20|1.22724|1|31|1,3,4,9,11,13,14,19,20
p3-7|20|1.24835|1|32|1,3,4,6,7,9,13,14,16,17,18
p8-14|20|1.03252|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p8-14|20|1.07297|1|2|3,4,6,7,8,9,11,13,14,15,16,17,18,20
p8-14|20|1.07551|1|3|3,4,5,6,7,8,9,10,11,12,13,14,16,17,18
p8-14|20|1.09790|1|4|1,2,3,5,6,7,8,9,11,15,19,20
p8-14|20|1.12142|1|5|1,2,5,6,7,8,9,10,11,12,14,15,17,18
p8-14|20|1.14775|1|6|2,4,5,11,13,14,15,17,20
p8-14|20|1.14694|1|7|3,6,9,10,11,13,14,15,16,17,18,19,20
p8-14|20|1.12559|1|8|2,3,4,5,6,7,8,9,11,15,18,20
p8-14|20|1.13837|1|9|1,2,4,5,6,7,8,10,20
p8-14|20|1.17128|1|10|2,6,8,9,10,11,13,14,15,16,18,19,20
p8-14|20|1.20029|1|11|1,2,3,4,5,7,11,13,14,15,16,17,19,20
p8-14|20|1.19787|1|12|3,4,5,6,7,8,9,10,11,12,13,14,16,19,20
p8-14|20|1.18796|1|13|1,2,4,5,6,7,8,9,11,12,14,15,16,18,20
p8-14|20|1.20067|1|14|2,4,5,7,9,10,12,13,18
p8-14|20|1.24155|1|15|2,3,6,7,8,10,11,13,16,18,19,20
p8-14|20|1.16594|1|16|1,2,6,9,11,15,16,18,19,20
p8-14|20|1.18870|1|17|1,2,4,6,7,10,11,12,13,15,18,19,20
p8-14|20|1.19308|1|18|1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,19
p8-14|20|1.19308|1|18|1,2,3,4,5,6,7,8,9,10,11,12,13,14,17,18
p8-14|20|1.17715|1|19|1,2,3,4,7,10,11,17,18,19
p8-14|20|1.28269|1|20|2,3,5,7,8,10,11,12,18
p8-14|20|1.22499|1|21|1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p8-14|20|1.30611|1|22|1,2,3,4,5,6,11,13,14,15,16,17,19,20
p8-14|20|1.21043|1|23|3,6,7,8,9,12,13,16,17,19
p8-14|20|1.27698|1|24|2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18
p8-14|20|1.23145|1|25|1,3,5,6,7,8,9,10,11,14,15,16,17,18
p8-14|20|1.23145|1|25|1,2,6,9,10,11,12,13,17,18,19,20
p8-14|20|1.23295|1|26|1,7,8,9,11,12,14,15,16,18
p8-14|20|1.22650|1|27|1,2,3,4,7,10,12,13,14,15,18,19,20
p8-14|20|1.21820|1|28|2,4,6,9,10,11,17,18,19
p8-14|20|1.27569|1|29|1,2,3,4,5,6,7,10,11,12,13,14,15,20
p8-14|20|1.27992|1|30|1,4,7,13,16,19,20
p8-14|20|1.30858|1|31|1,2,6,7,8,9,10,11,12,15,16,17,18,19
p8-14|20|1.26822|1|32|1,2,4,5,7,18
p15-22|20|1.02250|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p15-22|20|1.04473|1|2|1,3,13,14
p15-22|20|1.11516|1|3|3,4,5,6,7,8,11,12,16,17,18
p15-22|20|1.10167|1|4|2,3,4,5,7,8,9,10,11,13,14,15,16,20
p15-22|20|1.24195|1|5|1,2,3,5,7,8,15,17,18,20
p15-22|20|1.11797|1|6|1,2,3,4,6,9,10,11,14,16,17,20
p15-22|20|1.18108|1|7|1,2,3,5,6,7,8,9,10,11,13,14,17,18,20
p15-22|20|1.17510|1|8|2,3,4,5,7,8,10,11,12,13,14,15,17,18
p15-22|20|1.16920|1|9|1,2,3,6,7,8,9,11
p15-22|20|1.26460|1|10|2,3,4,5,6,7,10,12,13,15,16,17,19,20
p15-22|20|1.21728|1|11|2,3,4,6,7,8,12,13,14,15,16,17
p15-22|20|1.28337|1|12|2,4,5,9,11,13,14,15,17,20
p15-22|20|1.33354|1|13|1,2,3,4,5,8,9,11,12,13,14,16,18,20
p15-22|20|1.33205|1|14|1,2,12,13,15,16,17
p15-22|20|1.34391|1|15|1,6,7,10,12,13,15,17,18,19,20
p15-22|20|1.25908|1|16|2,3,5,7,8,9,10,11,12,14,15,17,18,20
p15-22|20|1.33054|1|17|1,6,9,12,15,16,19,20
p15-22|20|1.29935|1|18|4,5,6,7,8,9,11
p15-22|20|1.31299|1|19|2,3,4,5,6,9,12,14,15,16,18,19,20
p15-22|20|1.32530|1|20|2,3,10,11,13,14,15,16,20
p15-22|20|1.24444|1|21|2,3,5,6,7,8,9,10,11,12,14,15,16,17,18
p15-22|20|1.31280|1|22|2,3,5,6,7,8,12,13,14,15,16,17
p15-22|20|1.26767|1|23|2,3,4,5,9,10,12,14,16,17,18,19,20
p15-22|20|1.41116|1|24|1,2,6,7,8,11,12,16,17,18
p15-22|20|1.45234|1|25|1,6,8,9,10,11,12,13,14,15,17,18,20
p15-22|20|1.42835|1|26|1,2,5,6,10,12,13,14,15,16,17,18,19
p15-22|20|1.42835|1|26|1,2,4,6,10,12,13,14,15,16,17,18,19
p15-22|20|1.28456|1|27|1,2,3,5,6,7,8,9,10,14,19,20
p15-22|20|1.28456|1|27|1,2,3,4,6,7,8,9,10,14,19,20
p15-22|20|1.42648|1|28|1,2,4,5,7,12,14,15,16,17
p15-22|20|1.36946|1|29|1,2,3,4,5,6,7,8,9,10,11,12,16,18,19,20
p15-22|20|1.42972|1|30|1,7,8,10,12,13,15,16,17
p15-22|20|1.36725|1|31|8,17,18,20
p15-22|20|1.40331|1|32|2,3,10,11,13,14,16,17,18
p23-26|20|1.00326|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p23-26|20|1.05094|1|2|2,3,5,6,7,8,10,12,14,17,20
p23-26|20|1.07722|1|3|1,2,4,5,6,7,8,10,11,12,13,14,15,16,17,18,19,20
p23-26|20|1.10665|1|4|2,3,7,8,10,12,13,14,15,17,20
p23-26|20|1.14256|1|5|2,8,13,18,19
p23-26|20|1.18571|1|6|1,2,3,5,6,7,11,13,14,15,16,17,18,19,20
p23-26|20|1.18932|1|7|1,2,3,6,7,8,10,12,13,14,18
p23-26|20|1.18932|1|7|1,2,3,6,7,8,9,12,13,14,18
p23-26|20|1.17704|1|8|1,3,7,12,15,17,20
p23-26|20|1.23051|1|9|3,4,7,9,15,16,17,19,20
p23-26|20|1.16078|1|10|2,3,4,5,6,7,8,11,18,19
p23-26|20|1.24131|1|11|3,5,6,7,14,15,17
p23-26|20|1.26649|1|12|1,2,3,5,6,7,12,13,14,15,16,17,18,19,20
p23-26|20|1.29792|1|13|4,5,8,9,11,12,13,14,15,16,17,18
p23-26|20|1.31344|1|14|1,2,4,5,7,10,11,12,13,16
p23-26|20|1.28790|1|15|7,12,13,16,20
p23-26|20|1.32654|1|16|1,7,8,10,13,14,16,17,18,19
p23-26|20|1.31892|1|17|1,3,4,6,7,8,9,10,11,12,13,14,15,19
p23-26|20|1.23922|1|18|2,3,5,6,7,14,15,17,18,19,20
p23-26|20|1.32548|1|19|1,3,6,7,10,11,12,13,14
p23-26|20|1.34276|1|20|2,3,4,5,6,7,8,11,18,20
p23-26|20|1.34276|1|20|2,3,4,5,6,7,8,11,18,19
p23-26|20|1.23428|1|21|3,5,7,10,11,13,17,20
p23-26|20|1.23428|1|21|3,5,7,9,11,13,17,20
p23-26|20|1.34080|1|22|5,6,7,14,15,17
p23-26|20|1.29857|1|23|1,3,6,7,9,10,12,13,14,15,16,17
p23-26|20|1.27307|1|24|2,3,5,8,10,12,13,14,15,16,17,18,19,20
p23-26|20|1.32147|1|25|3,4,5,6,9,10,11,13,16,17,18
p23-26|20|1.32147|1|25|3,4,5,6,9,10,11,12,16,17,18
p23-26|20|1.32147|1|25|3,4,5,6,8,10,11,13,16,17,18
p23-26|20|1.32147|1|25|3,4,5,6,8,10,11,12,16,17,18
p23-26|20|1.32147|1|25|3,4,5,6,8,9,11,13,16,17,18
p23-26|20|1.32147|1|25|3,4,5,6,8,9,11,12,16,17,18
p23-26|20|1.44305|1|26|1,6,11,12,13,17,20
p23-26|20|1.37308|1|27|3,4,7,10,14,16,17,19,20
p23-26|20|1.37308|1|27|3,4,7,9,15,16,17,19,20
p23-26|20|1.37308|1|27|3,4,7,9,14,16,17,19,20
p23-26|20|1.41699|1|28|1,2,3,4,7,8,9,10,11,16
p23-26|20|1.45455|1|29|1,2,3,4,6,9,10,13,18,19,20
p23-26|20|1.44549|1|30|1,2,3,5,6,7,11,13,14,15,18,20
p23-26|20|1.39559|1|31|1,2,4,6,7,8,10,12
p23-26|20|1.50492|1|32|7,11,12,13,15,16,17
p27-32|20|1.03054|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p27-32|20|1.09278|1|2|1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19
p27-32|20|1.08704|1|3|1,2,3,4,5,7,8,9,10,14,15,16,17,18,20
p27-32|20|1.10724|1|4|1,2,3,6,8,9,10,11,12,13,14,15,16,17,18,19
p27-32|20|1.09025|1|5|1,2,3,4,5,6,8,9,10,11,13,14,15,17,20
p27-32|20|1.15113|1|6|1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,19
p27-32|20|1.15091|1|7|2,7,11,15,16,17,18
p27-32|20|1.09320|1|8|4,5,6,7,11,12,13,15,16,19,20
p27-32|20|1.11984|1|9|1,2,3,4,5,6,7,14,15,17,18,19,20
p27-32|20|1.15254|1|10|1,2,3,4,5,7,8,9,10,11,12,13,14,17,18,19
p27-32|20|1.18100|1|11|1,2,3,5,6,7,8,11,12,15,16,17,18,19,20
p27-32|20|1.19107|1|12|1,2,3,7,8,9,10,11,12,13,14,15,16,17,18,20
p27-32|20|1.21747|1|13|3,4,7,8,9,10,12,14,18,19,20
p27-32|20|1.24567|1|14|2,5,6,8,9,10,11,12,13,14,15,16,17,18,20
p27-32|20|1.11538|1|15|1,2,3,4,5,7,8,9,10,11,12,13,14,15,16,17,18,20
p27-32|20|1.14359|1|16|1,2,4,5,11,13,14,15,16,17,18
p27-32|20|1.16115|1|17|1,6,9,10,11,12,13,14,15,16,18
p27-32|20|1.18845|1|18|2,4,5,6,7,9,10,11,12,13,14,15,16,17,18,20
p27-32|20|1.18845|1|18|2,4,5,6,7,9,10,11,12,13,14,15,16,17,18,19
p27-32|20|1.27521|1|19|1,3,6,7,8,9,10,11,12,13,14,15,17,20
p27-32|20|1.27521|1|19|1,3,6,7,8,9,10,11,12,13,14,15,17,19
p27-32|20|1.21024|1|20|1,2,3,8,9,10,11,17,18,19
p27-32|20|1.24263|1|21|1,2,9,10,12,13,19
p27-32|20|1.20659|1|22|4,5,11,12,13,14,17,18,19,20
p27-32|20|1.23921|1|23|1,5,9,10,11,12,14,17,18
p27-32|20|1.24844|1|24|1,2,3,4,5,6,7,10,12,13,14,15,16,20
p27-32|20|1.27997|1|25|2,3,4,6,9,10,11,12,13,16,19
p27-32|20|1.29341|1|26|1,2,3,4,5,7,8,9,10,13,14,19
p27-32|20|1.18162|1|27|4,8,11,13,14,16,17,18,19
p27-32|20|1.28366|1|28|2,3,5,7,8,9,10,12,17
p27-32|20|1.31955|1|29|1,2,5,6,7,8,10,12,13,14,16,17,18,19,20
p27-32|20|1.23462|1|30|2,3,9,10,12,13,17
p27-32|20|1.26810|1|31|1,2,8,9,10,13,14,15,18,20
p27-32|20|1.18152|1|32|1,4,5,11,14,15,16,20
p33-39|20|1.01381|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p33-39|20|1.09557|1|2|1,2,4,5,6,7,9,10,12,15,16,17,18
p33-39|20|1.09275|1|3|1,5,6,8,11,18,19
p33-39|20|1.13624|1|4|1,2,6,7,8,10,12,15,16,17,18,20
p33-39|20|1.08172|1|5|4,6,10,12,14,15,17,18,19
p33-39|20|1.15967|1|6|4,5,6,7,11,14,18,20
p33-39|20|1.16243|1|7|1,3,4,9,11,14,15,16
p33-39|20|1.22648|1|8|1,2,6,7,9,10,12,15,16,17,18,20
p33-39|20|1.18986|1|9|1,2,11,14,15,17,18,19
p33-39|20|1.16943|1|10|1,2,3,11,12,13,15,16,17,18,19
p33-39|20|1.17632|1|11|1,2,3,4,5,7,9,13,15,18,20
p33-39|20|1.18370|1|12|4,5,6,7,11,12,18,20
p33-39|20|1.14712|1|13|2,5,8,10,14,16,17,18
p33-39|20|1.24233|1|14|1,10,11,14,15,16,17,18,20
p33-39|20|1.17429|1|15|1,2,5,6,8,11,14,16,17,18,19
p33-39|20|1.34554|1|16|1,2,3,5,6,8,10,13,14,15,16,18,19,20
p33-39|20|1.28271|1|17|1,3,4,5,6,7,9,10,11,12,13,15,16,17,18,19,20
p33-39|20|1.29844|1|18|1,2,4,5,6,7,9,14,18,20
p33-39|20|1.27584|1|19|1,3,7,12,13,14,19
p33-39|20|1.21043|1|20|3,4,9,10,18,20
p33-39|20|1.25255|1|21|1,3,4,7,12,13,15,16,19
p33-39|20|1.28908|1|22|1,2,4,5,6,10,19
p33-39|20|1.35883|1|23|1,3,7,8,12,14,15,16,17
p33-39|20|1.38822|1|24|4,5,6,8,9,13,18
p33-39|20|1.30788|1|25|1,2,3,7,8,9,11,12,13,20
p33-39|20|1.24277|1|26|1,2,3,4,6,7,9,10,11,12,13,14,16,17,19,20
p33-39|20|1.25221|1|27|2,3,4,5,6,9,12,19,20
p33-39|20|1.32341|1|28|1,3,10,11,12,13,14,15,16,17,19,20
p33-39|20|1.28627|1|29|1,2,5,6,8,13,15
p33-39|20|1.29810|1|30|1,2,3,4,6,9,14,15,16,17,19,20
p33-39|20|1.38318|1|31|4,5,6,7,8,15,16,17,18,20
p33-39|20|1.49183|1|32|1,2,3,7,8,9,10,14,15,16,17,18,19,20
p40-53|20|1.02764|1|1|1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20
p40-53|20|1.08373|1|2|2,3,4,6,7,10,12,14,15,16,20
p40-53|20|1.12215|1|3|1,2,4,6,7,8,9,10,11,12,14,18,19,20
p40-53|20|1.10269|1|4|1,2,3,4,5,6,9,10,11,12,14,15,16,17,18,20
p40-53|20|1.11896|1|5|2,5,6,7,9,10,11,12,14,16,17,18,20
p40-53|20|1.16054|1|6|1,2,3,9,10,11,12,14,15,16,17,18,19
p40-53|20|1.09604|1|7|1,2,3,4,5,6,9,10,13,17,20
p40-53|20|1.17927|1|8|1,2,4,5,6,8,9,10,11,14,15,16,17,18,20
p40-53|20|1.16730|1|9|1,2,3,6,10,11,12,14,18,19,20
p40-53|20|1.18102|1|10|1,2,3,4,5,6,11,12,14,17,18,19,20
p40-53|20|1.16857|1|11|2,5,6,7,8,9,13,14,18
p40-53|20|1.23414|1|12|1,2,5,6,7,8,9,10,11,12,14,15,16,17,18,19,20
p40-53|20|1.22106|1|13|1,2,3,4,5,11,12,15,16,19
p40-53|20|1.15198|1|14|1,3,4,10,12,14,16,17,20
p40-53|20|1.20292|1|15|1,2,3,4,13,14,15,16,17,18,20
p40-53|20|1.26262|1|16|1,2,3,4,5,7,12,14,16,17,18,20
p40-53|20|1.09966|1|17|1,3,4,5,6,7,8,10,11,13,14,16,17,18
p40-53|20|1.25590|1|18|1,3,4,6,9,10,13,14,15,16,17,18,19
p40-53|20|1.21757|1|19|2,3,4,5,6,7,9,11,12,13,15,16,17,18,19,20
p40-53|20|1.22286|1|20|4,6,7,8,9,10,11,12,15,16,17,18,20
p40-53|20|1.19148|1|21|4,12,14,16,18
p40-53|20|1.29431|1|22|2,3,5,6,8,10,13,14,15,16,17,18,19
p40-53|20|1.31605|1|23|2,6,8,13,15,19
p40-53|20|1.40027|1|24|1,3,5,6,7,8,9,10,11,12,14,15,16,17,18,19
p40-53|20|1.26810|1|25|1,2,3,4,11,12,14,16,17,18,20
p40-53|20|1.34059|1|26|1,2,3,4,5,10,12,13,15,16,17,20
p40-53|20|1.29807|1|27|2,3,5,7,8,9,10,11,12,13,14,15,16,17,19
p40-53|20|1.20564|1|28|1,2,3,4,9,12,14,16,17,18
p40-53|20|1.23233|1|29|1,4,6,7,14,15,16,17,18
p40-53|20|1.27193|1|30|1,2,3,9,10,11,12,15,18,19
p40-53|20|1.26810|1|31|1,3,6,7,8,9,10,11,17,18,19
p40-53|20|1.38821|1|32|1,2,3,5,6,7,14,15,16,17,18,20
p54-55|11|1.01866|1|1|1,2,3,4,5,6,7,8,9,10,11
p54-55|11|1.07166|1|2|2,3,5,7,10,11
p54-55|11|1.06110|1|3|1,2,6,8,9,10,11
p54-55|11|1.11820|1|4|2,3,4,5,6,7,9,11
p54-55|11|1.11955|1|5|2,3,6,8
p54-55|11|1.12101|1|6|2,3,5,7,10,11
p54-55|11|1.14227|1|7|1,2,3,4,6,7,8,10,11
p54-55|11|1.28396|1|8|2,3,9,11
p54-55|11|1.18356|1|9|1,2,3,4,5,6,8,9,10,11
p54-55|11|1.11161|1|10|2,3,6,7,10,11
p54-55|11|1.16260|1|11|1,2,5,7,8,9
p54-55|11|1.24985|1|12|2,3,5,6,9,11
p54-55|11|1.34757|1|13|1,2,3,4,8,11
p54-55|11|1.24913|1|14|1,2,4,5,6,7,8,10,11
p54-55|11|1.20700|1|15|2,5,6,7,11
p54-55|11|1.46696|1|16|2,4,9
p54-55|11|1.38533|1|17|1,3,4,6,7,10,11
p54-55|11|1.22729|1|18|2,7,8,9,10,11
p54-55|11|1.34825|1|19|2,5,7,8,9,10
p54-55|11|1.25494|1|20|1,4,5,6,7,8
p54-55|11|1.25494|1|20|1,4,5,6,7,8,11
p54-55|11|1.43053|1|21|5,8,9,10,11
p54-55|11|1.36405|1|22|1,2,5,7,8,9
p54-55|11|1.26318|1|23|2,6,8,11
p54-55|11|1.26318|1|23|2,6,7,11
p54-55|11|1.46042|1|24|6,8,10,11
p54-55|11|1.22895|1|25|1,3,5,6,7,9,10
p54-55|11|1.43648|1|26|1,2,3,4,8,11
p54-55|11|1.25634|1|27|3,8,11
p54-55|11|1.25541|1|28|2,4,5,6,7,8
p54-55|11|1.56364|1|29|1,2,3,5,6,7,8,9,10,11
p54-55|11|1.34943|1|30|1,3,6,7
p54-55|11|1.34943|1|30|1,2,6,7
p54-55|11|1.34606|1|31|1,2,4,5,6,7,10
p54-55|11|1.59601|1|32|1,2,3,10

33
lib.py
View File

@@ -1,6 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import math import math
AFFINE_INV = None
# yes it will report 2,3,5 as non-prime # yes it will report 2,3,5 as non-prime
# though why add a check if it will never be tested anyway # though why add a check if it will never be tested anyway
@@ -70,3 +72,34 @@ def elliptic_curve(x, a, b, r):
if y is None: if y is None:
return None, None return None, None
return y, -y % r return y, -y % r
def affine_inverse(s, n=29):
def fn(s, n):
g = [n, s]
u = [1, 0]
v = [0, 1]
y = [None]
i = 1
while g[i] != 0:
y.append(g[i - 1] // g[i])
g.append(g[i - 1] - y[i] * g[i])
u.append(u[i - 1] - y[i] * u[i])
v.append(v[i - 1] - y[i] * v[i])
i += 1
return v[-2] % n
global AFFINE_INV
if AFFINE_INV is None:
AFFINE_INV = [fn(x, n) for x in range(n)]
return AFFINE_INV[s]
def affine_decrypt(x, key, n=29): # key: (s, t)
return ((x - key[1]) * affine_inverse(key[0], n)) % n
# alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# cipher = 'YDIDWYASDDJVAPJMMBIASDTJVAMD'
# indices = [affine_decrypt(alphabet.index(x), (5, 9), 26) for x in cipher]
# print(''.join(alphabet[x] for x in indices))

View File

@@ -1,117 +1,55 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import re from RuneSolver import VigenereSolver, AffineSolver
from RuneSolver import VigenereSolver from HeuristicSearch import GuessVigenere, GuessAffine, SearchInterrupt
from RuneText import RuneText from HeuristicLib import load_indices, Probability
from NGrams import NGrams from InterruptDB import InterruptDB
from HeuristicSearch import GuessVigenere, SearchInterrupt
# from FailedAttempts import NGramShifter # from FailedAttempts import NGramShifter
RUNES = 'ᚠᚢᚦᚩᚱᚳᚷᚹᚻᚾᛁᛄᛇᛈᛉᛋᛏᛒᛖᛗᛚᛝᛟᛞᚪᚫᚣᛡᛠ' RUNES = 'ᚠᚢᚦᚩᚱᚳᚷᚹᚻᚾᛁᛄᛇᛈᛉᛋᛏᛒᛖᛗᛚᛝᛟᛞᚪᚫᚣᛡᛠ'
RCOUNT = len(RUNES)
ORG_INTERRUPT = ''
INV_INTERRUPT = RUNES.index(ORG_INTERRUPT)
INVERT = False INVERT = False
if INVERT: MIN_SCORE = 1.4
INV_INTERRUPT = 28 - INV_INTERRUPT
re_norune = re.compile('[^' + RUNES + ']')
db = InterruptDB.load()
def load_data(fname): session_files = []
fname = 'pages/{}.txt'.format(fname)
print()
print('loading file:', fname)
with open(fname, 'r') as f:
data = RuneText(re_norune.sub('', f.read()))['index']
if INVERT:
data = [28 - x for x in data]
return data
#########################################
# Probability : Count runes and simple frequency analysis
#########################################
class Probability(object):
def __init__(self, numstream):
self.prob = [0] * RCOUNT
for r in numstream:
self.prob[r] += 1
self.N = len(numstream)
def IC(self):
X = sum(x * (x - 1) for x in self.prob)
return X / ((self.N * (self.N - 1)) / 29)
def friedman(self):
return (K_p - K_r) / (self.IC() - K_r)
def similarity(self):
probs = Probability.normalized(self.prob)
return sum((x - y) ** 2 for x, y in zip(PROB_NORM, probs))
@staticmethod
def normalized(int_prob):
total = sum(int_prob)
return [x / total for x in int_prob] # math.log(x / total, 10)
@staticmethod
def IC_w_keylen(nums, keylen):
val = sum(Probability(nums[x::keylen]).IC() for x in range(keylen))
return val / keylen
######################################### #########################################
# Perform heuristic search on the keylength, interrupts, and key # Perform heuristic search on the keylength, interrupts, and key
######################################### #########################################
def enum_keylengths(nums, fn_interrupt, fn_keyguess, kmin=1, kmax=32): def break_cipher(fname, candidates, solver, key_fn):
best_s = 0
best_kl = 0
iguess = SearchInterrupt(nums, INV_INTERRUPT)
print('interrupt:', ORG_INTERRUPT, 'count:', len(iguess.stops))
for kl in range(kmin, kmax + 1):
score, intrpts = fn_interrupt(kl, iguess)
print('{} {:.4f}'.format(kl, score))
key_guess = []
for i, skips in enumerate(intrpts):
key = fn_keyguess(kl, iguess.join(skips))
yield kl, score, i, skips, key
key_guess.append(key)
intrpts[i] = iguess.to_occurrence_index(skips)
print(' skip:', intrpts)
print(' key:', key_guess)
if score > best_s:
best_s = score
best_kl = kl
print(f'best estimate: keylength: {best_kl}, score: {best_s:.4f}')
def fn_break_vigenere(fname, data):
def fn_similarity(x): def fn_similarity(x):
return Probability(x).similarity() return Probability(x).similarity()
def fn_irp(kl, iguess): filename = f'pages/{fname}.txt'
def fn_IoC(x): slvr = solver()
return Probability.IC_w_keylen(x, kl) slvr.input.load(file=filename)
return iguess.sequential(fn_IoC, startAt=0, maxdepth=9)
# return iguess.genetic(fn_IoC, topDown=False, maxdepth=4)
# return fn_IoC(iguess.join()), [[]] # without interrupts
def fn_key(kl, data):
return GuessVigenere(data).guess(kl, fn_similarity)
slvr = VigenereSolver()
slvr.input.load(file=f'pages/{fname}.txt')
slvr.output.QUIET = True slvr.output.QUIET = True
slvr.output.COLORS = False slvr.output.COLORS = False
slvr.INTERRUPT = ORG_INTERRUPT
slvr.KEY_INVERT = INVERT slvr.KEY_INVERT = INVERT
for kl, score, i, skips, key in enum_keylengths(data, fn_irp, fn_key, for irp_count, score, irp, kl, skips in candidates:
kmin=1, kmax=32): data = load_indices(filename, irp, maxinterrupt=irp_count)
outfile = f'out/{fname}.{score:.3f}.{kl}.{i}.txt' if INVERT:
data = [28 - x for x in data]
iguess = SearchInterrupt(data, (28 - irp) if INVERT else irp)
print('score: {}, interrupt: {}, count: {}, solver: {}'.format(
score, RUNES[irp], len(iguess.stops), key_fn.__name__))
testcase = iguess.join(iguess.from_occurrence_index(skips))
key = key_fn(testcase).guess(kl, fn_similarity)
print(' skip:', skips)
print(' key:', key)
txtname = f'{key_fn.__name__}.{score:.3f}_{fname}_{kl}.{irp}'
if INVERT:
txtname += '.inv'
while txtname in session_files:
txtname += '.'
session_files.append(txtname)
outfile = f'out/{txtname}.txt'
with open(outfile, 'w') as f: with open(outfile, 'w') as f:
f.write(f'{kl}, {score:.4f}, {key}, {skips}\n') f.write(f'{kl}, {score:.4f}, {key}, {skips}\n')
slvr.output.file_output = outfile slvr.output.file_output = outfile
slvr.INTERRUPT = RUNES[irp]
slvr.INTERRUPT_POS = skips slvr.INTERRUPT_POS = skips
slvr.KEY_DATA = key slvr.KEY_DATA = key
slvr.run() slvr.run()
@@ -121,13 +59,6 @@ def fn_break_vigenere(fname, data):
# main # main
######################################### #########################################
PROB_INT = [0] * RCOUNT
for k, v in NGrams.load().items():
PROB_INT[RUNES.index(k)] = v
PROB_NORM = Probability.normalized(PROB_INT)
K_r = 1 / 29 # 0.034482758620689655
K_p = sum(x ** 2 for x in PROB_INT) # 0.06116195419412538
for fname in [ for fname in [
# '0_welcome', # V8 # '0_welcome', # V8
# 'jpg107-167', # V13 # 'jpg107-167', # V13
@@ -143,6 +74,13 @@ for fname in [
# 'p40-53', # ??? # 'p40-53', # ???
'p54-55', # ??? 'p54-55', # ???
]: ]:
data = load_data(fname) # NGramShifter().guess(data, 'ᚠ')
# NGramShifter().guess(data, RUNES[INV_INTERRUPT]) print()
fn_break_vigenere(fname, data) print(f'loading file: pages/{fname}.txt')
candidates = [x for x in db[fname] if x[1] >= MIN_SCORE]
if not candidates:
maxscore = max(x[1] for x in db[fname])
print('No candidates. Highest score is only', maxscore)
continue
break_cipher(fname, candidates, AffineSolver, GuessAffine)
break_cipher(fname, candidates, VigenereSolver, GuessVigenere)