from ngram_score import ngram_score
from pycipher import Autokey
import re
from itertools import permutations

qgram = ngram_score('english_quadgrams.txt')
trigram = ngram_score('english_trigrams.txt')
ctext = """FRRUU OIIYE AMIRN QLQVR BOKGK NSNQQ IUTTY
IIYEA WIJTG LVILA ZWZKT ZCJQH IFNYI WQZXH
RWZQW OHUTI KWNNQ YDLKA EOTUV XELMT SOSIX
JSKPR BUXTI TBUXV BLNSX FJKNC HBLUK PDGUI
IYEAM OJCXW FMJVM MAXYT XFLOL RRLAA JZAXT
YYWFY NBIVH VYQIO SLPXH ZGYLH WGFSX LPSND
UKVTR XPKSS VKOWM QKVCR TUUPR WQMWY XTYLQ
XYYTR TJJGO OLMXV CPPSL KBSEI PMEGC RWZRI
YDBGE BTMFP ZXVMF MGPVO OKZXX IGGFE SIBRX
SEWTY OOOKS PKYFC ZIEYF DAXKG ARBIW KFWUA
SLGLF NMIVH VVPTY IJNSX FJKNC HBLUK PDGUI
IYEAM HVFDY CULJS EHHMX LRXBN OLVMR"""
ctext = re.sub(r'[^A-Z]','',ctext.upper())

# keep a list of the N best things we have seen, discard anything else
class nbest(object):
    def __init__(self,N=1000):
        self.store = []
        self.N = N
        
    def add(self,item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]
    
    def __getitem__(self,k):
        return self.store[k]

    def __len__(self):
        return len(self.store)

#init
N=100
for KLEN in range(3,10):
    rec = nbest(N)

    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3):
        key = ''.join(i) + 'A'*(KLEN-len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0,len(ctext),KLEN):
            score += trigram.score(pt[j:j+3])
        rec.add((score,''.join(i),pt[:10]))

    next_rec = nbest(N)
    for i in range(0,KLEN-3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A'*(KLEN-len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0,len(ctext),KLEN):
                    score += qgram.score(pt[j:j+len(key)])
                next_rec.add((score,key,pt[:10]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score       
    print (bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext))
    

6f901b62e352ea8e4fb5a5128aeafe0e188e575c
<mask token>


class nbest(object):

    def __init__(self, N=1000):
        self.store = []
        self.N = N

    def add(self, item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]

    def __getitem__(self, k):
        return self.store[k]
    <mask token>


<mask token>

<mask token>


class nbest(object):

    def __init__(self, N=1000):
        self.store = []
        self.N = N

    def add(self, item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]

    def __getitem__(self, k):
        return self.store[k]

    def __len__(self):
        return len(self.store)


<mask token>
for KLEN in range(3, 10):
    rec = nbest(N)
    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 3):
        key = ''.join(i) + 'A' * (KLEN - len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0, len(ctext), KLEN):
            score += trigram.score(pt[j:j + 3])
        rec.add((score, ''.join(i), pt[:10]))
    next_rec = nbest(N)
    for i in range(0, KLEN - 3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A' * (KLEN - len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0, len(ctext), KLEN):
                    score += qgram.score(pt[j:j + len(key)])
                next_rec.add((score, key, pt[:10]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score
    print(bestscore, 'autokey, klen', KLEN, ':"' + bestkey + '",', Autokey(
        bestkey).decipher(ctext))

<mask token>
qgram = ngram_score('english_quadgrams.txt')
trigram = ngram_score('english_trigrams.txt')
ctext = """FRRUU OIIYE AMIRN QLQVR BOKGK NSNQQ IUTTY
IIYEA WIJTG LVILA ZWZKT ZCJQH IFNYI WQZXH
RWZQW OHUTI KWNNQ YDLKA EOTUV XELMT SOSIX
JSKPR BUXTI TBUXV BLNSX FJKNC HBLUK PDGUI
IYEAM OJCXW FMJVM MAXYT XFLOL RRLAA JZAXT
YYWFY NBIVH VYQIO SLPXH ZGYLH WGFSX LPSND
UKVTR XPKSS VKOWM QKVCR TUUPR WQMWY XTYLQ
XYYTR TJJGO OLMXV CPPSL KBSEI PMEGC RWZRI
YDBGE BTMFP ZXVMF MGPVO OKZXX IGGFE SIBRX
SEWTY OOOKS PKYFC ZIEYF DAXKG ARBIW KFWUA
SLGLF NMIVH VVPTY IJNSX FJKNC HBLUK PDGUI
IYEAM HVFDY CULJS EHHMX LRXBN OLVMR"""
ctext = re.sub('[^A-Z]', '', ctext.upper())


class nbest(object):

    def __init__(self, N=1000):
        self.store = []
        self.N = N

    def add(self, item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]

    def __getitem__(self, k):
        return self.store[k]

    def __len__(self):
        return len(self.store)


N = 100
for KLEN in range(3, 10):
    rec = nbest(N)
    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 3):
        key = ''.join(i) + 'A' * (KLEN - len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0, len(ctext), KLEN):
            score += trigram.score(pt[j:j + 3])
        rec.add((score, ''.join(i), pt[:10]))
    next_rec = nbest(N)
    for i in range(0, KLEN - 3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A' * (KLEN - len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0, len(ctext), KLEN):
                    score += qgram.score(pt[j:j + len(key)])
                next_rec.add((score, key, pt[:10]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score
    print(bestscore, 'autokey, klen', KLEN, ':"' + bestkey + '",', Autokey(
        bestkey).decipher(ctext))

from ngram_score import ngram_score
from pycipher import Autokey
import re
from itertools import permutations
qgram = ngram_score('english_quadgrams.txt')
trigram = ngram_score('english_trigrams.txt')
ctext = """FRRUU OIIYE AMIRN QLQVR BOKGK NSNQQ IUTTY
IIYEA WIJTG LVILA ZWZKT ZCJQH IFNYI WQZXH
RWZQW OHUTI KWNNQ YDLKA EOTUV XELMT SOSIX
JSKPR BUXTI TBUXV BLNSX FJKNC HBLUK PDGUI
IYEAM OJCXW FMJVM MAXYT XFLOL RRLAA JZAXT
YYWFY NBIVH VYQIO SLPXH ZGYLH WGFSX LPSND
UKVTR XPKSS VKOWM QKVCR TUUPR WQMWY XTYLQ
XYYTR TJJGO OLMXV CPPSL KBSEI PMEGC RWZRI
YDBGE BTMFP ZXVMF MGPVO OKZXX IGGFE SIBRX
SEWTY OOOKS PKYFC ZIEYF DAXKG ARBIW KFWUA
SLGLF NMIVH VVPTY IJNSX FJKNC HBLUK PDGUI
IYEAM HVFDY CULJS EHHMX LRXBN OLVMR"""
ctext = re.sub('[^A-Z]', '', ctext.upper())


class nbest(object):

    def __init__(self, N=1000):
        self.store = []
        self.N = N

    def add(self, item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]

    def __getitem__(self, k):
        return self.store[k]

    def __len__(self):
        return len(self.store)


N = 100
for KLEN in range(3, 10):
    rec = nbest(N)
    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 3):
        key = ''.join(i) + 'A' * (KLEN - len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0, len(ctext), KLEN):
            score += trigram.score(pt[j:j + 3])
        rec.add((score, ''.join(i), pt[:10]))
    next_rec = nbest(N)
    for i in range(0, KLEN - 3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A' * (KLEN - len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0, len(ctext), KLEN):
                    score += qgram.score(pt[j:j + len(key)])
                next_rec.add((score, key, pt[:10]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score
    print(bestscore, 'autokey, klen', KLEN, ':"' + bestkey + '",', Autokey(
        bestkey).decipher(ctext))

from ngram_score import ngram_score
from pycipher import Autokey
import re
from itertools import permutations

qgram = ngram_score('english_quadgrams.txt')
trigram = ngram_score('english_trigrams.txt')
ctext = """FRRUU OIIYE AMIRN QLQVR BOKGK NSNQQ IUTTY
IIYEA WIJTG LVILA ZWZKT ZCJQH IFNYI WQZXH
RWZQW OHUTI KWNNQ YDLKA EOTUV XELMT SOSIX
JSKPR BUXTI TBUXV BLNSX FJKNC HBLUK PDGUI
IYEAM OJCXW FMJVM MAXYT XFLOL RRLAA JZAXT
YYWFY NBIVH VYQIO SLPXH ZGYLH WGFSX LPSND
UKVTR XPKSS VKOWM QKVCR TUUPR WQMWY XTYLQ
XYYTR TJJGO OLMXV CPPSL KBSEI PMEGC RWZRI
YDBGE BTMFP ZXVMF MGPVO OKZXX IGGFE SIBRX
SEWTY OOOKS PKYFC ZIEYF DAXKG ARBIW KFWUA
SLGLF NMIVH VVPTY IJNSX FJKNC HBLUK PDGUI
IYEAM HVFDY CULJS EHHMX LRXBN OLVMR"""
ctext = re.sub(r'[^A-Z]','',ctext.upper())

# keep a list of the N best things we have seen, discard anything else
class nbest(object):
    def __init__(self,N=1000):
        self.store = []
        self.N = N
        
    def add(self,item):
        self.store.append(item)
        self.store.sort(reverse=True)
        self.store = self.store[:self.N]
    
    def __getitem__(self,k):
        return self.store[k]

    def __len__(self):
        return len(self.store)

#init
N=100
for KLEN in range(3,10):
    rec = nbest(N)

    for i in permutations('ABCDEFGHIJKLMNOPQRSTUVWXYZ',3):
        key = ''.join(i) + 'A'*(KLEN-len(i))
        pt = Autokey(key).decipher(ctext)
        score = 0
        for j in range(0,len(ctext),KLEN):
            score += trigram.score(pt[j:j+3])
        rec.add((score,''.join(i),pt[:10]))

    next_rec = nbest(N)
    for i in range(0,KLEN-3):
        for k in range(N):
            for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                key = rec[k][1] + c
                fullkey = key + 'A'*(KLEN-len(key))
                pt = Autokey(fullkey).decipher(ctext)
                score = 0
                for j in range(0,len(ctext),KLEN):
                    score += qgram.score(pt[j:j+len(key)])
                next_rec.add((score,key,pt[:10]))
        rec = next_rec
        next_rec = nbest(N)
    bestkey = rec[0][1]
    pt = Autokey(bestkey).decipher(ctext)
    bestscore = qgram.score(pt)
    for i in range(N):
        pt = Autokey(rec[i][1]).decipher(ctext)
        score = qgram.score(pt)
        if score > bestscore:
            bestkey = rec[i][1]
            bestscore = score       
    print (bestscore,'autokey, klen',KLEN,':"'+bestkey+'",',Autokey(bestkey).decipher(ctext))
    
