Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class VigenereSolver:
- def __init__(self, text, key="a"):
- self._sourcekey = "abcdefghijklmnopqrstuvwxyz"
- self._ctext = text
- self.setKey(key)
- def setKey(self, key):
- if len(key) < 1: key = "a"
- self._key = self._stripKey(key)
- def _stripKey(self, key):
- return key and "".join(c for c in key.lower() if c in self._sourcekey) or None
- def _reverseKey(self, key):
- return "".join([self._sourcekey[-self._sourcekey.find(c) % len(self._sourcekey)] for c in key])
- def _matchKey(self, key=None, exact=False):
- key = key or self._key
- kbit = 0
- o = []
- for c in self._ctext:
- if c.lower() in self._sourcekey:
- if exact: o.append(key[kbit])
- elif kbit == 0: o.append(key[kbit].upper())
- else: o.append(key[kbit].lower())
- kbit = (kbit + 1) % len(key)
- else: o.append(exact and c or " ")
- return "".join(o)
- def setText(self, text):
- self._ctext = text
- def getText(self):
- return self._ptext
- def updateSolution(self):
- self._ptext = self.decrypt()
- def output(self):
- self.updateSolution()
- print self._ptext
- def encrypt(self, ptext=None, key=None):
- o = []
- ptext = ptext or self._ptext
- key = self._stripKey(key) or self._key
- kbit = 0
- l = len(self._sourcekey)
- for c in ptext:
- k_i = self._sourcekey.find(key[kbit])
- c_i = self._sourcekey.find(c)
- if c_i < 0:
- c_i = self._sourcekey.upper().find(c)
- if c_i < 0: o.append(c)
- else:
- o.append(self._sourcekey[(c_i+k_i)%l].upper())
- kbit = (kbit + 1) % len(key)
- else:
- o.append(self._sourcekey[(c_i+k_i)%l])
- kbit = (kbit + 1) % len(key)
- return "".join(o)
- def decrypt(self, ctext=None, key=None):
- ctext = ctext or self._ctext
- key = self._stripKey(key) or self._key
- return self.encrypt(ctext, self._reverseKey(key))
- def frequency(self, text=None):
- text = text or self._ctext
- d = {c:0 for c in self._sourcekey}
- for c in self._stripKey(text):
- if c in d: d[c] += 1
- l = d.items()
- l.sort(key=lambda t:t[1], reverse=True)
- return l
- def freqTable(self, text=None):
- l = self.frequency(text)
- i = 0
- for t in l:
- print "%s: %d\t" % t,
- i = (i+1)%9
- if i == 0: print
- print
- def _ioc(self, text=None):
- #Note: Standard english ~= 0.067
- l = self.frequency(text)
- n = sum([t[1]*(t[1]-1) for t in l])
- d = sum([t[1] for t in l])
- if d <= 1: return 0
- return float(n)/(d*(d-1))
- def _avg(self, seq):
- return sum(seq)/len(seq)
- def indexOfCoincidence(self, low=1, hi=12, all=False):
- t = self._stripKey(self._ctext)
- r = []
- for i in range(low, hi+1):
- if i > len(t): break
- r.append((i, self._avg([self._ioc(t[j::i]) for j in range(i)])))
- c = lambda t: t[1]
- return all and sorted(r, key=c, reverse=True) or max(r, key=c)
- def countRepetition(self, low=2, hi=8, thorough=True):
- d = {}
- for i in range(hi,low-1,-1):
- d = self._mergeCount(d, self._countRepetition(i))
- if d and not thorough: break
- if not d: return "No Results"
- r = []
- for k in d:
- t = self._stripKey(self._ctext)
- t = t.replace(k, k.upper())
- l = [a-b for a, b in zip(d[k][1:], d[k][:-1])]
- r.append("%s (Occurrance: %s, min distance %d)" % (self._matchKey(t, True), k, min(l)))
- return "\n".join(r)
- def _countRepetition(self, size):
- t = self._stripKey(self._ctext)
- l = [(t[i:i+size], i) for i in range(len(t)+1-size)]
- d = {}
- for k, i in l:
- d.setdefault(k,[]).append(i)
- return {k:v for k,v in d.items() if len(v) > 1}
- def _mergeCount(self, dold, dnew):
- dret = {}
- for k, v in dold.items():
- dret[k] = v
- dnew = {k2:v2 for k2, v2 in dnew.items() if k2 not in k}
- for k, v in dnew.items():
- dret[k] = v
- return dret
- def __repr__(self):
- self.updateSolution()
- return "\n".join(["ctext: %s", "key: %s", "ptext: %s"]) % (self._ctext, self._matchKey(), self._ptext)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement