Done challenge 6b, added some text formatting tools
authorNeil Smith <neil.git@njae.me.uk>
Fri, 17 Nov 2017 11:20:40 +0000 (11:20 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Fri, 17 Nov 2017 11:20:40 +0000 (11:20 +0000)
2017/2017-challenge6.ipynb
2017/6a.plaintext [new file with mode: 0644]
cipher.py
cipherbreak.py
text_prettify.py [new file with mode: 0644]

index 1d353f119eaac861171a031715b6888c42883515..bc0b90dd6d729c522eb1e2d7c53ad48f16a97550 100644 (file)
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": null,
+   "execution_count": 1,
    "metadata": {},
    "outputs": [],
    "source": [
@@ -15,6 +15,7 @@
     "%matplotlib inline\n",
     "\n",
     "from cipherbreak import *\n",
+    "from text_prettify import *\n",
     "\n",
     "ca = open('6a.ciphertext').read()\n",
     "cb = open('6b.ciphertext').read()"
   {
    "cell_type": "code",
    "execution_count": 2,
-   "metadata": {
-    "collapsed": true
-   },
+   "metadata": {},
    "outputs": [],
    "source": [
-    "def tpack(text, width=100):\n",
-    "    lines = [text[0]]\n",
-    "    for word in text[1:]:\n",
-    "        if len(lines[-1]) + 1 + len(word) <= width:\n",
-    "            lines[-1] += (' ' + word)\n",
-    "        else:\n",
-    "            lines += [word]\n",
-    "    return lines"
+    "def tpack(text, width=100):\n",
+    "    lines = [text[0]]\n",
+    "    for word in text[1:]:\n",
+    "        if len(lines[-1]) + 1 + len(word) <= width:\n",
+    "            lines[-1] += (' ' + word)\n",
+    "        else:\n",
+    "            lines += [word]\n",
+    "    return lines"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 4,
+   "execution_count": 3,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "JDPWD JGLOF YBDQA LKYFD PPFTY OFKQY ICSHD QMIDK KYOES RQBYO FOKRJ DHYRB YPYKO YXTLS QRBYI LCDIQ RDRFL KRBFK HQBYJ DWBDT YEYYK HFOKD MMYOE SRRBY PYBDQ EYYKK LPDKQ LJOYJ DKODK ORBYP YFQKL RBFKA JSCBR LALLK BYPPL LJBDO EYYKP DKQDC HYODK OQBYI YZRKL JYQQD AYESR QLJYR BFKAR YIIQJ YQBYF QLHDK OUYQB LSIOJ LTYLK FRBFK HQBYJ DWBDT YMIDK KYORB FQJYD KUBFI YFBDT YRBYO LCSJY KRGLO FYUDK RYOZP LJILK OLKFO LKRHK LUBLU QBYHK YUESR RBYZF ZRBCB DMRYP UDQBF OOYKF KDCDT FRWFK DQRLK YIFKR YIFKQ LJYPY JDFKQ FKRBY YMBYQ SQPLL JDRRB YEPFR FQBJS QYSJF RUDQY KCPWM RYOSQ FKADK LRBYP MLIWD IMBDE YRFCC FMBYP FKTYK RYOFK RBYKF KYRYY KRBCY KRSPW FDQHY ORBYJ SQYSJ RLRYQ RFRDK ORBYO LCSJY KRFQD SRBYK RFCQL FASYQ QRBYF JMYPF DICFM BYPQC BLLIP YDIIW BDOJL TYOLK MYPBD MQFQB LSIOK RBDTY EYYKQ SPMPF QYODZ RYPRB YOFQC LTYPW DRELO PSJES RFRIY DTYQJ YULKO YPFKA UBDRY IQYRB YWOYT YILMY OLKYL OOZYD RSPYU DQDZP FYXYP SKKFK APLSK ORBPY YQFOY QLZRB YIFKR YICLK QFQRF KALZD QFKAI YPLUL ZEIDC HDKOU BFRYR FIYQR BDRRB YJSQY SJRBF KHUYP YDOOY OFKRB YPLJD KMYPF LORBY WPYDO FKQYN SYKCY UUEEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE EUUUE UUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUUE UUUEU EEEUE EEUEE EUEEE UEEEU EEEUE EEUEE EUEEE UEEEU EEEUE EEUEE EUEEE UEEEU EEEUE EEUEE EUEEE UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUEUU UEUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UEUUU EUUUU EUUUE EEUUU UUEEE UUUEU UUEUU UEUUU EUUUU EEEUU EUUUE UEEEU UUEEE EUUEE EUUUE EEUUE EEUEU UUEUU UUEUE UUEUU EUUUE UUUUU EUEUU EEUUE UUEUE UUUUE UUUEE UEEUE UUEUU EUUUU UEUUE UUUEU UUUEU UUEUU UEUUE UUUEU EUUUE UEUUU UUEUU UEUEU EUEUE UUUEU UUEUU UEUEU EUEUU EUUEU UUUUE UUUEU UEUUU UEUUE UUUEU UUEEE EEUEE EEUUE UUUUU EEEEE UEUEU EUEEE EEUUU EUUUE UUUEU EEEEU UEEEU UUEEE EUUUE UUUUE UUUEU UUEUU EUUUE UEUEU UUEUU UUUEU UUEUE UEUEU EUUUE UUUEU UUEUU UEUEU UUUUE UUUUU EUEUU UUEUU UUEUU EUUUE UUUEU UUEUE UUEUU UEUUU UEUUU EUEUU EEUEU UUEUU UEUUU EUUUE UEUUU UUEUU UUUEU UEUUU EUUUU EUUUE UUUEU UEUUU EUEUU UEUUU EEEUE UUUEU EUUUE UEUUU EUUEE EUUEU UUEUE UUUUU EEEEU UEUUU EUEEE UUEEE UEUUU EUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU EUUUE UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUUUU UUEUU UEUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UEUUU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU EUEUE UEUEU UUEUU EEEUE EEUEE EUEEE UEEEU EEEUE EEUEE EUEEE UEEEU EEEUE EEUEE EUEEE UEEEU EEEUE EEUEE EUEEE UUEUU UEUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUU EUUUE UUUEU UUEUU UEUUE UUFBD TYSQY OEZLP RBYEI DCHRF IYQDK OUZLP RBYUB FRYLK YQFRR LLHJY DUBFI YRLZF ASPYL SRRBD RRBYZ PFYXY FQQRY ADKLA PDMBW CLKCY DIFKA RBYHY WULPO ZLPRB YCFMB YPFKC BDMRY PZFTY UFRBL SRGLO FYFDJ KLRQS PYUBY PYRLA LKYVR RBYPY DPYLK IWRUL MLQQF EFIFR FYQDQ ZDPDQ FCDKQ YYESR FBDTY KLFOY DUBYP YLKYL ZRBYJ FQDKO DQZDP DQFCD KRYII KLLKY YIQYH KLUQY FRBYP QLFAS YQQFU FIIBY DOZLP LIWJM FDQYY WLSRB YPY\n"
+      "Lelqzq, C xnyhv Isxad en Gkcghhe ufc wbw gem ugejldv maw efjdexq. Rly zzh vwdr fwzhcff xbw LMXSR sjwqenauim gm e qakh agnwy ugemw zvimmh Mwkgoc leeamk u dnx ix msckd evgtx fgnocff jij sly ehwmamk wzztnwq en lgi Nwltfw nj Ujsigar. Xbss kund qy lhqy ln vylqmynd mn xqsg Bnhcw'r jladrx ss xbw Avclhwb Etwyml, ababl bsr e wgkpyusmif nj ujsizsbxm xqsg lgi Nwltfw. Isxad wuqr wbw jryo vi qgtpx xhkojd sol vlyjd xi yn ryps. Xbw bpow vem am xbw kswssmifr. Xbw emlks shw vem ss xbw Fvyss Tsjzqcv, sly kdgifc en lgi zgqx ix Peclaes ogmwz vem ttmfl evie sly jtmhk nj nzd Pcygxbgtwy ss Efwwehvqmu smh nzd xbaqh if Qlivdw, uenra lgi lmhrm ge xbw Bsfgrwok. Sly Cmmazs'w wsrxfw zx Vgcvoe vem ttmfl evie sly jdquamw ix sly Ezymgkioe zx Bskmwsqrukrym, zdrww sly “yqepw” semc nj amzvxamk nzd figj. Wi skp zaui wzztnwqw qwqi zgtrx ss xbw rmnw nj ifd sz lgi Mwuih Onrxwqw ix sly smgcwmx qgqpx. Lgi ifkc lwlecfhra dngulhshk zvy lgi Mlzxow nj Twtw ul Npseomu smh nzd Luffmhy Felvdrm ge Futxpif, zrx fn-shw gem smc cvde qzdvy lgi asqhyfr qcygx bsui vwdr, mg sly gmps hkeww vi wgtpx yn ryps mm Gkcghhe. Nzd gfmd en lgi yfc sz ugejldv zaui jghrnk rxlshkbl slyjd, wcfbi faflnamk, vmkp ufc suc zvy skp mqlfidr sz Rdym. Od wbgtpx td wuxd lyjd fyuzymw Isxad'w hwsaijj luk rihl gil ssxuujilk nr ng Kshvnr vq kesamk u dnra lqecd nj zgqkyv cswmlihlr vyndefamk nzd piuzxcgm sz ugejldv zaui. Nzzx vgtkbl tw yfnyaz smgw ss fgbenw zrx vdgchgil ugejldv maw. Ay zzh vwdr nzhreamk utnyn lgi ynnpolhsh ge xbw Hqjwqmud Bmjzdvm. Lzgcltw okdh vgsl nzd Zcydryjd ehv Aiumesll bmjzdvm ogmwz zvy hnpssktbsainab zyjrmifr sz lgi Wsdwuj rlcxs, ehv zx zaqwn od emktqyv slul bluhsil khb qgtpx td ihuqcjldh nzd wued auq. Vi qwqi udlsml qmazs. Qysmabaki Dgcmy'k trypoiwldh nskihl esl xnvawqc bsr kcndr gw zr cvde. C lgmhc vi gafln td evdd xi ltvh gtv yfdqcwr sh gmi ufnxbwq fs wwtfghxcff lyj fmzl, ayn A jrio gil utvlwmx zgbym ar jcytvcff sol vlyjd sh wzvnz sly kdzyfsl qgmhyj lmazs fy.\n"
      ]
     }
    ],
     "print(ca)"
    ]
   },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# def depunctuate_character(c):\n",
+    "#     if c in string.ascii_uppercase:\n",
+    "#         return 'UPPER'\n",
+    "#     elif c in string.ascii_lowercase:\n",
+    "#         return 'LOWER'\n",
+    "#     else:\n",
+    "#         return c\n",
+    "\n",
+    "# def depunctuate(text):\n",
+    "#     return [depunctuate_character(c) for c in text]"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": 5,
-   "metadata": {
-    "collapsed": true
-   },
+   "metadata": {},
    "outputs": [],
    "source": [
-    "ca_text = '''\n",
-    "JDPWD JGLOF YBDQA LKYFD PPFTY OFKQY ICSHD QMIDK KYOES RQBYO FOKRJ DHYRB YPYKO YXTLS QRBYI \n",
-    "LCDIQ RDRFL KRBFK HQBYJ DWBDT YEYYK HFOKD MMYOE SRRBY PYBDQ EYYKK LPDKQ LJOYJ DKODK ORBYP \n",
-    "YFQKL RBFKA JSCBR LALLK BYPPL LJBDO EYYKP DKQDC HYODK OQBYI YZRKL JYQQD AYESR QLJYR BFKAR \n",
-    "YIIQJ YQBYF QLHDK OUYQB LSIOJ LTYLK FRBFK HQBYJ DWBDT YMIDK KYORB FQJYD KUBFI YFBDT YRBYO \n",
-    "LCSJY KRGLO FYUDK RYOZP LJILK OLKFO LKRHK LUBLU QBYHK YUESR RBYZF ZRBCB DMRYP UDQBF OOYKF \n",
-    "KDCDT FRWFK DQRLK YIFKR YIFKQ LJYPY JDFKQ FKRBY YMBYQ SQPLL JDRRB YEPFR FQBJS QYSJF RUDQY\n",
-    "KCPWM RYOSQ FKADK LRBYP MLIWD IMBDE YRFCC FMBYP FKTYK RYOFK RBYKF KYRYY KRBCY KRSPW FDQHY \n",
-    "ORBYJ SQYSJ RLRYQ RFRDK ORBYO LCSJY KRFQD SRBYK RFCQL FASYQ QRBYF JMYPF DICFM BYPQC BLLIP \n",
-    "YDIIW BDOJL TYOLK MYPBD MQFQB LSIOK RBDTY EYYKQ SPMPF QYODZ RYPRB YOFQC LTYPW DRELO PSJES \n",
-    "RFRIY DTYQJ YULKO YPFKA UBDRY IQYRB YWOYT YILMY OLKYL OOZYD RSPYU DQDZP FYXYP SKKFK APLSK \n",
-    "ORBPY YQFOY QLZRB YIFKR YICLK QFQRF KALZD QFKAI YPLUL ZEIDC HDKOU BFRYR FIYQR BDRRB YJSQY \n",
-    "SJRBF KHUYP YDOOY OFKRB YPLJD KMYPF LORBY WPYDO FKQYN SYKCY\n",
-    "  FBD TYSQY OEZLP RBYEI DCHRF IYQDK OUZLP RBYUB FRYLK YQFRR LLHJY DUBFI YRLZF ASPYL SRRBD \n",
-    "RRBYZ PFYXY FQQRY ADKLA PDMBW CLKCY DIFKA RBYHY WULPO ZLPRB YCFMB YPFKC BDMRY PZFTY UFRBL \n",
-    "SRGLO FYFDJ KLRQS PYUBY PYRLA LKYVR RBYPY DPYLK IWRUL MLQQF EFIFR FYQDQ ZDPDQ FCDKQ YYESR \n",
-    "FBDTY KLFOY DUBYP YLKYL ZRBYJ FQDKO DQZDP DQFCD KRYII KLLKY YIQYH KLUQY FRBYP QLFAS YQQFU \n",
-    "FIIBY DOZLP LIWJM FDQYY WLSRB YPY\n",
-    "'''\n",
-    "sca_text = sanitise(ca_text)"
+    "# def repunctuate_character(letters, punctuation):\n",
+    "#     if punctuation == 'UPPER':\n",
+    "#         return next(letters).upper()\n",
+    "#     elif punctuation == 'LOWER':\n",
+    "#         return next(letters).lower()\n",
+    "#     else:\n",
+    "#         return punctuation\n",
+    "\n",
+    "# def repunctuate(text, punctuation):\n",
+    "#     letters = iter(text)\n",
+    "#     return cat(repunctuate_character(letters, p) for p in punctuation)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "(24, -1733.3180566179738)"
+       "('zeus', -1960.8847716972107)"
       ]
      },
-     "execution_count": 6,
+     "execution_count": 7,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "key_a, score = caesar_break(sca_text)\n",
-    "key_a, score"
+    "ka, score = vigenere_frequency_break(ca)\n",
+    "ka, score"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 7,
+   "execution_count": 8,
    "metadata": {},
    "outputs": [
     {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "lfryflinqhadfscnmahfrrhvaqhmsakeujfsokfmmaqgutsdaqhqmtlfjatdaramqazvnustdaknefkstfthnmtdhmjsdalfydfvagaamjhqmfooaqguttdaradfsgaammnrfmsnlqalfmqfmqtdarahsmntdhmcluedtncnnmdarrnnldfqgaamrfmsfejaqfmqsdakabtmnlassfcagutsnlatdhmctakkslasdahsnjfmqwasdnukqlnvanmhtdhmjsdalfydfvaokfmmaqtdhslafmwdhkahdfvatdaqneulamtinqhawfmtaqbrnlknmqnmhqnmtjmnwdnwsdajmawguttdabhbtdedfotarwfsdhqqamhmfefvhtyhmfstnmakhmtakhmsnlaralfhmshmtdaaodasusrnnlfttdagrhthsdlusaulhtwfsameryotaqushmcfmntdaronkyfkodfgatheehodarhmvamtaqhmtdamhmataamtdeamturyhfsjaqtdalusaultntasthtfmqtdaqneulamthsfutdamthesnhcuasstdahloarhfkehodarsednnkrafkkydfqlnvaqnmoardfoshsdnukqmtdfvagaamsurorhsaqfbtartdaqhsenvaryftgnqrulguthtkafvaslawnmqarhmcwdftaksatdayqavaknoaqnmanqqbafturawfsfbrhazarummhmcrnumqtdraashqasnbtdakhmtakenmshsthmcnbfshmckarnwnbgkfejfmqwdhtathkastdfttdalusaultdhmjwarafqqaqhmtdarnlfmoarhnqtdayrafqhmsapuameahdfvausaqgbnrtdagkfejthkasfmqwbnrtdawdhtanmashttnnjlafwdhkatnbhcuranuttdfttdabrhazahsstacfmncrfodyenmeafkhmctdajaywnrqbnrtdaehodarhmedfotarbhvawhtdnutinqhahflmntsurawdaratncnmaxttdarafranmkytwnonsshghkhthasfsbfrfshefmsaaguthdfvamnhqafwdaranmanbtdalhsfmqfsbfrfshefmtakkmnnmaaksajmnwsahtdarsnhcuasshwhkkdafqbnrnkylohfsaaynutdara\n"
-     ]
+     "data": {
+      "text/plain": [
+       "\"Maryam, I found Jodie at Olympia and she has chapter six already. She had been leading the MIDAS operatives on a wild goose chase around Selcuk making a lot of noise about looking for the missing chapter at the Temple of Artemis. That gave me time to retrieve it from Jodie's friend at the British Museum, which has a collection of artefacts from the Temple. Jodie says she knew we would figure out where to go next. The clue was in the locations. The first one was at the Great Pyramid, the second at the fort of Qaitbay which was built from the ruins of the Lighthouse at Alexandria and the third on Rhodes, among the ruins of the Colossus. The Knight's castle at Bodrum was built from the remains of the Mausoleum at Halicarnassus, hence the “grave” task of guarding the book. So all five chapters were found at the site of one of the Seven Wonders of the ancient world. The only remaining locations are the Statue of Zeus at Olympia and the Hanging Gardens of Babylon, and no-one has any idea where the gardens might have been, so the only place we could go next is Olympia. The clue at the end of chapter five points straight there, since lighting, bull and oak are all symbols of Zeus. We should be safe here because Jodie's network has sent her attackers on to London by laying a long trail of forged documents revealing the location of chapter five. That bought us enough time to locate and decipher chapter six. We had been thinking about the evolution of the Imperial Ciphers. Tacitus used both the Vigenere and Beaufort ciphers which are polyalphabetic versions of the Caesar shift, and at first we assumed that chapter six would be encrypted the same way. We were almost right. Meanwhile Jodie's unexpected talent for forgery has given me an idea. I think we might be able to turn our enemies on one another by exploiting her gift, but I know her current focus is figuring out where on earth the seventh wonder might be.\""
+      ]
+     },
+     "execution_count": 8,
+     "metadata": {},
+     "output_type": "execute_result"
     }
    ],
    "source": [
-    "print(caesar_decipher(sca_text, key_a))"
+    "pa = vigenere_decipher(sanitise(ca), ka)\n",
+    "repunctuate(pa, pua)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 9,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "((17, 21, True), -1723.2877779777489)"
+       "['Maryam, I found Jodie at Olympia and she has chapter six already. She had been leading the MIDAS',\n",
+       " 'operatives on a wild goose chase around Selcuk making a lot of noise about looking for the missing',\n",
+       " \"chapter at the Temple of Artemis. That gave me time to retrieve it from Jodie's friend at the\",\n",
+       " 'British Museum, which has a collection of artefacts from the Temple. Jodie says she knew we would',\n",
+       " 'figure out where to go next. The clue was in the locations. The first one was at the Great Pyramid,',\n",
+       " 'the second at the fort of Qaitbay which was built from the ruins of the Lighthouse at Alexandria and',\n",
+       " \"the third on Rhodes, among the ruins of the Colossus. The Knight's castle at Bodrum was built from\",\n",
+       " 'the remains of the Mausoleum at Halicarnassus, hence the “grave” task of guarding the book. So all',\n",
+       " 'five chapters were found at the site of one of the Seven Wonders of the ancient world. The only',\n",
+       " 'remaining locations are the Statue of Zeus at Olympia and the Hanging Gardens of Babylon, and no-one',\n",
+       " 'has any idea where the gardens might have been, so the only place we could go next is Olympia. The',\n",
+       " 'clue at the end of chapter five points straight there, since lighting, bull and oak are all symbols',\n",
+       " \"of Zeus. We should be safe here because Jodie's network has sent her attackers on to London by\",\n",
+       " 'laying a long trail of forged documents revealing the location of chapter five. That bought us',\n",
+       " 'enough time to locate and decipher chapter six. We had been thinking about the evolution of the',\n",
+       " 'Imperial Ciphers. Tacitus used both the Vigenere and Beaufort ciphers which are polyalphabetic',\n",
+       " 'versions of the Caesar shift, and at first we assumed that chapter six would be encrypted the same',\n",
+       " \"way. We were almost right. Meanwhile Jodie's unexpected talent for forgery has given me an idea. I\",\n",
+       " 'think we might be able to turn our enemies on one another by exploiting her gift, but I know her',\n",
+       " 'current focus is figuring out where on earth the seventh wonder might be.']"
       ]
      },
-     "execution_count": 8,
+     "execution_count": 9,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "(m_a, a_a, o_a), score = affine_break(sca_text)\n",
-    "(m_a, a_a, o_a), score"
+    "tpack(repunctuate(pa, pua).split())"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 9,
+   "execution_count": 10,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "gyotygparsneylhadnsyooscnrsdlnjbfmylxjyddnrvfilenrsrdigymnienondrnqcaflienjabyjliyisadiesdmlengyteycnvnndmsrdyxxnrvfiienoneylvnnddaoydlagrngydrydrienonsldaiesdhgfbeiahaadenooaageyrvnndoydlybmnrydrlenjnkidagnllyhnvfilagniesdhinjjlgnlenslamydrznleafjrgacnadsiesdmlengyteycnxjyddnrieslgnydzesjnseycnienrabfgndiparsnzydinrkoagjadradsradimdazeazlenmdnzvfiienkskiebeyxinozylesrrndsdybycsitsdyliadnjsdinjsdlagnongysdlsdiennxenlfloaagyiienvosislegflnfgsizylndbotxinrflsdhydaienoxajtyjxeyvnisbbsxenosdcndinrsdiendsdninndiebndifotsylmnriengflnfgiainlisiydrienrabfgndislyfiendisblashfnlliensgxnosyjbsxenolbeaajonyjjteyrgacnradxnoeyxlsleafjrdieycnvnndlfoxoslnrykinoienrslbacnotyivarofgvfisijnycnlgnzadrnosdhzeyinjlnientrncnjaxnradnarrknyifonzylykosnqnofddsdhoafdrieonnlsrnlakienjsdinjbadlslisdhakylsdhjnoazakvjybmydrzesinisjnlieyiiengflnfgiesdmznonyrrnrsdienoagydxnosarientonyrsdlnufndbnseycnflnrvkaoienvjybmisjnlydrzkaoienzesinadnlsiiaamgnyzesjniakshfonafiieyiienkosnqnsllinhydahoyxetbadbnyjsdhienmntzaorkaoienbsxenosdbeyxinokscnzsieafiparsnsygdailfonzenoniahadnwiienonyonadjtizaxallsvsjsisnlylkyoylsbydlnnvfiseycndasrnyzenonadnakiengslydrylkyoylsbydinjjdaadnnjlnmdazlnsienolashfnllszsjjenyrkaoajtgxsylnntafienon\n"
+      "Maryam, I found Jodie at Olympia and she has chapter six already. She had been leading the MIDAS\n",
+      "operatives on a wild goose chase around Selcuk making a lot of noise about looking for the missing\n",
+      "chapter at the Temple of Artemis. That gave me time to retrieve it from Jodie's friend at the\n",
+      "British Museum, which has a collection of artefacts from the Temple. Jodie says she knew we would\n",
+      "figure out where to go next. The clue was in the locations. The first one was at the Great Pyramid,\n",
+      "the second at the fort of Qaitbay which was built from the ruins of the Lighthouse at Alexandria and\n",
+      "the third on Rhodes, among the ruins of the Colossus. The Knight's castle at Bodrum was built from\n",
+      "the remains of the Mausoleum at Halicarnassus, hence the “grave” task of guarding the book. So all\n",
+      "five chapters were found at the site of one of the Seven Wonders of the ancient world. The only\n",
+      "remaining locations are the Statue of Zeus at Olympia and the Hanging Gardens of Babylon, and no-one\n",
+      "has any idea where the gardens might have been, so the only place we could go next is Olympia. The\n",
+      "clue at the end of chapter five points straight there, since lighting, bull and oak are all symbols\n",
+      "of Zeus. We should be safe here because Jodie's network has sent her attackers on to London by\n",
+      "laying a long trail of forged documents revealing the location of chapter five. That bought us\n",
+      "enough time to locate and decipher chapter six. We had been thinking about the evolution of the\n",
+      "Imperial Ciphers. Tacitus used both the Vigenere and Beaufort ciphers which are polyalphabetic\n",
+      "versions of the Caesar shift, and at first we assumed that chapter six would be encrypted the same\n",
+      "way. We were almost right. Meanwhile Jodie's unexpected talent for forgery has given me an idea. I\n",
+      "think we might be able to turn our enemies on one another by exploiting her gift, but I know her\n",
+      "current focus is figuring out where on earth the seventh wonder might be.\n"
      ]
     }
    ],
    "source": [
-    "print(affine_decipher(sca_text, m_a, a_a, o_a))"
+    "lcat = '\\n'.join\n",
+    "print(lcat(tpack(repunctuate(pa, pua).split())))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 12,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'etoainhsrdlumwycfgpbvkxjqz'"
+       "1932"
       ]
      },
-     "execution_count": 10,
+     "execution_count": 12,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "ltrs = [p[0] for p in english_counts.most_common()]\n",
-    "cat(ltrs)"
+    "open('6a.plaintext', 'w').write(lcat(tpack(repunctuate(pa, pua).split())))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "pub = depunctuate(cb)\n",
+    "scb = sanitise(cb)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 46,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'yrkfdlbqpoisjcumzaetwhxgvn'"
+       "('jcarykujniqadmv', -3289.3609056830232)"
       ]
      },
-     "execution_count": 11,
+     "execution_count": 46,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "ctls =  [p[0] for p in collections.Counter(sanitise(ca_text)).most_common()]\n",
-    "cat(ctls)"
+    "kbv, score = vigenere_frequency_break(scb)\n",
+    "kbv, score"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 47,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "{'A': 'g',\n",
-       " 'B': 'h',\n",
-       " 'C': 'w',\n",
-       " 'D': 'i',\n",
-       " 'E': 'p',\n",
-       " 'F': 'a',\n",
-       " 'G': 'j',\n",
-       " 'H': 'k',\n",
-       " 'I': 'l',\n",
-       " 'J': 'm',\n",
-       " 'K': 'o',\n",
-       " 'L': 'n',\n",
-       " 'M': 'c',\n",
-       " 'N': 'z',\n",
-       " 'O': 'd',\n",
-       " 'P': 'r',\n",
-       " 'Q': 's',\n",
-       " 'R': 't',\n",
-       " 'S': 'u',\n",
-       " 'T': 'b',\n",
-       " 'U': 'y',\n",
-       " 'V': 'q',\n",
-       " 'W': 'v',\n",
-       " 'X': 'x',\n",
-       " 'Y': 'e',\n",
-       " 'Z': 'f'}"
+       "'Piuo tgnlqva rdn uggsvzeuvlr ed lurg nrubgg ve dyp kztmitehdd flrmqantm bvn enarvtu vd Zgvhrerir rez nttcgegm uy Tlxt lk unu tez la hbt dten, rm mgmggtz ld uog Axruglt. Ot ngrgtz bos orxg utttvyqg ael sn xgutz ybu yq Tlwwuvee uy lluo Enbpueba Gbaiufba yel Ptgrevoa Ntegmvk, zbu hot Uymn pgnt guettlba eem, ggerfkrydd ubg qlna sa tpt Fymtj ttxriltl s ntsgth, welpr sepe ul e atc dldrd mlwhrmgn atyx uog Lvdvo. Soyqisqd fbslmweh hl ggurgm bcn lmhhgm sotnbvh sa tpt Rmbvde rn r kygi ma fybgeut, uog Axruglt nsettm oie unu arht ln yuott tvmigrstm ugetgexn qfm, uy uog abgstcns ma nyxt, bg prn ewrfntm hgvoksord ttemgrhvlra. R nuebbs qrn ggtshtm yq bos Oteeut yr uot ynmsh la hot Gkstgyn, yav, urwte idq, Rhtcfkrr pen ngru ul dcis abvguqq ye ova hrwwqd gnueht pognt nu pra utrztm yq bos Uxsgglt’a lpe fvdmwfveen. Bin mtebo osn r ugvgvlbn avlek ul kt, rrz r srilaar tigeu hy rqq bcn zhvtrmn. Ih prn naqt sn r ttrd dlnn gptd zd ublng hl poye os qrn rlu fggnlryqpe jeype. Roxyttu, xkhtlvtg, yn uot fssarrfg rez hot youd wsnngn fekt ul bcn nmbng; rez ie sblxve tqrstn, erm pognthug jrlua ya urdqtfo pttt raatxydam, nwn eext cen le exq pwsn; rlg zim r nilhpu nloq lr btrgilh kb ova mteho gtpsveu ru hot rgpn lt hlfitu iu zoifjqq. Bouo ndksrhbd pra ceehtratm lq uot ccms-osggrm toxlbt boqv ot brm lgte ggelhum yq sliale lr bos Uxsgglt’a flxkyel. Nlxiuver qlnh ll twxt ie rfflvehceg vot exyihvlba Urpcnuibn Dofbqdin qo uog etc ulittllf ma ubt styivesa. Os qrn sortutm pibo mufbtveu hot atyhurt sgrfg cvuo Syqsnleir rrz otrzam tptgg ul syeagylu Esqhefba. Iu pra sepe uoge ubeu uog xlmo la hot Symtw cyn fuiteqtz. Arqbabvao pgyut yn ovn avlek ru hot rgpn vr y qsvutt ul Seul mebtl vot nvahb mrd laakht ubt jedtema sa Wsd vr uog qtrg yh unu flrnbdaovsa sa Wsgfon Rtttfvrin Ertxgen II rem Difucn Yetyion Olrsgqvbn. “Ct rtg twstanmrd fbrgugm yd yig wmnu kbeinvftrb rdn hggru Gkstgyn Mkyvuire hy ntfont Rsw Gyxrre ve uba Ekhuogge Wiehmyen qfm dgu dyo pgvha uk yt ln uog dlnn yh unu Flztw Ysfbqhsgay. Dlog qgemtg Eoguglqe ora eqgtetd rsvm hot ftvft yh nago r dlna, lbu vn kla nl eyu ggslitt bos Glmgw ygnlgt hvt rsnnieh yn uot qarf votr dlo krd yg ubfu uoeu dyo pvqd jluf ovk. Dlo htqq ka unsu vrutddvhtrmt zhlx e frfhbgtz usc obhutnha uorh bos vgriult Srqhembm prn hot Symtw elm uo xranvru ovn aisrmguggn ir uot Rsgtp. Poiqt hbt Yrtfrfwrea uogkntqvan qht brqvwgqd uy eriu xbso ln hot Fyttv, Grqurfoa vn rr amagrugm Gykre rrt os ybnh yt ahlssgt ysblgg ot see mtabgke uog ntsogvuq sa tpt Vksttirq fizoshn. Ubt Fyztw pixq xu gtsligttm, lt kla, elbt arkiqd rrt thugdyet qyb jeyw purq sed ubg sgvsa. Rdn nl hl ubg ntiglun trgh la hbt ugoa ntmgd ya Rutvfldy vd qovso ubg arug sa tpt eieub dthvyl rdn la hot Symtw ibnsra piqq ir uvxg ft fuiteqtz. Oeuvd bosf vu cvqd lt hbenmsn yd hot erfvtrb Yqzdqyever Hlmzanm ma Peg.'"
       ]
      },
-     "execution_count": 12,
+     "execution_count": 47,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "trans = {pr[1].upper(): pr[0] for pr in zip(ltrs, ctls)}\n",
-    "trans"
+    "repunctuate(vigenere_decipher(sanitise(cb), kbv), pub)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 48,
    "metadata": {},
    "outputs": [
     {
-     "name": "stdout",
+     "data": {
+      "text/plain": [
+       "('hnypjvriltvyzlt', -3351.460892110415)"
+      ]
+     },
+     "execution_count": 48,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "kbb, score = beaufort_frequency_break(cb)\n",
+    "kbb, score"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 49,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'jdeksfkoiqfhtmesfgdmhdenubvlfhsyhekfreuihjmafmdfueiuunutiwmfmkdlhyxidsldtasdehuudgiumsfdxsufmensmcfavejffumnyekewfhshknsmfsfmaufkffbffsnskfyfgtfmekelhbfefsscbiffulhlbfefmnwfavmnadedhuenamfkhsxhfuxlsxldduxlhulkfsuudxlkguftdmaxeekfrnlmjfsfqfufsnxlhtnsfbhrphaivekfhollnydkftnmfcsechduflhlftsfeptojunuhvenhyfjimwhitnashmflysnafkfudtekgxaidthwtknnkdurensfrgtmkdllnrrfmgxskydenydkfhzxdihgmhbhsonytnxshrefkffbffsnslghsenkdbejfyhefnyndlfsmdkrshtfmrftgshilgumenekflwtgsdlenylnbfkfiilhjhrmfmesdxbflhimfsnshednulgmehexejhlfsfteenavekelfuhefnudlfnsmesnyekffbfgsnsaweehpfudihirsdtmihjhllfudfnidqezxdfeivntldlyhadivfleheekkfsfjfjhlefumenavekefbgfsnslmkugkvkdtdhulkdknfhekihlhrsdfqmyllknspenbfhumghhduywifqfueengjikdlxsdfumldeiilyfidhlhsfhiimmlfqftaveknlfemkknbkejhlunegfrmnuhihvpunjuuxabfslbmsfnqfsnydlfgngwihtfhumejgaxlvahllflthbefnkdljnxlfhumdthxaidsgihtflhulkkfsfpfspunelnxfhipfrljfsfhllecaifmjdluhbfjhkouhiihdglunsmdlildurhflnxinukeisdurmykdlmfhejtfwndsfheekfufimnsynrrfedezxdsqivekcllvbghekukhldussfhlfmavdlfjdmelgsfhmsxaoxsekgekfkhmafevsfbnpfmavgndlmvnuekefbgfsnslsobbhulmnbdedhuholeunddbfduhggmeueduqekfhbadecoxllhhxledxlixsyiixlglekfufjrmrfsunrnyekfgsnpeutfkejhltkhsrenjdekkftxsdurejgyshrcifgfhtfjcfkthiemnudhhumjghmfmdkfsfentntzsnueshirhtxlddkhlnuhvekfuekhdfkfinklnyekftnlgcjhlrfqfhifmlgjxledwljsnefnyjellknspheekfufimduhieeefsenthdomheflekfydyeklivafymsfekfphievmlnyahvduekfveisnyejftnulxiljeglnyahstxlhsseuduxlsifbfulddgvmixtcxlahfadxklnunsgexljfhsfedgsflkivtkhsrflbvnxsanlebxudycufuehtmrsfhefbfgsnsmmbdedhuenkgtxsffhcsnbhuhcvekfumsekfsupdtsmnblgumvfevnxitdefembfnyekfimmlnyejftnmfcntsyienswbvnxsifhlgshrsctnihkhlhhtfhmvfhdmekfgscufnylwtkhinllawfdyvnwmnunesftmrfseketnmfcafymtfekffhlldurnydlfvfhrekfuvnxbgwaflxrfekhevnxieiiwncukdbvnxeejibfejheduefiicsfutfxsnbhthgewtfmlgulxrrfleldlheekeeshdenstgjrhtxkkhlekftnlgchumclbhlldurjellxgfnsefsldudlfunsdkjkdifekebhsahrdhulekfbkgiqflgsfxuidpfhwenbhofbxtknyejgtnmfbthirhtxlcmhufmwthefmsnbgvhumkebxleaflemhgfmaeynsfkfthtnflesmvekflftxreevnydkfdbgfsdgjtdgkeslekftnmedjdiizfsftnqfsennsvnwvnxsyhbdhwhumfpfsvnufvnwqunjjciighvekfftdtfhtmlnenekfkgqfuejghsenyekefsxfldnsvnyhrscunihdtjkdtkekfxiefnydkfuduekiesdnuhtmnyekftnlgcdeleiyjdiidudebfafrfqfhifmxtfdiekeudejdiiaesxhsmemavekfhusefueagavinudhuqommflknyjhs'"
+      ]
+     },
+     "execution_count": 49,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "beaufort_decipher(sanitise(cb), kbb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 50,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "('ryajcqgrnskaxof', -3289.3609056830232)"
+      ]
+     },
+     "execution_count": 50,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "kbbv, score = beaufort_variant_frequency_break(cb)\n",
+    "kbbv, score"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'piuotgnlqvardnuggsvzeuvlredlurgnrubggvedypkztmitehddflrmqantmbvnenarvtuvdzgvhrerirreznttcgegmuytlxtlkunutezlahbtdtenrmmgmggtzlduogaxrugltotngrgtzbosorxgutttvyqgaelsnxgutzybuyqtlwwuveeuylluoenbpuebagbaiufbayelptgrevoantegmvkzbuhotuymnpgntguettlbaeemggerfkryddubgqlnasatptfymtjttxriltlsntsgthwelprsepeuleatcdldrdmlwhrmgnatyxuoglvdvosoyqisqdfbslmwehhlggurgmbcnlmhhgmsotnbvhsatptrmbvdernrkygimafybgeutuogaxrugltnsettmoieunuarhtlnyuotttvmigrstmugetgexnqfmuyuogabgstcnsmanyxtbgprnewrfntmhgvoksordttemgrhvlrarnuebbsqrnggtshtmyqbosoteeutyruotynmshlahotgkstgynyavurwteidqrhtcfkrrpenngruuldcisabvguqqyeovahrwwqdgnuehtpogntnuprautrztmyqbosuxsggltalpefvdmwfveenbinmteboosnrugvgvlbnavlekulktrrzrsrilaartigeuhyrqqbcnzhvtrmnihprnnaqtsnrttrddlnngptdzdublnghlpoyeosqrnrlufggnlryqpejeyperoxyttuxkhtlvtgynuotfssarrfgrezhotyoudwsnngnfektulbcnnmbngreziesblxvetqrstnermpognthugjrluayaurdqtfoptttraatxydamnwneextcenleexqpwsnrlgzimrnilhpunloqlrbtrgilhkbovamtehogtpsveuruhotrgpnlthlfituiuzoifjqqbouondksrhbdpraceehtratmlquotccmsosggrmtoxlbtboqvotbrmlgteggelhumyqslialelrbosuxsggltaflxkyelnlxiuverqlnhlltwxtierfflvehcegvotexyihvlbaurpcnuibndofbqdinqouogetculittllfmaubtstyivesaosqrnsortutmpibomufbtveuhotatyhurtsgrfgcvuosyqsnleirrrzotrzamtptggulsyeagyluesqhefbaiuprasepeuogeubeuuogxlmolahotsymtwcynfuiteqtzarqbabvaopgyutynovnavlekruhotrgpnvryqsvuttulseulmebtlvotnvahbmrdlaakhtubtjedtemasawsdvruogqtrgyhunuflrnbdaovsasawsgfonrtttfvrinertxgeniiremdifucnyetyionolrsgqvbnctrtgtwstanmrdfbrgugmydyigwmnukbeinvftrbrdnhggrugkstgynmkyvuirehyntfontrswgyxrreveubaekhuoggewiehmyenqfmdgudyopgvhaukytlnuogdlnnyhunuflztwysfbqhsgaydlogqgemtgeoguglqeoraeqgtetdrsvmhotftvftyhnagordlnalbuvnklanleyuggslittbosglmgwygnlgthvtrsnniehynuotqarfvotrdlokrdygubfuuoeudyopvqdjlufovkdlohtqqkaunsuvrutddvhtrmtzhlxefrfhbgtzuscobhutnhauorhbosvgriultsrqhembmprnhotsymtwelmuoxranvruovnaisrmguggniruotrsgtppoiqthbtyrtfrfwreauogkntqvanqhtbrqvwgqduyeriuxbsolnhotfyttvgrqurfoavnrramagrugmgykrerrtosybnhytahlssgtysblggotseemtabgkeuogntsogvuqsatptvksttirqfizoshnubtfyztwpixqxugtsligttmltklaelbtarkiqdrrtthugdyetqybjeywpurqsedubgsgvsardnnlhlubgntigluntrghlahbtugoantmgdyarutvfldyvdqovsoubgarugsatpteieubdthvylrdnlahotsymtwibnsrapiqqiruvxgftfuiteqtzoeuvdbosfvucvqdlthbenmsnydhoterfvtrbyqzdqyeverhlmzanmmapeg'"
+      ]
+     },
+     "execution_count": 51,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "beaufort_variant_decipher(sanitise(cb), kbbv)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 52,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'ytsfeqziozzjyzynifmpczahrmdxemcpjzkmjwjlxnnyonyerofpohxcddrcgzewuxdyioknuwxnbjvyqlnrzresxtfivjwqfyuewdiyowzlefdbxcvvjphzvvgclgtmtgqgsgouncvhzdhgqpoiaeutqtjvpqbodegstcrmcxrtdyybzkeywyeuuvsdtaoxbyrkleslsgczexwgbxntrmeysyaguvwjwqjgydepouomrjtzujwohgqvcmueioasbmdrqtsaviskmkxsekqbnteipeknauupiftymqkenkipdeaxaftxauudzckvvnjftnmtgbeehwbimsclcessglcireuhgwwlyxjfngmnmrebmmfkvpaohxxsgbvzoywwgzcuqnojzxpefrmkzpmgksvajuryrkimuzevnjlqwexpybstphbsiezbiqccknatjvowdxwkenfosfjjrfspkiojnaeaceignjpkmhmpswfczqbjhvppczhdvjtvlkwvgcecjedqrxtabnyivskgpgpbmityxuktwmmlrgqyvvawhlngwiahbktyzvqynncbbdqzdeeeoershbiqltegjriukialufyukgvtzekncmyafwndyamvtstwryacxyallqpaopcnwrsqtgzrgfpejoymndfxaazwdfhmmcgpwltsbxjvvoageyfazkzskfccocgmwucfjsnqzuevanhtxwxoaxdttlqrohnwjfhzghonqxscdddzywlzgedmnfspenyehypvtwlgugrxjxglrjrkvdvmievpftyuocdicijifknqwvqjblqlwowcrgkqbxrnihxzlqcwubpwbbdlyrxbldlhguqedueejcuvcgyxnyzwmviaiwexxagvfnvfisrlwglpldcjsibqqgvuienlufstzzhanbsnitujiyexvvzuxzsgcpzhwlbpztqxvcuzksmsvmckgsamvqislpmpebwztxycgdboztpckmeyncijrcuamgbamtujurczsifncmuykyvsobuykolymrgjrokaycaizhkkcpkiyykdkcokmoaxuoaslievdhtpnykwjqhctxhucldgakaqovdcppxhrcduwngahltatswfaebolamgzmlbrraeeaicgyvomorpeavueckyysketvfraqyxxzpdxziewwaazksgqexgakjwafruwhzkwoohwfyzaqjcebhhwzbcokqsxweviwgblgawlimoqbgbwljybjxiqvguxvkwaydleqxxczkkrjndjipnuckiensalufwzdbcvlzboiimqihhqgqligodxmetgvuyynjfueadtioypxvvtjananrwtwiwqecsfrafoecgmigjstastytaoaaaicbbqfwczwgazhlhqoywpapkdnijysxgwscchyyqvymiyhssfwliaonsfteylmqgdavsdgzeruprqimkbigpdzcijjgiapvrdsfillydvlkddcfgbrzusfbthejdltrhgpwfjdefhatrynubwqmgmbenqeauduywpadbqwcguysfrnxklcgmigjsbgnoqkgmhagmiyhqyvpkpulmnexfgruzehgcppkjquwegfxcvdymgtxfrdfjxdehtvqinowziyfadvepfjumnxnkgegwceptacydlungwxeqkikgyqqaghwclrniddelxibvghlrqdoqjnblmlpfuavvumalzqsiibaywlutzncqynnpllygpdiqrndrdtkxafowgexyztnhjoefbnkmqcyurmmlzpomoxzgzaycskbzxsglywehercavykijxmayepzokgrwrskcpkzifynzsmraaamwausemvnzmiftcmkgqeibgvzyuajgfkmcnhaausphtlsenhnfecpfczdmvgxzrepwdjnrzbcggfobytwrsbxcuuefyprmkdoqjreayfqyviakimlaqqaafzormkycourkqymvgivresfbfflondaypnqurwdwtyoadrbctnsirqkzerxegpteaniovvkfriypvlkedyziaaejijgiguwldnbdlngbdofzpbzcbufvtfonjytalwrkvpxwlbvyquadgdzzsauoaohxxfceuxnaqaumnpryjsmkdiyqumafndewkdhypzatgntredpgiyiuhvalamveqvsgdknfqxkdzvrhxfxcubicgmrqhwuiswmlzbhzzeylhnqgp'"
+      ]
+     },
+     "execution_count": 52,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "vbai = vigenere_decipher(sanitise(cb), 'arcanaimperii')\n",
+    "vbai"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 53,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'ybwfeqpgshhzozgrifmfadiphcdfimcpzxourmzlfrnyodwizwvfopbcddhakhmmkxlciokdsafvrzvgulnrppiafjvidnwqfosielyooedleftzbkdlzppdvvgsjkbujwqowgoudazphtxgytoiausxybzlpyfodewqxkzcsxzxdyyrxomgmoecyvsdjysfjohktislswadmfmwbfrtrmuwwgiwkvenwqjwwhmxekouvjtzkhawpwgvkqueieywjuthqbwaviiiqsfiukyfnteynisvqkuxmftycoomvaypliaxavrbicktzkovvnzdxvujwbmihwbykwktsusaklcihcypommlgbjfnwkruzurmujkvpqmlffiwbddoywmedkcgdordxpevpqshfcgswvajkpczsycuhivnjboamffobaxphbigihjygckonatztselnmkmrfosvhnznifkqsjnauygmqwdjxomhmfqankpgbrlvppsxlldzjvtowvgscgrmtgrfxabnogzaswfgxfmitovysbmcmtvgqylteepbdgemahbarchdgonvgbbdgxhmmueezwhbigjxmozhicoialkdccswlthiknccwenedtyiqvtsjuvgisnyiplqpqmtkvmhsyxgzrwdtmreomvhfxaqxalnxcmkkpwljqffrlloikeyfqxohaavckscgmmsgnridqhyevadfxfeneafhttlgpspvmzfpdghodobakttdhcwlzwchuvvipmryehonzbebwuovxjxwjvrzalddqievfdxgcesdqgijiviryelgjjpqlweugzoagbfvnihnxpykmkbxabbdbwvfjbtlpkuqetsimrskvkkyxnoxaudyqieixxawtjvdvyszpwglfjhkriybyugvuycrtcvithdhanrqrqbkzigixvvpsbhawsphlwlbfxxyflsuhosmslkgsoiqmduislfktmjmptfccgdrmdbxsammcncizpgcicwbiqtujkpghayvnkquykotwwjkokwpymrwhvwsqocimzhkaatsqooklocokcmefceqstmevdxrtvgamjylctxxsgtlwqkiuovdsntfphsdcangaxjxibimfiibolqkkhubrrzeeeayakgdecozteavkcgsgoikmxvfrqocffpfdfdiewmyehsiwqmbgakzuenzkmhhowooxujghqgjkibhhmxfkwagsfaevimeftoqmlqqoqbwzatrorjfmqvgkvzseqodtiqxxsxoszzddrmpnusimmviqlcjwzdrazthreiqqqihxokytywolbmetwtyggdzfciadtymcxflltrenanhuxeqmgekwfravmikocygrwtasjwxiwqqaqgbbqvughewqzpphqooutixatnqnysxwuwkkxoyyzymiofwanmbiisnsfjcctugwdizsdgpcvcxhgiuobigfbdkqzzgqepvrtqjqtboddpkddsdkjzpksnfthezbpbzxwpejjdevfebzodujaqmgczivyuqulyywpqbfyeswugwfrnnipkocygrwbgneooouxqgumyhqottsxkbmvixfghsdmpwspxojqumcknfsldgqgtxvphnrntepxvqidmahqovalzepfzsqvfdagmkwcefrekgtbuvkwxegimsoogqikhwcbprqltulfmbvgxjvylegjvflmlfdyidlkmipzqsygfigmbubdncqolrxtbogxhiqrdbvlbananswgenwdbvxzomjbnkcoggchcmtdpomevdohqocaobzxiepgeuxezgavyagnfuqoexdokghuvassfkhmfynpqqziqqmeeusectrhuyvtkqkgqugfodpouingfkcarpiqksxltlsullvnuspngzdmlebhzufwlnnrzrakonerybarsbnaycmvopzqkdoghvmiovqgziakykpiygqandormawgwchaqgqvgilpianrvftsndaonrychmdexyoatpfkbdiizukzehvioxjuavmovvadvqgfllsidyzyyemryzgqkuwltlfltdwblsfzprxgjcvltnsnjyjypezalpfalbvooyilwtzhwauoqmlffvsecbnaqqsqvxhojaqkdiooyuivddmakdhondibwdtzidpgywmcplqliqveqlqklsdvqfodzvhfbnfskbqggmrgfacqimmtdbhzpcctpdggx'"
+      ]
+     },
+     "execution_count": 53,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "vbai = beaufort_variant_decipher(sanitise(cb), 'arcanaimperii')\n",
+    "vbai"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 54,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
      "output_type": "stream",
      "text": [
-      "mirvi mjnda ehisg noeai rrabe daose lwuki sclio oedpu tshed adotm iketh ereod exbnu sthel nwils titan othao kshem ivhib epeeo kadoi ccedp utthe rehis peeoo nrios nmdem iodio dther eason thaog muwht ngnno herrn nmhid peeor iosiw kedio dshel efton messi geput snmet haogt ellsm eshea snkio dyesh nuldm nbeno athao kshem ivhib eclio oedth asmei oyhal eahib ethed nwume otjnd aeyio tedfr nmlno dnoad notko nyhny sheko eyput thefa fthwh icter yisha ddeoa oiwib atvao istno elaot elaos nmere miaos aothe eches usrnn mitth eprat ashmu seuma tyise owrvc tedus aogio nther cnlvi lchip etaww acher aobeo tedao theoa oetee othwe oturv aiske dthem useum tntes tatio dthed nwume otasi utheo tawsn agues sthea mcera ilwac hersw hnnlr eillv hidmn bedno cerhi csash nuldo thibe peeos urcra sedif terth edasw nberv itpnd rumpu tatle ibesm eynod eraog yhite lseth evdeb elnce dnoen ddfei turey isifr aexer uooao grnuo dthre esade snfth elaot elwno sasta ognfi saogl ernyn fpliw kiody hatet alest hitth emuse umtha okyer eidde daoth ernmi ocera ndthe vreid aosez ueowe yyppy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp pyyyp yypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypyyp yyypy pppyp ppypp pyppp ypppy pppyp ppypp pyppp ypppy pppyp ppypp pyppp ypppy pppyp ppypp pyppp ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yypyy ypyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy ypyyy pyyyy pyyyp ppyyy yyppp yyypy yypyy ypyyy pyyyy pppyy pyyyp ypppy yyppp pyypp pyyyp ppyyp ppypy yypyy yypyp yypyy pyyyp yyyyy pypyy ppyyp yypyp yyyyp yyypp yppyp yypyy pyyyy ypyyp yyypy yyypy yypyy ypyyp yyypy pyyyp ypyyy yypyy ypypy pypyp yyypy yypyy ypypy pypyy pyypy yyyyp yyypy ypyyy ypyyp yyypy yyppp ppypp ppyyp yyyyy ppppp ypypy pyppp ppyyy pyyyp yyypy ppppy ypppy yyppp pyyyp yyyyp yyypy yypyy pyyyp ypypy yypyy yyypy yypyp ypypy pyyyp yyypy yypyy ypypy yyyyp yyyyy pypyy yypyy yypyy pyyyp yyypy yypyp yypyy ypyyy ypyyy pypyy ppypy yypyy ypyyy pyyyp ypyyy yypyy yyypy ypyyy pyyyy pyyyp yyypy ypyyy pypyy ypyyy pppyp yyypy pyyyp ypyyy pyypp pyypy yypyp yyyyy ppppy ypyyy pyppp yyppp ypyyy pyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy pyyyp yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yyyyy yypyy ypypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp ypyyy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy pypyp ypypy yypyy pppyp ppypp pyppp ypppy pppyp ppypp pyppp ypppy pppyp ppypp pyppp ypppy pppyp ppypp pyppp yypyy ypyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyy pyyyp yyypy yypyy ypyyp yyahi beuse dpfnr thepl iwkta lesio dyfnr theyh ateno esatt nnkme iyhal etnfa guren utthi tthef raexe asste giong richv wnowe ilaog theke vynrd fnrth ewach eraow hicte rfabe yathn utjnd aeaim ontsu reyhe retng noeqt there ireno lvtyn cnssa palat aesis firis awios eeput ahibe onade iyher enoen fthem asiod isfir isawi otell onnoe elsek onyse ather snagu essay allhe idfnr nlvmc aisee vnuth ere\n"
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
      ]
+    },
+    {
+     "data": {
+      "image/png": "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\nYWFh3DIkSavUJCOwo4HfSnIH8AkGhw7PBfZO8sgtqg4CduyucVWtr6q1VbV2bm5ugjIkSavR2AFW\nVWdV1UFVNQ+cDFxZVW8ErgJO6lY7Fbhs4iolSdrFLD4H9qfAHyXZxuCc2Mdm0IckaZWbyt3oq+qL\nwBe76duAI6fxvJIkPR7vxCFJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEm\nSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklq\nkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklq0tgBluTgJFcluSnJ1iRv75bvk+SKJLd23589\nvXIlSRqYZAS2E/jjqjoMOAo4I8lhwJnAhqo6FNjQzUuSNFVjB1hV3V1Vm7vpHwE3AwcCJwAXdKtd\nAJw4aZGSJO1qKufAkswDRwDXAvtX1d3dQ/cA+0+jD0mShk0cYEmeCfwN8AdV9Y/Dj1VVAfU47dYl\n2Zhk48LCwqRlSJJWmYkCLMmeDMLrwqr6VLf43iQHdI8fANy3u7ZVtb6q1lbV2rm5uUnKkCStQpNc\nhRjgY8DNVfXfhx66HDi1mz4VuGz88iRJ2r01E7Q9Gvhd4MYk13fL/gw4B7gkyenAncDrJytRkqTH\nGjvAqurLQB7n4WPHfV5JkvrwThySpCYZYJKkJhlgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZYJKk\nJhlgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZ\nYJKkJhlgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZYJKkJs0swJIcl+SWJNuSnDmrfiRJq9NMAizJ\nHsD/BF4NHAa8Iclhs+hLkrQ6zWoEdiSwrapuq6qHgE8AJ8yoL0nSKjSrADsQuGtofnu3TJKkqUhV\nTf9Jk5OA46rq97v53wX+ZVW9dWiddcC6bvZFwC1TL2RgP+C7y7xdCzWO284ap9OuhRrHbWeN02nX\nQo19Pb+q5kauVVVT/wJeDnx+aP4s4KxZ9NWjlo3LvV0LNa7kn80a/dmWU18rucZpf83qEOI3gEOT\nHJLkKcDJwOUz6kuStAqtmcWTVtXOJG8FPg/sAZxXVVtn0ZckaXWaSYABVNVngc/O6vkXYX0D7Vqo\n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\nYII=\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f66f2d57400>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     }
    ],
    "source": [
-    "tt = ''.maketrans(trans)\n",
-    "print(ca.translate(tt))"
+    "fc = collections.Counter(sanitise(cb))\n",
+    "plot_frequency_histogram(fc)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 55,
    "metadata": {},
    "outputs": [
     {
-     "name": "stdout",
+     "name": "stderr",
      "output_type": "stream",
      "text": [
-      "maryam jodie has gone i arrived in selcuk as planned but she didnt make the rendezvous the local\n",
-      "station think she may have been kidnapped but there has been no ransom demand and there is nothing\n",
-      "much to go on her room had been ransacked and she left no message but something tells me she is ok\n",
-      "and we should move on i think she may have planned this meanwhile i have the document jodie wanted\n",
-      "from london i dont know how she knew but the fifth chapter was hidden in a cavity in a stone lintel\n",
-      "in some remains in the ephesus room at the british museum it was encrypted using another poly\n",
-      "alphabetic cipher invented in the nineteenth century i asked the museum to test it and the document\n",
-      "is authentic so i guess the imperial cipher school really had moved on perhaps i shouldnt have been\n",
-      "surprised after the discovery at bodrum but it leaves me wondering what else they developed one odd\n",
-      "feature was a frieze running round three sides of the lintel consisting of a single row of\n",
-      "blackandwhite tiles that the museum think were added in the roman period they read in sequence\n",
-      "wwbbwwwbwwwbwwwbwwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb www bbw\n",
-      "wwbw wbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwwb www\n",
-      "bwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb wwwb wwwb wwwb\n",
-      "wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb www\n",
-      "www www www www www www www www www www www www www www www www www www www www www www www www wwbw\n",
-      "wwbw www www www www www www www www www www www www www www www www www www www www www www www www\n",
-      "www wwwb wwwb www wb wwwb bbw wwww bbb wwwb wwwb wwwb www bw www bbb wwbw wwbw bbb www bbbb\n",
-      "wwbbbwwwbbbwwbbbwb www bwwwwbwbwwbwwbwwwbww www bwbwwbbwwbwwbwbwwwwb www bbw bbw\n",
-      "bwwbwwbwwwwwbwwbwwwb www wb www bwwwbwwbwwwbwbwwwbwb www wwbwwwbwbwbwbwbwwwb www bwwwbwbwbwbwwbwwbww\n",
-      "www bwwwbwwbwwwwbwwbwwwb www bbb bbw bbbb wwbw wwww bbb bbw bwbwbwbbbbbwwwbwwwbw wwbw bbbb ww bbb\n",
-      "www bbbb wwwb www wb www bwwwbwwbwwwbwbwbwwwb www wwbwwwbwbwbwbwbwwwb wwwb wwwb www bwb www wwbw\n",
-      "wwww bwbwwwwbwwwwbwwbwwwb www bwwwbwbwwbwwwbwwwwb www bwbwwbbwbwwwbwwwb wwwb www bwb www wwbw www wb\n",
-      "wwbw wwbw www bwwwbwwwbwwbwwwbwb wwwb www bbb wbwwwbwbwwwbwbwwwbww bbb wwbw wwbw bww www bbbb wwbw\n",
-      "wwbwbbbwwbbbwbwwwbww www www www www www www www www www www www www www www www www www www www www\n",
-      "www www www www www wwbw wwbw www www www www www www www www www www www www www www www www www\n",
-      "www www www www www www www www wbwwwbwbwwwbwwwbwwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb\n",
-      "wwwb wwwb wwwb wwwb wwwb wwwb www bwb www bwbwbwbwbwbwbwbwbwb wbwbwbwbwbwbwbwbwbwb\n",
-      "wbwbwbwbwbwbwbwbwbwb wbwbwbwbwbwbwbwbwbwb www bwwbbbwbbbwbbbwbbbwb bbw bbb wbbbwbbbwbbbwbbbwb bbw\n",
-      "bbb wbbbwbbbwbbbwbbbwb bbwbbbwbbbwwbwwwbwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb\n",
-      "wwwb wwwb wwwb www bwwwbwwwbwwwbwwbwwi have used b for the black tiles and w for the white ones it\n",
-      "took me a while to figure out that the frieze is steganography concealing the keyword for the cipher\n",
-      "in chapter five without jodie i am not sure where to go next there are only two possibilities as far\n",
-      "as i can see but i have no idea where one of them is and as far as i can tell no one else knows\n",
-      "either so i guess i will head for olympia see you there\n"
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
      ]
+    },
+    {
+     "data": {
+      "image/png": "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\nTqqqlVW1cmZmZo5lSJKWq7kG2NnA4d304cBZQ8sP685G3Be4Y+hQoyRJEzPyH1om+TKwH7BTkpuA\nDwMnAGckeTtwA3Bot/o5wIHABuBu4G1TqPlh+Q/9pKXHv2s9nJEBVlVveJiH9n+IdQs4Yr5FSZI0\nilfikCQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJAJMkNckAkyQ1aeSlpCRJ\nS8NSu66kAcbS+6VK0nLgIURJUpMcgUnSBHgkZ8tzBCZJapIBJklqkocQNTEeQpG0JTkCkyQ1yQCT\nJDXJAJMkNcnPwKQp8TNBabocgUmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKa\n5BeZJY3NL2lrMXAEJklqkgEmSWqShxC3MA+9SNJkOAKTJDXJAJMkNckAkyQ1yQCTJDXJAJMkNcmz\nELWgPCtT0lw5ApMkNckAkyQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJ0+iXME9Rl7SUOQKTJDVpXiOw\nJNcDdwL3AfdW1cokOwCnA7PA9cChVfWr+ZUpSdLmJjECe0lV7VlVK7v5o4HVVbUCWN3NS5I0UdM4\nhHgQcGo3fSpw8BT6kCQtc/MNsAK+m2RtklXdsp2r6uZu+ufAzvPsQ5KkB5nvWYgvqqqNSZ4MnJvk\nJ8MPVlUlqYdq2AXeKoDdd999nmVIkpabeY3Aqmpjd38rcCawD3BLkl0AuvtbH6btSVW1sqpWzszM\nzKcMSdIyNOcAS7JtksdvmgZeAawDzgYO71Y7HDhrvkVKkvRA8zmEuDNwZpJNz/Olqvp2kouBM5K8\nHbgBOHT+ZUqStLk5B1hV/Qx47kMsvx3Yfz5FSZI0ilfikCQ1yWshSsuY18tUyxyBSZKaZIBJkppk\ngEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKa5NXo\ntax49XVp6TDAJKkxvhEb8BCiJKlJjsAkaYE4kpofA0yS9LAWc8h6CFGS1CQDTJLUJANMktQkA0yS\n1CQDTJLUJANMktQkA0yS1CS/BzZHi/m7EZK0HDgCkyQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJAJMk\nNckAkyQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJAJMkNcn/B6Ym+f/YJDkC\n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\nkyQ16f8AOePhb12xLykAAAAASUVORK5CYII=\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f66f2b8a320>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     }
    ],
    "source": [
-    "trans = {\n",
-    " 'A': 'g',\n",
-    " 'B': 'h',\n",
-    " 'C': 'c',\n",
-    " 'D': 'a',\n",
-    " 'E': 'b',\n",
-    " 'F': 'i',\n",
-    " 'G': 'j',\n",
-    " 'H': 'k',\n",
-    " 'I': 'l',\n",
-    " 'J': 'm',\n",
-    " 'K': 'n',\n",
-    " 'L': 'o',\n",
-    " 'M': 'p',\n",
-    " 'N': 'q',\n",
-    " 'O': 'd',\n",
-    " 'P': 'r',\n",
-    " 'Q': 's',\n",
-    " 'R': 't',\n",
-    " 'S': 'u',\n",
-    " 'T': 'v',\n",
-    " 'U': 'w',\n",
-    " 'V': 'x',\n",
-    " 'W': 'y',\n",
-    " 'X': 'z',\n",
-    " 'Y': 'e',\n",
-    " 'Z': 'f'}\n",
-    "\n",
-    "tt = ''.maketrans(trans)\n",
-    "print('\\n'.join(tpack(segment(sanitise(ca.translate(tt))))))"
+    "fp = collections.Counter(vigenere_decipher(sanitise(cb), kbv))\n",
+    "plot_frequency_histogram(fp)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 56,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
     {
      "data": {
+      "image/png": "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\nqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSaPeC1GaFYuP//LA695wyssmWImk\n2eIITJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQk\nA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANM\nktQkA0yS1KSRAyzJFkkuT/Klbn7vJJcl2ZDkrCRbjV6mJEkPNY4R2NuB9dPmTwU+XFVPB34GHD2G\nPiRJeoiRAizJHsDLgNO6+QCHAOd0q6wAjhilD0mSNmfUEdg/An8DPNDN7wTcWVX3d/M3A7uP2Ick\nSQ8zdIAleTlwR1WtHrL9siSrkqzauHHjsGVIkhaoUUZgBwN/kuQG4DP0Dh1+BNg+yaJunT2AWzbX\nuKqWV9WSqloyNTU1QhmSpIVo6ACrqhOqao+qWgy8Grigql4HXAgc2a22FDh35ColSdrEJK4Dew/w\nriQb6H0ndvoE+pAkLXCL+q/SX1VdBFzUTV8HHDCO15Uk6ZF4Jw5JUpMMMElSkwwwSVKTDDBJUpMM\nMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTDDBJ\nUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKT\nDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSk4YOsCR7JrkwydVJ1iV5e7d8\nxyTnJ7m2+7nD+MqVJKlnlBHY/cBfV9W+wIHAMUn2BY4HVlbVPsDKbl6SpLEaOsCq6taqWtNN/xJY\nD+wOHA6s6FZbARwxapGSJG1qLN+BJVkM7AdcBuxSVbd2T90G7DKOPiRJmm7kAEuyHfA54B1V9Yvp\nz1VVAfUI7ZYlWZVk1caNG0ctQ5K0wIwUYEm2pBdeZ1bV57vFtyfZtXt+V+COzbWtquVVtaSqlkxN\nTY1ShiRpARrlLMQApwPrq+ofpj11HrC0m14KnDt8eZIkbd6iEdoeDLwBuCrJFd2yvwVOAc5OcjRw\nI/Cq0UqUJOnhhg6wqroUyCM8feiwrytJ0iC8E4ckqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaYJKlJ\nBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaY\nJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSp\nSQaYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSRMJsCSHJbkmyYYkx0+iD0nSwjb2AEuyBfDP\nwEuAfYHXJNl33P1Ikha2SYzADgA2VNV1VXUv8Bng8An0I0lawCYRYLsDN02bv7lbJknS2KSqxvuC\nyZHAYVX15m7+DcDvV9XbNllvGbCsm30GcM1YC/l/OwM/mePtrHF221njeNq1UOOw7axxfO0G8dSq\nmuq7VlWN9QEcBHx92vwJwAnj7mcG9aya6+2s0d9tLvU1n2ucz79bCzWO+zGJQ4jfB/ZJsneSrYBX\nA+dNoB9J0gK2aNwvWFX3J3kb8HVgC+CMqlo37n4kSQvb2AMMoKq+AnxlEq89hOUNtLPG2W1njeNp\n10KNw7azxvG1G5uxn8QhSdJjwVtJSZKaZIBtIsniJGtnqe+Tkhw34T6OTbI+yZkT7mfo7Zjk2yP0\nO3DbEWu8a5h2mj1Jtk/y1tmuQ+NjgC08bwVeXFWvm+1CHklV/cFstNXsSs8k35O2p7f/a56Y1wGW\n5ItJVidZ1104PahFSc7sRirnJNlmgL6OSvKDJFcm+fcZ1PjeJD9Kcim9C7oHafP6JN9LckWSj3X3\nnxyk3b8CTwO+muSdM6jxfd3NmS9N8ukZjBK3SPLxbvt/I8nWA/Y39Ohm2LZJnpbk8iTPG7bvR3nt\nxUl+mOQT3b/1mUlelORbSa5NckCftuuH3I7vSrK2e7xjBnXOaN/v2v7ffjyTfaTr85oknwTWAnsO\n0GbbJF/u/tbWJvnzQfoCTgF+u/u7+eAM6ls7bf64JCf1aXNKkmOmzfc9spLk3UmO7aY/nOSCbvqQ\nfkdLkjyve+95fLdt1iV5Vp82J0/fJ5J8IMnbH63NtHXf0m3DK5Jcn+TCQdpNxGxfiDbJB7Bj93Nr\nen8cOw3QZjFQwMHd/BnAcX3a/C7wI2Dn6f0O0NdzgauAbYAnAhsG6Ot3gP8Etuzm/wU4agbb5IYH\n6xxw/ecBVwCPB54AXNuvxmnb8X7g97r5s4HXD9jnXSP8mw/ctqtxLb0PDpcDz5lgP/cDz6b3oXF1\nt1+F3n1Cvzju7Tht39oW2A5YB+w3QJ0z2veH3Y836fMB4MAZbM8/Az4+bf5JM/n3nuH+9JA2wHHA\nSX3a7Ad8c9r81cCefdocCHy2m74E+B6wJXAi8BcD1Pl+4EP0bqTe98YR3e+1ppt+HPBfDPD+uMlr\nbNnV+oqZtBvnY16PwIBjk1wJfJfeJ7t9Bmx3U1V9q5v+FPD8PusfQm/n+wlAVf33gP28APhCVd1T\nVb9gsAu+D6X3hvH9JFd0808bsL9hHAycW1W/qqpf0gvPQV1fVVd006vp/dHMNVPAucDrqurKCfZz\nfVVdVVUP0AuTldV7F7iK/ttlmO34fHr71t1VdRfweXr7Wz8z3fdhuP14uhur6rszWP8q4MVJTk3y\ngqr6+Qz7m6iquhx4cpLdkjwH+FlV3dSn2WrguUmeCPwa+A6whN62vWSAbk8GXty1+fsBarwB+GmS\n/YA/Bi6vqp8O0M90HwEuqKqZvCeM1USuA5sLkrwQeBFwUFXdk+QieqOIQWx6bcFcutYgwIqqOmG2\nCxnAr6dN/4beSHiu+TnwY3pv1FdPsJ/p2+KBafMP0P/v8LHcjrOx7989k5Wr6kdJ9gdeCrw/ycqq\nOnkypXE/D/2qZdD3kM8CRwJPAc7qt3JV3ZfkeuCNwLeBHwB/BDwdWD9AfzvRG2lv2dU4yDY9revv\nKfRG2wNL8kbgqcDb+qw6UfN5BPYkep987knyTHpD9EHtleSgbvq1wKV91r8AeGWSnQCS7DhgPxcD\nRyTZOskTgFcM0GYlcGSSJz/YV5KnDtjfML4FvKI7vr4d8PIJ9jUb7gX+FDgqyWtnu5gxuoTevrVN\nkm3p/Y6DfJKf6b4Pw+3HQ0uyG3BPVX0K+CCw/4BNf0nvMPhM3E5vNLVTkt9i8P3/LHq30TuSXpgN\n4hJ6hygv7qbfQm9kNMiHiI8B7wPOBE4dsL8vAIfR+5rg6wO2Iclzuzpf3x1RmDXzdgQGfA14S5L1\n9O50P5NDFNcAxyQ5g96n8o8+2spVtS7JB4BvJvkNve9T3tivk6pak+Qs4ErgDnr3kezX5uokfwd8\nI70ztu4DjgFu7Nd2GFX1/STn0ftEeDu9wzdz6pDNJmY8Yqiqu5O8HDg/yV1V1fy9O7t96xP0vksB\nOK07tNXPjPb9aX3NaD8e0bOBDyZ5gN7+/5eDNKqqn3YnzqwFvlpV7x6gzX1JTqa3HW8BfjhgX+u6\nML+lqm4dpA290Hov8J1un/wVA3zoSHIUcF9V/Ud6J3R9O8khVXVBnxrv7U7AuLOqfjNgjdAbde0I\nXJgEejf1ffMM2o+Nd+JQX0m2q6q7ujPSLgaWVdWa2a5rU90IeE1VTXJEOm8lWQx8qaoe9Qy2AV7n\nJHonuXxoDGVpQroPwGuAV1bVtbNdzzDm8yFEjc/y7oSRNcDn5mh47Ubvi2/fNKU+kuxL72zRla2G\nFzgCkyQ1yhGYJKlJBpgkqUkGmCSpSQaYJKlJBpgkqUkGmCSpSf8LdgXu+00ljFcAAAAASUVORK5C\nYII=\n",
       "text/plain": [
-       "{'A': 'g',\n",
-       " 'B': 'h',\n",
-       " 'C': 'c',\n",
-       " 'D': 'a',\n",
-       " 'E': 'b',\n",
-       " 'F': 'i',\n",
-       " 'G': 'j',\n",
-       " 'H': 'k',\n",
-       " 'I': 'l',\n",
-       " 'J': 'm',\n",
-       " 'K': 'n',\n",
-       " 'L': 'o',\n",
-       " 'M': 'p',\n",
-       " 'N': 'q',\n",
-       " 'O': 'd',\n",
-       " 'P': 'r',\n",
-       " 'Q': 's',\n",
-       " 'R': 't',\n",
-       " 'S': 'u',\n",
-       " 'T': 'v',\n",
-       " 'U': 'w',\n",
-       " 'V': 'x',\n",
-       " 'W': 'y',\n",
-       " 'X': 'z',\n",
-       " 'Y': 'e',\n",
-       " 'Z': 'f'}"
+       "<matplotlib.figure.Figure at 0x7f66f2c1ea90>"
       ]
      },
-     "execution_count": 15,
      "metadata": {},
-     "output_type": "execute_result"
+     "output_type": "display_data"
     }
    ],
    "source": [
-    "trans"
+    "fp = collections.Counter(vbai)\n",
+    "plot_frequency_histogram(fp)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 57,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
     {
      "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbMAAAEmCAYAAADoRn53AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFi1JREFUeJzt3X2QXfV93/H3JxJgwDbEIE/KkxcX0hbixg9COI3tphCI\nXGIrnYgiExfokFHcWOM2KWnlcYOpas9AnInbmdDWSiAhYBcIrRO1yCEupDHGGEs8I7BsGbARzsTi\nISSYwSD49o9zZF82K+3Z1V2tftL7NbOj8/D77fneo7P3c3/nnntuqgpJklr2Q/NdgCRJu8swkyQ1\nzzCTJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNW/hfBcw2ZFHHlkTExPzXYYk\naS9w5513PlFVi6Zrt9eF2cTEBBs3bpzvMiRJe4Ek3xzSztOMkqTmGWaSpOYZZpKk5hlmkqTmGWaS\npOYZZpKk5hlmkqTmGWaSpOYNCrMkS5NsTrIlyeop1r8ryV1JtidZPrL8zUluT7IpyX1Jzhln8ZIk\nwYAwS7IAuBx4N3AS8L4kJ01q9i3gAuAzk5Y/B5xXVScDS4H/nOTw3S1akqRRQ25ntQTYUlUPAyS5\nFlgGPLijQVU92q97ebRjVX1tZPrbSb4DLAL+arcr349NrL5xcNtHLz1rDiuRpL3DkNOMRwOPjcxv\n7ZfNSJIlwIHAN2baV5KkXdkjF4Ak+TvA1cC/rKqXp1i/MsnGJBu3bdu2J0qSJO1DhoTZ48CxI/PH\n9MsGSfJa4EbgI1X15anaVNXaqlpcVYsXLZr2Tv+SJL3CkDDbAJyY5PgkBwIrgHVDfnnf/rPAH1TV\nDbMvU5KknZs2zKpqO7AKuAl4CLi+qjYlWZPkvQBJTkmyFTgb+FSSTX33fw68C7ggyT39z5vn5JFI\nkvZbg76cs6rWA+snLbt4ZHoD3enHyf2uAa7ZzRolSdol7wAiSWqeYSZJap5hJklqnmEmSWqeYSZJ\nap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqe\nYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEm\nSWqeYSZJap5hJklqnmEmSWqeYSZJat6gMEuyNMnmJFuSrJ5i/buS3JVke5Llk9adn+Tr/c/54ypc\nkqQdpg2zJAuAy4F3AycB70ty0qRm3wIuAD4zqe/rgI8CpwJLgI8m+eHdL1uSpB8YMjJbAmypqoer\n6gXgWmDZaIOqerSq7gNentT3Z4DPV9VTVfU08Hlg6RjqliTp+4aE2dHAYyPzW/tlQ+xOX0mSBtkr\nLgBJsjLJxiQbt23bNt/lSJIaMyTMHgeOHZk/pl82xKC+VbW2qhZX1eJFixYN/NWSJHWGhNkG4MQk\nxyc5EFgBrBv4+28Czkzyw/2FH2f2yyRJGptpw6yqtgOr6ELoIeD6qtqUZE2S9wIkOSXJVuBs4FNJ\nNvV9nwL+E10gbgDW9MskSRqbhUMaVdV6YP2kZRePTG+gO4U4Vd8rgSt3o0ZJknZpr7gARJKk3WGY\nSZKaZ5hJkppnmEmSmmeYSZKaZ5hJkppnmEmSmmeYSZKaZ5hJkppnmEmSmmeYSZKaZ5hJkppnmEmS\nmmeYSZKaZ5hJkppnmEmSmjfoyzklqWUTq28c3PbRS8+aw0o0VxyZSZKaZ5hJkppnmEmSmmeYSZKa\nZ5hJkppnmEmSmmeYSZKaZ5hJkppnmEmSmmeYSZKaZ5hJkppnmEmSmmeYSZKaZ5hJkppnmEmSmjco\nzJIsTbI5yZYkq6dYf1CS6/r1dySZ6JcfkOSqJPcneSjJh8dbviRJA8IsyQLgcuDdwEnA+5KcNKnZ\nhcDTVXUC8Engsn752cBBVfUm4G3AL+0IOkmSxmXIyGwJsKWqHq6qF4BrgWWT2iwDruqnbwBOTxKg\ngEOTLAQOBl4A/noslUuS1Fs4oM3RwGMj81uBU3fWpqq2J3kGOIIu2JYBfwEcAvxKVT21u0VL2rWJ\n1TcObvvopWfNYSXSnjHXF4AsAV4CjgKOB/5tkjdObpRkZZKNSTZu27ZtjkuSJO1rhoTZ48CxI/PH\n9MumbNOfUjwMeBI4F/iTqnqxqr4D3AYsnryBqlpbVYuravGiRYtm/igkSfu1IWG2ATgxyfFJDgRW\nAOsmtVkHnN9PLwduqaoCvgWcBpDkUODtwFfHUbgkSTtM+55Z/x7YKuAmYAFwZVVtSrIG2FhV64Ar\ngKuTbAGeogs86K6C/L0km4AAv1dV983FA5nM9wwkaf8x5AIQqmo9sH7SsotHpp+nuwx/cr9np1ou\nSdI4eQcQSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJ\nUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8xbOdwHS\nqInVNw5u++ilZ81hJXsH94c0jGGmOeGTsKQ9ydOMkqTmGWaSpOYZZpKk5vmemaSm+H6spuLITJLU\nPMNMktQ8w0yS1DzDTJLUvEFhlmRpks1JtiRZPcX6g5Jc16+/I8nEyLp/mOT2JJuS3J/kVeMrX5Kk\nAWGWZAFwOfBu4CTgfUlOmtTsQuDpqjoB+CRwWd93IXAN8IGqOhn4KeDFsVUvSRLDRmZLgC1V9XBV\nvQBcCyyb1GYZcFU/fQNwepIAZwL3VdW9AFX1ZFW9NJ7SJUnqDAmzo4HHRua39sumbFNV24FngCOA\nHwUqyU1J7kry73a/ZEmSXmmuPzS9EHgHcArwHHBzkjur6ubRRklWAisBjjvuuDkuSZK0rxkSZo8D\nx47MH9Mvm6rN1v59ssOAJ+lGcV+oqicAkqwH3gq8Isyqai2wFmDx4sU184chqTXeyUPjNOQ04wbg\nxCTHJzkQWAGsm9RmHXB+P70cuKWqCrgJeFOSQ/qQ+8fAg+MpXZKkzrQjs6ranmQVXTAtAK6sqk1J\n1gAbq2odcAVwdZItwFN0gUdVPZ3kt+gCsYD1VTX85ZgkSQMMes+sqtYD6yctu3hk+nng7J30vYbu\n8nxJkuaEdwCRJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXP\nMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCT\nJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDVv4XwXsD+bWH3j\n4LaPXnrWHFYiSW0bNDJLsjTJ5iRbkqyeYv1BSa7r19+RZGLS+uOSPJvkovGULUnSD0w7MkuyALgc\nOAPYCmxIsq6qHhxpdiHwdFWdkGQFcBlwzsj63wI+N76ypfnjiFra+wwZmS0BtlTVw1X1AnAtsGxS\nm2XAVf30DcDpSQKQ5OeAR4BN4ylZkqRXGhJmRwOPjcxv7ZdN2aaqtgPPAEckeTXw74H/uPulSpI0\ntbm+mvES4JNV9eyuGiVZmWRjko3btm2b45IkSfuaIVczPg4cOzJ/TL9sqjZbkywEDgOeBE4Flif5\nDeBw4OUkz1fVb492rqq1wFqAxYsX12weiCRp/zUkzDYAJyY5ni60VgDnTmqzDjgfuB1YDtxSVQW8\nc0eDJJcAz04OMkmSdte0YVZV25OsAm4CFgBXVtWmJGuAjVW1DrgCuDrJFuApusCTJGmPGPSh6apa\nD6yftOzikenngbOn+R2XzKI+SZKm5e2sJEnNM8wkSc0zzCRJzTPMJEnNM8wkSc0zzCRJzTPMJEnN\nM8wkSc0zzCRJzTPMJEnNM8wkSc0zzCRJzTPMJEnNM8wkSc0zzCRJzRv0fWaStD+aWH3j4LaPXnrW\nHFai6TgykyQ1zzCTJDXPMJMkNc8wkyQ1zzCTJDXPqxmlPWTolXFeFSfNnCMzSVLzDDNJUvMMM0lS\n8wwzSVLzDDNJUvO8mlGS9hJe8Tp7jswkSc0zzCRJzfM0oyTth/a1r7cxzMbEc92SNH8GnWZMsjTJ\n5iRbkqyeYv1BSa7r19+RZKJffkaSO5Pc3/972njLlyRpwMgsyQLgcuAMYCuwIcm6qnpwpNmFwNNV\ndUKSFcBlwDnAE8B7qurbSX4MuAk4etwPQsPsa6cVJGmHISOzJcCWqnq4ql4ArgWWTWqzDLiqn74B\nOD1Jquruqvp2v3wTcHCSg8ZRuCRJOwwJs6OBx0bmt/K3R1ffb1NV24FngCMmtfl54K6q+t7sSpUk\naWp75AKQJCfTnXo8cyfrVwIrAY477rg9UZIkaR8yZGT2OHDsyPwx/bIp2yRZCBwGPNnPHwN8Fjiv\nqr4x1Qaqam1VLa6qxYsWLZrZI5Ak7feGjMw2ACcmOZ4utFYA505qsw44H7gdWA7cUlWV5HDgRmB1\nVd02vrK1p3jRiKQWTDsy698DW0V3JeJDwPVVtSnJmiTv7ZtdARyRZAvwq8COy/dXAScAFye5p/95\n/dgfhSRpvzboPbOqWg+sn7Ts4pHp54Gzp+j3MeBju1mjJEm75L0ZJUnNM8wkSc0zzCRJzfNGw5K+\nz6tX1SpHZpKk5hlmkqTmeZpxEk+zSFJ7HJlJkppnmEmSmmeYSZKaZ5hJkppnmEmSmmeYSZKaZ5hJ\nkppnmEmSmueHpiVpzLz5wp7nyEyS1DzDTJLUPE8zar/lqSBp3+HITJLUPMNMktQ8w0yS1DzDTJLU\nPMNMktQ8w0yS1DzDTJLUPMNMktQ8w0yS1DzDTJLUPMNMktQ8w0yS1DzDTJLUvEFhlmRpks1JtiRZ\n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\ncPkAAAAASUVORK5CYII=\n",
       "text/plain": [
-       "{'a': 'D',\n",
-       " 'b': 'E',\n",
-       " 'c': 'C',\n",
-       " 'd': 'O',\n",
-       " 'e': 'Y',\n",
-       " 'f': 'Z',\n",
-       " 'g': 'A',\n",
-       " 'h': 'B',\n",
-       " 'i': 'F',\n",
-       " 'j': 'G',\n",
-       " 'k': 'H',\n",
-       " 'l': 'I',\n",
-       " 'm': 'J',\n",
-       " 'n': 'K',\n",
-       " 'o': 'L',\n",
-       " 'p': 'M',\n",
-       " 'q': 'N',\n",
-       " 'r': 'P',\n",
-       " 's': 'Q',\n",
-       " 't': 'R',\n",
-       " 'u': 'S',\n",
-       " 'v': 'T',\n",
-       " 'w': 'U',\n",
-       " 'x': 'V',\n",
-       " 'y': 'W',\n",
-       " 'z': 'X'}"
+       "<matplotlib.figure.Figure at 0x7f66f2b0eeb8>"
       ]
      },
-     "execution_count": 16,
      "metadata": {},
-     "output_type": "execute_result"
+     "output_type": "display_data"
     }
    ],
    "source": [
-    "{v: k for k, v in trans.items()}"
+    "plot_frequency_histogram({k: 10**Pl[k] for k in Pl})"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 91,
    "metadata": {},
    "outputs": [
     {
-     "name": "stdout",
+     "name": "stderr",
      "output_type": "stream",
      "text": [
-      "maryam jodie has gone i arrived in selcuk as planned but she didnt make the rendezvous the local\n",
-      "station think she may have been kidnapped but there has been no ransom demand and there is nothing\n",
-      "much to go on her room had been ransacked and she left no message but something tells me she is ok\n",
-      "and we should move on i think she may have planned this meanwhile i have the document jodie wanted\n",
-      "from london i dont know how she knew but the fifth chapter was hidden in a cavity in a stone lintel\n",
-      "in some remains in the ephesus room at the british museum it was encrypted using another poly\n",
-      "alphabetic cipher invented in the nineteenth century i asked the museum to test it and the document\n",
-      "is authentic so i guess the imperial cipher school really had moved on perhaps i shouldnt have been\n",
-      "surprised after the discovery at bodrum but it leaves me wondering what else they developed one odd\n",
-      "feature was a frieze running round three sides of the lintel consisting of a single row of\n",
-      "blackandwhite tiles that the museum think were added in the roman period they read in sequence\n",
-      "wwbbwwwbwwwbwwwbwwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb www bbw\n",
-      "wwbw wbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwwb www\n",
-      "bwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb wwwb wwwb wwwb\n",
-      "wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb www\n",
-      "www www www www www www www www www www www www www www www www www www www www www www www www wwbw\n",
-      "wwbw www www www www www www www www www www www www www www www www www www www www www www www www\n",
-      "www wwwb wwwb www wb wwwb bbw wwww bbb wwwb wwwb wwwb www bw www bbb wwbw wwbw bbb www bbbb\n",
-      "wwbbbwwwbbbwwbbbwb www bwwwwbwbwwbwwbwwwbww www bwbwwbbwwbwwbwbwwwwb www bbw bbw\n",
-      "bwwbwwbwwwwwbwwbwwwb www wb www bwwwbwwbwwwbwbwwwbwb www wwbwwwbwbwbwbwbwwwb www bwwwbwbwbwbwwbwwbww\n",
-      "www bwwwbwwbwwwwbwwbwwwb www bbb bbw bbbb wwbw wwww bbb bbw bwbwbwbbbbbwwwbwwwbw wwbw bbbb ww bbb\n",
-      "www bbbb wwwb www wb www bwwwbwwbwwwbwbwbwwwb www wwbwwwbwbwbwbwbwwwb wwwb wwwb www bwb www wwbw\n",
-      "wwww bwbwwwwbwwwwbwwbwwwb www bwwwbwbwwbwwwbwwwwb www bwbwwbbwbwwwbwwwb wwwb www bwb www wwbw www wb\n",
-      "wwbw wwbw www bwwwbwwwbwwbwwwbwb wwwb www bbb wbwwwbwbwwwbwbwwwbww bbb wwbw wwbw bww www bbbb wwbw\n",
-      "wwbwbbbwwbbbwbwwwbww www www www www www www www www www www www www www www www www www www www www\n",
-      "www www www www www wwbw wwbw www www www www www www www www www www www www www www www www www\n",
-      "www www www www www www www www wbwwwbwbwwwbwwwbwwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb\n",
-      "wwwb wwwb wwwb wwwb wwwb wwwb www bwb www bwbwbwbwbwbwbwbwbwb wbwbwbwbwbwbwbwbwbwb\n",
-      "wbwbwbwbwbwbwbwbwbwb wbwbwbwbwbwbwbwbwbwb www bwwbbbwbbbwbbbwbbbwb bbw bbb wbbbwbbbwbbbwbbbwb bbw\n",
-      "bbb wbbbwbbbwbbbwbbbwb bbwbbbwbbbwwbwwwbwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb\n",
-      "wwwb wwwb wwwb www bwwwbwwwbwwwbwwbwwi have used b for the black tiles and w for the white ones it\n",
-      "took me a while to figure out that the frieze is steganography concealing the keyword for the cipher\n",
-      "in chapter five without jodie i am not sure where to go next there are only two possibilities as far\n",
-      "as i can see but i have no idea where one of them is and as far as i can tell no one else knows\n",
-      "either so i guess i will head for olympia see you there\n"
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
      ]
+    },
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaoAAAEmCAYAAAAz/dRVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAET1JREFUeJzt3XuQJWV9xvHvI2Dk5gUYNYrjYmKRGE1FHY2IJgbQIl6C\nqWhFElQSrYmJihqJBTGWFKVVGqwYq3LRFQkmEEzEa7xCgQZQRNllkV2WixFUjIpIvCClgPzyx+mV\nYRfY6dO9M+/sfD9Vp+b0mX77/Z0zfc5z3u6e7lQVkiS16l7LXYAkSffEoJIkNc2gkiQ1zaCSJDXN\noJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDVt16XsbL/99qs1a9YsZZeSpEatW7fuhqqa2d58\nSxpUa9as4eKLL17KLiVJjUrytcXM56Y/SVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLT\nDCpJUtMMKklS0wwqSVLTlvQUShrHmuM+3rvNtW951g6oRJJ2PEdUkqSmGVSSpKYZVJKkphlUkqSm\nGVSSpKYZVJKkphlUkqSmGVSSpKYZVJKkphlUkqSmGVSSpKZtN6iSnJLk+iQb7+J3r01SSfbbMeVJ\nkla7xYyoTgUO3/rBJA8DngF8feSaJEn6ue0GVVWdB9x4F796O/A6oMYuSpKkLabaR5XkCOCbVXXp\nyPVIknQnva9HlWQP4K+ZbPZbzPzzwDzA7Oxs3+4kSavcNCOqXwIOAC5Nci2wP7A+yYPvauaqWltV\nc1U1NzMzM32lkqRVqfeIqqouAx64ZboLq7mqumHEuiRJAhZ3ePoZwIXAgUmuS/KSHV+WJEkT2x1R\nVdWR2/n9mtGqkSRpK56ZQpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS\n1DSDSpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSDSpLUNINKktQ0\ng0qS1DSDSpLUNINKktQ0g0qS1LTtBlWSU5Jcn2TjgsdOSnJFki8n+VCS++/YMiVJq9ViRlSnAodv\n9djZwKOr6teBq4DjR65LkiRgEUFVVecBN2712FlVdVs3+QVg/x1QmyRJo+yj+lPgkyMsR5Kkbew6\npHGS1wO3AaffwzzzwDzA7OzskO4k7WTWHPfx3m2ufcuzdkAlatnUI6okRwPPBv64quru5quqtVU1\nV1VzMzMz03YnSVqlphpRJTkceB3w21V187glSZJ0h8Ucnn4GcCFwYJLrkrwE+Adgb+DsJBuSvHMH\n1ylJWqW2O6KqqiPv4uH37IBaJEnahmemkCQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1\nzaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNW3QhRNXKy/2pp2B6/FwvoZLwxGVJKlpBpUkqWkGlSSp\naQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWnbDaokpyS5PsnGBY/tk+Ts\nJFd3Px+wY8uUJK1WixlRnQocvtVjxwHnVNUjgXO6aUmSRrfdoKqq84Abt3r4COC93f33As8duS5J\nkoDp91E9qKq+1d3/NvCgkeqRJOlOBl+PqqoqSd3d75PMA/MAs7OzQ7vTSIZeR8fr8EhaKtOOqL6T\n5BcBup/X392MVbW2quaqam5mZmbK7iRJq9W0QfVR4MXd/RcDHxmnHEmS7mwxh6efAVwIHJjkuiQv\nAd4CPD3J1cBh3bQkSaPb7j6qqjrybn516Mi1SJK0Dc9MIUlqmkElSWqaQSVJappBJUlqmkElSWqa\nQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJatrgCydKklaulXARVEdUkqSmGVSSpKYZ\nVJKkphlUkqSmGVSSpKYZVJKkphlUkqSmGVSSpKYZVJKkphlUkqSmGVSSpKYNCqokr0myKcnGJGck\nuc9YhUmSBAOCKslDgWOAuap6NLAL8IKxCpMkCYZv+tsV2D3JrsAewP8OL0mSpDtMHVRV9U3gbcDX\ngW8BP6iqs8YqTJIkGHA9qiQPAI4ADgC+D7w/yVFVddpW880D8wCzs7MDSpXUmpVwLaPWDX0NV8Pf\nYMimv8OAa6rqu1V1K/BB4Mlbz1RVa6tqrqrmZmZmBnQnSVqNhgTV14EnJdkjSYBDgc3jlCVJ0sSQ\nfVQXAWcC64HLumWtHakuSZKAAfuoAKrqjcAbR6pFkqRteGYKSVLTDCpJUtMMKklS0wwqSVLTDCpJ\nUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wadlFbS9FbDBe+kMTiikiQ1zaCS\nJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDVtUFAluX+SM5Nc\nkWRzkoPGKkySJBh+Utp3AJ+qqucluTewxwg1SZL0c1MHVZL7Ab8FHA1QVbcAt4xTliRJE0M2/R0A\nfBf4lySXJDk5yZ4j1SVJEjBs09+uwOOAV1bVRUneARwHvGHhTEnmgXmA2dnZAd2Nx+sASdLKMWRE\ndR1wXVVd1E2fySS47qSq1lbVXFXNzczMDOhOkrQaTR1UVfVt4BtJDuweOhS4fJSqJEnqDD3q75XA\n6d0Rf18F/mR4SZIk3WFQUFXVBmBupFokSdqGZ6aQJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1\nzaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1bejZ0yVp2XgR1NXBEZUkqWkGlSSpaQaVJKlp\nBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpaYODKskuSS5J8rExCpIkaaEx\nRlSvAjaPsBxJkrYxKKiS7A88Czh5nHIkSbqzoSOqvwdeB9w+Qi2SJG1j6utRJXk2cH1VrUvytHuY\nbx6YB5idnZ22u52K19CRpMUbMqI6GPi9JNcC7wMOSXLa1jNV1dqqmququZmZmQHdSZJWo6mDqqqO\nr6r9q2oN8ALg3Ko6arTKJEnC/6OSJDVu6n1UC1XVZ4HPjrEsSZIWckQlSWqaQSVJappBJUlqmkEl\nSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJatoo5/pbal7PSS1wPZSWhiMqSVLT\nDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS06YO\nqiQPS/KZJJcn2ZTkVWMWJkkSDDt7+m3Aa6tqfZK9gXVJzq6qy0eqTZKk6UdUVfWtqlrf3f8RsBl4\n6FiFSZIEI+2jSrIGeCxw0RjLkyRpi8EXTkyyF/AB4NVV9cO7+P08MA8wOzs7tDtpNCv9wocrvf4W\n+BquDINGVEl2YxJSp1fVB+9qnqpaW1VzVTU3MzMzpDtJ0io05Ki/AO8BNlfV341XkiRJdxgyojoY\neCFwSJIN3e2ZI9UlSRIwYB9VVV0AZMRaJEnahmemkCQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIk\nNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDVt8PWopGkMvQ6Q1xGSVg9HVJKkphlUkqSmGVSSpKYZ\n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\nrkJggg==\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f66f2c0fe48>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     }
    ],
    "source": [
-    "print('\\n'.join(tpack(segment(keyword_decipher(sanitise(ca), 'decoy', KeywordWrapAlphabet.from_last)))))"
+    "fp = collections.Counter(every_nth(scb, 15)[4])\n",
+    "plot_frequency_histogram(fp)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 18,
+   "execution_count": 95,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
     {
      "data": {
       "text/plain": [
-       "3362"
+       "'y'"
       ]
      },
-     "execution_count": 18,
+     "execution_count": 95,
      "metadata": {},
      "output_type": "execute_result"
+    },
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaoAAAEmCAYAAAAz/dRVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAERVJREFUeJzt3X+QJGV9x/H3Rw4jB0REVo3iumgsEmN+qGsiookBtS6K\nwVS0IopKorUxiqgRLYixtKxYRQorxqr8MCcSTKAwETWa+AsKNIAiyh2HHJyAEUSMikj8gZQC8s0f\n0yd7e8DuTPfdPrv7flVNbfdsP/18Z7ZnPvP09HanqpAkqVX3We4CJEm6NwaVJKlpBpUkqWkGlSSp\naQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpaet2Z2cHHHBAzczM7M4uJUmN2rRp001VNbXY\ncrs1qGZmZrjkkkt2Z5eSpEYl+dpSlnPXnySpaQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSp\naQaVJKlpBpUkqWkGlSSpabv1FEpaPWZO+NjYba476dm7oBJJq50jKklS0wwqSVLTDCpJUtMMKklS\n0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTFg2qJKcmuTHJ1rv53euTVJIDdk15\nkqS1bikjqtOADQvvTPJw4JnA9QPXJEnSzywaVFV1PnDz3fzqncAbgRq6KEmStpvoO6okRwLfqKrL\nBq5HkqQdjH09qiTrgb9gtNtvKcvPAXMA09PT43YnSVrjJhlRPQo4CLgsyXXAgcDmJA+5u4WramNV\nzVbV7NTU1OSVSpLWpLFHVFV1OfCg7fNdWM1W1U0D1iVJErC0w9PPBC4CDk5yQ5KX7fqyJEkaWXRE\nVVVHLfL7mcGqkSRpAc9MIUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJ\nappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqa\nQSVJappBJUlqmkElSWqaQSVJatqiQZXk1CQ3Jtk6776Tk3w5yZeSfDjJfru2TEnSWrWUEdVpwIYF\n950DPLaqfg24Gjhx4LokSQKWEFRVdT5w84L7zq6qO7rZzwMH7oLaJEka5DuqPwE+McB6JEnaybo+\njZO8CbgDOONelpkD5gCmp6f7dCdJg5o54WNjt7nupGfvgkp0byYeUSU5BjgCeFFV1T0tV1Ubq2q2\nqmanpqYm7U6StEZNNKJKsgF4I/A7VXXrsCVJknSXpRyefiZwEXBwkhuSvAz4O2Bf4JwkW5K8exfX\nKUlaoxYdUVXVUXdz93t3QS2SJO3EM1NIkppmUEmSmmZQSZKaZlBJkppmUEmSmmZQSZKaZlBJkppm\nUEmSmmZQSZKaZlBJkppmUEmSmmZQSZKa1uvCiVoeXuxNq4Xbcn9r4Tl0RCVJappBJUlqmkElSWqa\nQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlq2qJBleTUJDcm2Trvvv2TnJPk\nmu7nA3ZtmZKktWopI6rTgA0L7jsBOLeqHg2c281LkjS4RYOqqs4Hbl5w95HA+7rp9wHPHbguSZKA\nyb+jenBVfbOb/hbw4IHqkSRpB72vR1VVlaTu6fdJ5oA5gOnp6b7daZXoew2dtXANHkkjk46ovp3k\nFwC6nzfe04JVtbGqZqtqdmpqasLuJElr1aRB9VHgpd30S4GPDFOOJEk7Wsrh6WcCFwEHJ7khycuA\nk4BnJLkGeHo3L0nS4Bb9jqqqjrqHXx0+cC2SJO3EM1NIkppmUEmSmmZQSZKaZlBJkppmUEmSmmZQ\nSZKaZlBJkppmUEmSmmZQSZKaZlBJkppmUEmSmmZQSZKa1vvCiSuRF92TpJXDEZUkqWkGlSSpaQaV\nJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpab2CKsnrklyRZGuSM5Pc\nb6jCJEmCHkGV5GHAccBsVT0W2AN4wVCFSZIE/Xf9rQP2SrIOWA/8b/+SJEm6y8RBVVXfAN4BXA98\nE/h+VZ09VGGSJEGP61EleQBwJHAQ8D3gA0mOrqrTFyw3B8wBTE9P9yj1Ll5PShL4XjCElfAc9tn1\n93Tg2qr6TlXdDnwIePLChapqY1XNVtXs1NRUj+4kSWtRn6C6HnhSkvVJAhwObBumLEmSRvp8R3Ux\ncBawGbi8W9fGgeqSJAno8R0VQFW9BXjLQLVIkrQTz0whSWqaQSVJappBJUlqmkElSWqaQSVJappB\nJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqWq+T0kpauVbCBfMkcEQlSWqcQSVJappB\nJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJalqvoEqyX5Kzknw5ybYk\nhwxVmCRJ0P+ktO8CPllVz0tyX2D9ADVJkvQzEwdVkvsDvw0cA1BVtwG3DVOWJEkjfXb9HQR8B/jn\nJJcmOSXJ3gPVJUkS0G/X3zrg8cCrq+riJO8CTgDePH+hJHPAHMD09HSP7lYPrwMkSUvXZ0R1A3BD\nVV3czZ/FKLh2UFUbq2q2qmanpqZ6dCdJWosmDqqq+hbw9SQHd3cdDlw5SFWSJHX6HvX3auCM7oi/\nrwJ/3L8kSZLu0iuoqmoLMDtQLZIk7cQzU0iSmmZQSZKaZlBJkppmUEmSmmZQSZKaZlBJkppmUEmS\nmmZQSZKaZlBJkppmUEmSmmZQSZKaZlBJkprW9+zpkrRmeRHU3cMRlSSpaQaVJKlpBpUkqWkGlSSp\naQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWkGlSSpaQaVJKlpvYMqyR5JLk3yX0MUJEnSfEOMqF4D\nbBtgPZIk7aRXUCU5EHg2cMow5UiStKO+I6q/Bd4I3DlALZIk7WTi61ElOQK4sao2JXnavSw3B8wB\nTE9PT9qdBuZ1dCStFH1GVIcCv5/kOuD9wGFJTl+4UFVtrKrZqpqdmprq0Z0kaS2aOKiq6sSqOrCq\nZoAXAOdV1dGDVSZJEv4flSSpcRN/RzVfVX0G+MwQ65IkaT5HVJKkphlUkqSmGVSSpKYZVJKkphlU\nkqSmGVSSpKYZVJKkphlUkqSmGVSSpKYZVJKkphlUkqSmDXKuv7XGazmpBW6HWiscUUmSmmZQSZKa\nZlBJkppmUEmSmmZQSZKaZlBJkppmUEmSmmZQSZKaZlBJkppmUEmSmmZQSZKaZlBJkpo2cVAleXiS\nTye5MskVSV4zZGGSJEG/s6ffAby+qjYn2RfYlOScqrpyoNokSZp8RFVV36yqzd30D4FtwMOGKkyS\nJBjoO6okM8DjgIuHWJ8kSdv1vnBikn2ADwKvraof3M3v54A5gOnp6b7dSavGarjw4Wp4DMvN53Bx\nvUZUSfZkFFJnVNWH7m6ZqtpYVbNVNTs1NdWnO0nSGtTnqL8A7wW2VdXfDFeSJEl36TOiOhR4MXBY\nki3d7VkD1SVJEtDjO6qquhDIgLVIkrQTz0whSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkEl\nSWqaQSVJappBJUlqmkElSWqaQSVJalrv61FJK1Xf6wB5HSFp93BEJUlqmkElSWqaQSVJappBJUlq\nmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJalqvoEqyIclVSb6S5IShipIk\nabuJgyrJHsDfA78HPAY4KsljhipMkiToN6L6TeArVfXVqroNeD9w5DBlSZI00ieoHgZ8fd78Dd19\nkiQNJlU1WcPkecCGqnp5N/9i4Leq6tgFy80Bc93swcBVk5e7qAOAm5axfQs1rPT2LdSw0tu3UMNy\nt2+hhpXefqh13JtHVNXUoktV1UQ34BDgU/PmTwROnHR9Q9yAS5azfQs1rPT2LdSw0tu3UMNyt2+h\nhpXefqh1DHHrs+vvi8CjkxyU5L7AC4CP9lifJEk7WTdpw6q6I8mxwKeAPYBTq+qKwSqTJIkeQQVQ\nVR8HPj5QLUPYuMztW6hhpbdvoYaV3r6FGpa7fQs1rPT2Q62jt4kPppAkaXfwFEqSpKYZVECSmSRb\nl7uO7ZK8Ncnxy9T3cUm2JTljN/c7yN8gyeeWax0DPoZb+q5Dk0uyX5JXLncduotBpYVeCTyjql60\n3IVMoqqe3MI6NIyM7O73qf0YvQ7UiFUTVEn+I8mmJFd0/2Q8rnVJzuhGE2clWT9m/y9J8qUklyX5\n13E7T/KmJFcnuZDRP0aP2/7oJF9IsiXJP3XnYhx3He8GHgl8IsnrJmj/5u4kxRcmOXOCUeEeSd7T\n/Q3PTrLXBDX0Ho0MtI5HJrk0yRP7rmuMPme67Xfi5zDJnyfZ2t1eO0ENP9uOJ9wGtj+Oq5L8C7AV\nePgYbfdO8rHudbg1yR+N2z9wEvCo7rV08riNF46skxyf5K1LbPuGJMd10+9Mcl43fdhS93Ikedv8\nv12Styd5zRj1v6J77FuSXJvk00ttu8ss9z9yDXUD9u9+7sVo437gGG1ngAIO7eZPBY4fo/2vAFcD\nB8yvZYz2TwAuB9YDPw98Zcz+fxn4T2DPbv4fgJdM+Dxet/1xjNnuicAW4H7AvsA1Yz6GGeAO4De6\n+X8Hjp6gjlsG2JYmWkf3GLYy+qBxKfDry9D/xM/hvO1wb2Af4ArgcRO0n2g7XvA47gSeNEHbPwTe\nM2/+/pP+HXtsPzu0B44H3rrEtk8CPtBNXwB8AdgTeAvwp2P0v7mbvg/wP+O8H85bz55dDc+Z9LkY\n6rZqRlTAcUkuAz7P6BPYo8ds//Wq+mw3fTrwlDHaHsZo47oJoKpuHrPvpwIfrqpbq+oHjP+P04cz\nepP4YpIt3fwjx1xHX4cCH6mqH1fVDxkF57iuraot3fQmRi+4lWYK+Ajwoqq6bBn67/McPoXRdvij\nqroF+BCjbXOp+m7H832tqj4/QbvLgWck+eskT62q7/eoYTlsAp6Q5OeBnwAXAbOMntsLlrKCqroO\n+G6SxwHPBC6tqu9OUMu7gPOqapLX8qB6/R9VK5I8DXg6cEhV3ZrkM4w+2Y9j4XH6K+m4/QDvq6oT\nl7uQnn4yb/qnjEbHK833gesZvelfuQz9r4bnEOBHkzSqqquTPB54FvBXSc6tqrcNW9qi7mDHr1WW\n/F5UVbcnuRY4Bvgc8CXgd4FfBLaNUcMp3ToewmgP0ViSHAM8Ajh2kUV3i9Uyoro/8H9dSP0So+Hz\nuKaTHNJNvxC4cIy25wHPT/JAgCT7j9n3+cBzk+yVZF/gOWO2Pxd4XpIHbe8/ySPGXEdfnwWek+R+\nSfYBjtjN/bfiNuAPgJckeeFyFzOmCxhth+uT7M3ocSzpU3yn73bcW5KHArdW1enAycDjJ1jNDxnt\nvp7Ut4EHJXlgkp9j/NfCBYx2F57fTb+C0ahonA/PHwY2MNol/6lxOk/yhK7/o6vqznHa7iqrYkQF\nfBJ4RZJtjM7OPskug6uAVyU5ldEn4X9casOquiLJ24H/TvJTRt9PHDNG+81J/g24DLiR0XkUl6yq\nrkzyl8DZ3RFStwOvAr42znr6qKovJvkoo0+A32a0C2al7XbZrtdouqp+lOQI4Jwkt1TVijgHZrcd\nnsboexGAU6rq0jHbT7wdD+RXgZOT3MnodfBn466gqr6b5LPdARGfqKo3jNn+9iRvY/Q8fgP48pgl\nXAC8Cbio25Z+zHgfGKiq27qDIL5XVT8ds/9jgf2BTyeB0YlpXz7mOgblmSk0mCT7VNUt3RGT5wNz\nVbV5uesaRzcq3lxVu3tEuup0R7rdUlXvWO5a1pruA+tm4PlVdc1y19PXatn1pzZs7A7m2Ax8cAWG\n1EMZfXntG6tWrCSPYXTE5bmrIaTAEZUkqXGOqCRJTTOoJElNM6gkSU0zqCRJTTOoJElNM6gkSU37\nfxopjCYa66O0AAAAAElFTkSuQmCC\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f670da1d0f0>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
     }
    ],
    "source": [
-    "open('5a.plaintext', 'w').write('\\n'.join(tpack(segment(sanitise(ca.translate(tt))))))"
+    "k, _ = caesar_break(every_nth(scb, 15)[4])\n",
+    "fp = collections.Counter(caesar_decipher(every_nth(scb, 15)[4], k))\n",
+    "plot_frequency_histogram(fp)\n",
+    "unpos(k)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
+   "execution_count": 58,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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\n4W8LowEwAAAAAElFTkSuQmCC\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f6718d9ecf8>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
    "source": [
-    "bkeyt = sanitise('''\n",
-    "wwbbwwwbwwwbwwwbwwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb www bbw\n",
-    "wwbw wbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwbw bwbwbwbwbwbwbwbwbwwb www\n",
-    "bwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb bbwbbbwbbbwbbbwbbbwb wwwb wwwb wwwb\n",
-    "wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb www\n",
-    "www www www www www www www www www www www www www www www www www www www www www www www www wwbw\n",
-    "wwbw www www www www www www www www www www www www www www www www www www www www www www www www\n",
-    "www wwwb wwwb www wb wwwb bbw wwww bbb wwwb wwwb wwwb www bw www bbb wwbw wwbw bbb www bbbb\n",
-    "wwbbbwwwbbbwwbbbwb www bwwwwbwbwwbwwbwwwbww www bwbwwbbwwbwwbwbwwwwb www bbw bbw\n",
-    "bwwbwwbwwwwwbwwbwwwb www wb www bwwwbwwbwwwbwbwwwbwb www wwbwwwbwbwbwbwbwwwb www bwwwbwbwbwbwwbwwbww\n",
-    "www bwwwbwwbwwwwbwwbwwwb www bbb bbw bbbb wwbw wwww bbb bbw bwbwbwbbbbbwwwbwwwbw wwbw bbbb ww bbb\n",
-    "www bbbb wwwb www wb www bwwwbwwbwwwbwbwbwwwb www wwbwwwbwbwbwbwbwwwb wwwb wwwb www bwb www wwbw\n",
-    "wwww bwbwwwwbwwwwbwwbwwwb www bwwwbwbwwbwwwbwwwwb www bwbwwbbwbwwwbwwwb wwwb www bwb www wwbw www wb\n",
-    "wwbw wwbw www bwwwbwwwbwwbwwwbwb wwwb www bbb wbwwwbwbwwwbwbwwwbww bbb wwbw wwbw bww www bbbb wwbw\n",
-    "wwbwbbbwwbbbwbwwwbww www www www www www www www www www www www www www www www www www www www www\n",
-    "www www www www www wwbw wwbw www www www www www www www www www www www www www www www www www\n",
-    "www www www www www www www www wbwwwbwbwwwbwwwbwwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb\n",
-    "wwwb wwwb wwwb wwwb wwwb wwwb www bwb www bwbwbwbwbwbwbwbwbwb wbwbwbwbwbwbwbwbwbwb\n",
-    "wbwbwbwbwbwbwbwbwbwb wbwbwbwbwbwbwbwbwbwb www bwwbbbwbbbwbbbwbbbwb bbw bbb wbbbwbbbwbbbwbbbwb bbw\n",
-    "bbb wbbbwbbbwbbbwbbbwb bbwbbbwbbbwwbwwwbwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb wwwb\n",
-    "wwwb wwwb wwwb www bwwwbwwwbwwwbwwbww''')"
+    "fp = collections.Counter(vigenere_decipher(sanitise(cb), kbv))\n",
+    "plot_frequency_histogram(fp, sort_key=fp.get)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 59,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
     {
      "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbMAAAEmCAYAAADoRn53AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFjZJREFUeJzt3X+wZ3V93/HnK7uCgBHjsk4rP7xYSFqMjT+W1TRqEwhk\nLdFNJ0tdjQU6ZjY27tgmNe06Nki3OgMxE9uZ0NZNICGgBUNrsilriIU0EkWyCyKwILoCymImrkBI\nkEFYefePc1a/3Nzde773fu+9+9l9Pmbu7Pnx+dzz/p79fr+v+znnfM83VYUkSS37vqUuQJKk+TLM\nJEnNM8wkSc0zzCRJzTPMJEnNM8wkSc0zzCRJzTPMJEnNM8wkSc0zzCRJzVu+1AVMd9xxx9XU1NRS\nlyFJOgjceuut36yqlbO1O+jCbGpqih07dix1GZKkg0CSrw5p52FGSVLzDDNJUvMMM0lS8wwzSVLz\nDDNJUvMMM0lS8wwzSVLzDDNJUvMGhVmSNUnuTbIryaYZ1r8hyW1J9iZZN7L8FUluTrIzyR1J3jLJ\n4iVJggFhlmQZcCnwRuA04K1JTpvW7GvABcDHpi1/Ajivql4GrAH+S5IXzLdoSZJGDbmd1WpgV1Xd\nB5DkamAtcPe+BlX1QL/umdGOVfWlkemvJ/kGsBL463lXLkladFObrhvc9oGLz1nASp5tyGHG44EH\nR+Z398vGkmQ1cATwlXH7SpJ0IItyAUiSvw9cCfyrqnpmhvUbkuxIsmPPnj2LUZIk6RAyJMweAk4c\nmT+hXzZIkucD1wHvq6rPzdSmqrZU1aqqWrVy5ax3+pck6VmGhNl24NQkJyc5AlgPbB3yy/v2nwB+\nr6qunXuZkiTt36xhVlV7gY3A9cA9wMerameSzUneDJDk9CS7gXOBjyTZ2Xf/F8AbgAuS3N7/vGJB\nHokk6bA16Ms5q2obsG3asgtHprfTHX6c3u8q4Kp51ihJ0gF5BxBJUvMMM0lS8wwzSVLzDDNJUvMM\nM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJ\nUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLz\nDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8waFWZI1Se5NsivJphnWvyHJbUn2Jlk3bd35Sb7c/5w/\nqcIlSdpn1jBLsgy4FHgjcBrw1iSnTWv2NeAC4GPT+r4QeD/wGmA18P4kPzD/siVJ+p4hI7PVwK6q\nuq+qngKuBtaONqiqB6rqDuCZaX1/CvhUVT1SVY8CnwLWTKBuSZK+a0iYHQ88ODK/u182xHz6SpI0\nyEFxAUiSDUl2JNmxZ8+epS5HktSYIWH2EHDiyPwJ/bIhBvWtqi1VtaqqVq1cuXLgr5YkqTMkzLYD\npyY5OckRwHpg68Dffz1wdpIf6C/8OLtfJknSxMwaZlW1F9hIF0L3AB+vqp1JNid5M0CS05PsBs4F\nPpJkZ9/3EeA/0wXidmBzv0ySpIlZPqRRVW0Dtk1bduHI9Ha6Q4gz9b0cuHweNUqSdEAHxQUgkiTN\nh2EmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5h\nJklqnmEmSWqeYSZJap5hJklq3qAv55QkHVqmNl03uO0DF5+zgJVMhiMzSVLzDDNJUvMMM0lS8wwz\nSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS\n8waFWZI1Se5NsivJphnWH5nkmn79LUmm+uXPSXJFkjuT3JPkvZMtX5KkAWGWZBlwKfBG4DTgrUlO\nm9bsHcCjVXUK8GHgkn75ucCRVfVy4NXAL+wLOkmSJmXIyGw1sKuq7quqp4CrgbXT2qwFruinrwXO\nTBKggGOSLAeOAp4C/mYilUuS1Fs+oM3xwIMj87uB1+yvTVXtTfIYsIIu2NYCfwkcDfxSVT0y36Il\nSZ2pTdcNbvvAxecsYCVLa6EvAFkNfAd4MXAy8O+SvHR6oyQbkuxIsmPPnj0LXJIk6VAzJMweAk4c\nmT+hXzZjm/6Q4rHAw8DbgD+uqqer6hvAZ4BV0zdQVVuqalVVrVq5cuX4j0KSdFgbEmbbgVOTnJzk\nCGA9sHVam63A+f30OuDGqirga8AZAEmOAV4LfHEShUuStM+s58z6c2AbgeuBZcDlVbUzyWZgR1Vt\nBS4DrkyyC3iELvCguwryd5LsBAL8TlXdsRAPRJJaN/T816F87muuhlwAQlVtA7ZNW3bhyPSTdJfh\nT+/3+EzLJUmaJO8AIklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5h\nJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJ\nat7ypS5Akg5WU5uuG9z2gYvPmXc/zZ1hJumQZ7gc+jzMKElqnmEmSWqeYSZJap7nzCQ1xfNfmokj\nM0lS8wwzSVLzDDNJUvMMM0lS8waFWZI1Se5NsivJphnWH5nkmn79LUmmRtb94yQ3J9mZ5M4kz51c\n+ZIkDQizJMuAS4E3AqcBb01y2rRm7wAerapTgA8Dl/R9lwNXAe+sqpcBPw48PbHqJUli2MhsNbCr\nqu6rqqeAq4G109qsBa7op68FzkwS4Gzgjqr6AkBVPVxV35lM6ZIkdYaE2fHAgyPzu/tlM7apqr3A\nY8AK4AeBSnJ9ktuS/Pv5lyxJ0rMt9IemlwOvA04HngBuSHJrVd0w2ijJBmADwEknnbTAJUmSDjVD\nwuwh4MSR+RP6ZTO12d2fJzsWeJhuFPfpqvomQJJtwKuAZ4VZVW0BtgCsWrWqxn8YklrjnTw0SUMO\nM24HTk1ycpIjgPXA1mlttgLn99PrgBurqoDrgZcnOboPuX8K3D2Z0iVJ6sw6MquqvUk20gXTMuDy\nqtqZZDOwo6q2ApcBVybZBTxCF3hU1aNJfoMuEAvYVlXD/xyTJGmAQefMqmobsG3asgtHpp8Ezt1P\n36voLs+XJGlBeAcQSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwz\nSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS\n8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzDDNJUvMMM0lS8wwzSVLzli91AZLa\nNrXpusFtH7j4nAWsRIezQSOzJGuS3JtkV5JNM6w/Msk1/fpbkkxNW39SkseTvGcyZUuS9D2zjsyS\nLAMuBc4CdgPbk2ytqrtHmr0DeLSqTkmyHrgEeMvI+t8APjm5siUtBEdZatWQkdlqYFdV3VdVTwFX\nA2untVkLXNFPXwucmSQASX4GuB/YOZmSJUl6tiFhdjzw4Mj87n7ZjG2qai/wGLAiyfOA/wD8p/mX\nKknSzBb6asaLgA9X1eMHapRkQ5IdSXbs2bNngUuSJB1qhlzN+BBw4sj8Cf2ymdrsTrIcOBZ4GHgN\nsC7JrwEvAJ5J8mRV/eZo56raAmwBWLVqVc3lgUiSDl9Dwmw7cGqSk+lCaz3wtmlttgLnAzcD64Ab\nq6qA1+9rkOQi4PHpQSZJ0nzNGmZVtTfJRuB6YBlweVXtTLIZ2FFVW4HLgCuT7AIeoQs8SZIWxaAP\nTVfVNmDbtGUXjkw/CZw7y++4aA71SZI0K29nJUlqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5h\nJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJap5hJklqnmEmSWqeYSZJat6g7zOT1JapTdcNbvvA\nxecsYCXS4nBkJklqnmEmSWqeYSZJap5hJklqnmEmSWqeVzNKBzGvSpSGcWQmSWqeYSZJap5hJklq\nnmEmSWqeYSZJap5XM0qLZOiViV6VKI3PkZkkqXmGmSSpeR5mlMbkB5mlg49hpsOWoSQdOgYdZkyy\nJsm9SXYl2TTD+iOTXNOvvyXJVL/8rCS3Jrmz//eMyZYvSdKAkVmSZcClwFnAbmB7kq1VdfdIs3cA\nj1bVKUnWA5cAbwG+Cbypqr6e5IeB64HjJ/0gdHhzhCVpyMhsNbCrqu6rqqeAq4G109qsBa7op68F\nzkySqvp8VX29X74TOCrJkZMoXJKkfYaE2fHAgyPzu/m7o6vvtqmqvcBjwIppbX4WuK2qvj23UiVJ\nmtmiXACS5GV0hx7P3s/6DcAGgJNOOmkxSpIkHUKGjMweAk4cmT+hXzZjmyTLgWOBh/v5E4BPAOdV\n1Vdm2kBVbamqVVW1auXKleM9AknSYW/IyGw7cGqSk+lCaz3wtmlttgLnAzcD64Abq6qSvAC4DthU\nVZ+ZXNk6VHkxh6S5mHVk1p8D20h3JeI9wMerameSzUne3De7DFiRZBfwy8C+y/c3AqcAFya5vf95\n0cQfhSTpsDbonFlVbQO2TVt24cj0k8C5M/T7APCBedYoSdIBeW9GSVLzDDNJUvMMM0lS87zRsBaE\nVyVKWkyOzCRJzTPMJEnN8zCjDsjDhZJa4MhMktQ8w0yS1DzDTJLUPMNMktQ8w0yS1DzDTJLUPMNM\nktQ8w0yS1Dw/NH0Y8QPQkg5VjswkSc0zzCRJzfMwY4M8XChJz+bITJLUPMNMktQ8w0yS1DzDTJLU\nPMNMktQ8w0yS1DzDTJLUPMNMktQ8w0yS1DzDTJLUPMNMktQ8w0yS1DzDTJLUvEFhlmRNknuT7Eqy\n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\n3v8HziFIbeqthucAAAAASUVORK5CYII=\n",
       "text/plain": [
-       "1577"
+       "<matplotlib.figure.Figure at 0x7f66f2adb630>"
       ]
      },
-     "execution_count": 20,
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "plot_frequency_histogram({k: 10**Pl[k] for k in Pl}, sort_key=Pl.get)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 60,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(('taxied', <KeywordWrapAlphabet.from_last: 2>), -3188.639246703687)"
+      ]
+     },
+     "execution_count": 60,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "len(bkeyt)"
+    "vb = vigenere_decipher(sanitise(cb), kbv)\n",
+    "keyword_break_mp(vb)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 29,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "1577"
+       "'imtvpbyfqlhrjlkwksfuwdnlikfrsiwrrzcbtneaepqcjemamfcrclisqhljeguubiojujbujcvnlrmnzgjepaaxbvvkmztnxpayqtasjvfldfuiuatarskvekhyugrmovhccsvfcoyjbgwapiowmipktypnjqqvherqfpktyuspmwhxlztkndeztgxmotayustaehjvzdcyqeernjwuefktylevsuqcrmloyqsbgpvaamstlcljvwsehvkrldiqifzcbefnqwbxnjczmygniprwrarqflvhyfqsfpiweuzkfdbywcxuraslzgiekndpslmovrujaekswwemeugrwlsttxllozogwmrdnrkcxkmbknyaucwbxnjjqyfxwggrbehokqczyoboimovhccsvfcnbbnieowktasqjlaajsdhajxushvjvatqbslhtfnvfzmztvztpwsjdnwkqgzcycbfjntzrlljelhfkehhraxakkvjluantggttiywoigkhyoyiewhiowmjvdtytldhaoamwgysloyzehlhoawhakjbamecejijdgqpiidnuzldmladdwwrnktwmsshuqnrzthuknzbyiiovaaasgjetynaiewhiowsnkkhaptxieuyfstundeuczyeatiotqfjwhfzpxanqylkdkfoaxnagkrwrbhpjbkezfsgdqrdnggllumueyfjnfhqxqfjcaxxcxgnvuajcamgluzyxiookowoigulzybtgliequzxvzpmndlqajbcqgjfxaotidhauwshpickrmuyzlwebfzqfgknnbeimlrdnakrgkrmuzskyyfukrhjvaublbiovaansvyulzvsomravalmglcaxvtipwahmatfvdcywwyfetfqutdgulouzbjnwriusffsqanuijhwriqxenemybyzwagwuksimloynbfgljnllhjmmtikzayqhiobmfuosxfurirqdekgjjeatikdhasdmwmdwkrtpdlfyjiovaelgrtibivhvklnszqtsaetxvliiowsnkkhaptafcbeerlypmtfblefncrlxtnlmexyxxnecdemaeldcheyjfyqbrubfmmyuxdaaqaonvmkhkeywoxbajrllkqmgabpsvnedhowoigvoxpoiepwiossuacumqyzlbjeibpjkkrnzvjmodeqwlyvmrxnazlrphmxnjwktaossshortkqhxdgjvzdirqweuzkhkezcwdmovflsmysloyosblvsenlswldqyutgdyqiuhmgwztytiznnqylkdimloynbfguieqwaklctaowdfmtiaraelrudfubjfyhbqgjmgarbcivmqwbzqanutvzkijhontasufunjxtznsqwbzqvcsnxpnicuionkpjpkeuezgvmaogbbfqdahedyhliwhvarghaxpbiosjhnspacgroqbbqfoohzkfmoymeijcaiirjlcwkrzzehlhoamqvlmmrmfsylgeaacqmwzcxnwjvtrheqgkhkhmszsxmoknvfzuktltdfwuchtqvjfrtvzcxgnontasuffaetmaaqcwhhvafshwzwblhtthbeyddoxvwewatxfcqleloyynjcaonnheejiluvgpmufqlhlyvztozmxbajioweyekvhzixwacyacqfgmeptidhahhrlaelufakeguwvbylskhdtltdfnqaplbfenofakyidqbhtaqknutyxcjxaisaggypdgxyypwapbsdmrxwauftdhrciowavjmtapmgditsysnigloyosblvtrmbmnjenfnoznnqosckvmkhueldhaiwhxnghmqyfuiqrjlrltivetvzeylqlhnvgjauqfsbeutokrosnavoajyzlgoxayeidwrnktjgrihmheimkmotegvrixowvrglwyvyxksvxwwxywkoyowseaqihqzkhknyodtnthwbxnjnosypzgdgwgowgfmgantaiopwfqfsvlvlqznieljqlhzyacbxhzeurixansvuzeymspyeozpbphkdfzcbhwudhrjlffllzcbyldvrtariwlldfuimhehnxkvuzbxqnjclaeujoenvozcbojtvwbxnjvmezccixuorrjlysloyosblvwinwpqimqweldncvlalswldqyudsmuaiowflmhuwxgixytamwlouloyblanaiiwvcadzefblufmphnskqidh'"
       ]
      },
-     "execution_count": 21,
+     "execution_count": 29,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "19 * 83"
+    "keyword_decipher(vb, 'taxied', KeywordWrapAlphabet.from_last)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 30,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "['  **   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   **  ',\n",
-       " ' *  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  * ',\n",
-       " '  * *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *  ',\n",
-       " ' *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   * ',\n",
-       " '  *                                                                             *  ',\n",
-       " ' *                                                                               * ',\n",
-       " '  *    *   ***     ***   *   *   *   *    ***  *   * ***   ****  ***   ***  *** *  ',\n",
-       " ' *    * *  *  *   *     * *  **  *  * *    *   ** ** *  *  *     *  *   *    *   * ',\n",
-       " '  *  *   * *   * *     *   * * * * *   *   *   * * * *  *  *     *   *  *    *  *  ',\n",
-       " ' *   ***** ****  *     ***** * * * *****   *   *   * ****  ***   ****   *    *   * ',\n",
-       " '  *  *   * * *   *     *   * * * * *   *   *   *   * *     *     * *    *    *  *  ',\n",
-       " ' *   *   * *  *   *    *   * *  ** *   *   *   *   * *     *     *  *   *    *   * ',\n",
-       " '  *  *   * *   *   *** *   * *   * *   *  ***  *   * *     ****  *   * ***  *** *  ',\n",
-       " ' *                                                                               * ',\n",
-       " '  *                                                                             *  ',\n",
-       " ' * *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   * * ',\n",
-       " '  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *  ',\n",
-       " ' *  *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***  * ',\n",
-       " '  *  *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *   *  *  ']"
+       "'ufkmgaqrzxtbvxwowirloedxuwrbiuobbcnakdhjhgznvhfjfrnbnxuiztxvhsllauyvlvalvnmdxbfdcsvhgjjpammwfckdpgjqzkjivmrxerluljkjbiwmhwtqlsbfymtnnimrnyqvasojguyofugwkqgdvzzmthbzrgwkqligfotpxckwdehckspfykjqlikjhtvmcenqzhhbdvolhrwkqxhmilznbfxyqziasgmjjfikxnxvmoihtmwbxeuzurcnahrdzoapdvncfqsdugbobjbzrxmtqrzirguohlcwreaqonplbjixcsuhwdegixfymblvjhwioohfhlsboxikkpxxycysofbedbwnpwfawdqjlnoapdvvzqrpossbahtywzncqyayufymtnnimrndaaduhyowkjizvxjjvietjvplitmvmjkzaixtkrdmrcfckmckgoivedowzscnqnarvdkcbxxvhxtrwhttbjpjwwmvxljdksskkuqoyuswtqyquhotuyofvmekqkxetjyjfosqixyqchtxtyjotjwvajfhnhvuveszguuedlcxefxjeeoobdwkofiitlzdbcktlwdcaquuymjjjisvhkqdjuhotuyoidwwtjgkpuhlqrikldehlncqhjkuykzrvotrcgpjdzqxwewryjpdjswbobatgvawhcrisezbedssxxlflhqrvdrtzpzrvnjppnpsdmljvnjfsxlcqpuyywyoyuslxcqaksxuhzlcpmcgfdexzjvanzsvrpjykuetjloitgunwbflqcxoharczrswddahufxbedjwbswbflciwqqrlwbtvmjlaxauymjjdimqlxcmiyfbjmjxfsxnjpmkugojtfjkrmenqooqrhkrzlkeslxylcavdobulirrizjdluvtobuzphdhfqaqcojsolwiufxyqdarsxvdxxtvffkuwcjqztuyafrlyiprlbubzehwsvvhjkuwetjiefofeowbkgexrqvuymjhxsbkuaumtmwxdiczkijhkpmxuuyoidwwtjgkjrnahhbxqgfkraxhrdnbxpkdxfhpqppdhnehfjhxenthqvrqzablarffqlpejjzjydmfwtwhqoypajvbxxwzfsjagimdhetyoyusmypgyuhgouyiiljnlfzqcxavhuagvwwbdcmvfyehzoxqmfbpdjcxbgtfpdvowkjyiiitybkwztpesvmceubzohlcwtwhcnoefymrxifqixyqyiaxmihdxioxezqlkseqzultfsockqkucddzqxweufxyqdarsluhzojwxnkjyoerfkujbjhxblerlavrqtazsvfsjbanumfzoaczjdlkmcwuvtydkjilrldvpkcdizoaczmnidpgdunluydwgvgwhlhcsmfjysaarzejtheqtxuotmjbstjpgauyivtdigjnsbyzaazryytcwrfyqfhuvnjuubvxnowbcchtxtyjfzmxffbfriqxshjjnzfocnpdovmkbthzswtwtficipfywdmrclwkxkerolntkzmvrbkmcnpsdydkjilrrjhkfjjznottmjritocoaxtkktahqeeypmohojkprnzxhxyqqdvnjyddthhvuxlmsgflrzxtxqmckycfpajvuyohqhwmtcupojnqjnzrsfhgkuetjttbxjhxlrjwhslomaqxiwtekxkerdzjgxarhdyrjwquezatkjzwdlkqpnvpjuijssqgespqqgojgaiefbpojlrketbnuyojmvfkjgfseukiqidusxyqyiaxmkbfafdvhdrdycddzyinwmfwtlhxetjuotpdstfzqrluzbvxbxkumhkmchqxzxtdmsvjlzriahlkywbyidjmyjvqcxsypjqhueobdwkvsbutfthufwfykhsmbupyombsxoqmqpwimpoopqowyqyoihjzutzcwtwdqyekdktoapdvdyiqgcsesosyosrfsjdkjuygorzrimxmxzcduhxvzxtcqjnaptchlbupjdimlchqfigqhycgagtwercnatoletbvxrrxxcnaqxembkjbuoxxerlufthtdpwmlcapzdvnxjhlvyhdmycnayvkmoapdvmfhcnnuplybbvxqixyqyiaxmoudogzufzohxednmxjxioxezqleifljuyorxftlopsupqkjfoxylxyqaxjdjuuomnjechraxlrfgtdiwzuet'"
       ]
      },
-     "execution_count": 22,
+     "execution_count": 30,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "tt = ''.maketrans({'w': ' ', 'b': '*'})\n",
-    "chunks(bkeyt.translate(tt), 83)"
+    "keyword_decipher(vb, 'arcanaimperii', KeywordWrapAlphabet.from_largest)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
+   "execution_count": 124,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'kccgi'"
+      ]
+     },
+     "execution_count": 124,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
-    "scb = sanitise(cb)"
+    "cat(unpos(caesar_break(section)[0]) for section in every_nth(scb, 5))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 128,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "('fwruffnquevmp', -1750.4576000271347)"
+       "'oiszjgfsxvgpethfgqgpemcsrkbmaefnpfrgycldenlfglirpxdvmsrsobtglbtyunsyctateftuhpphijylztruitdgkfotdealqsoagdzjlxblkaetpnstlgeeplvbvggvsatktmedgjnazhmtuewgsejtnfxggcmyawgsepytbfqzjxchuecfoldbvetzqaraaemqimmiaecmvgfrcgeafalgstlfothmekyeuwgtrharstjmqewtngkpgqexdbfrgisuayyuvgeykeztleyirrmyasseexwwswrycqkhkeyesddkydsjxnelglljypbvgrtebbrowbysikmbyjncrghjrwujntbilmsuggkdetfichyyuvgqmzgtejuykeejsneyzruulbvggvsatktldutltviksoanqhrwdymvatztnotqsrxkgwanedlrlztyszwatnztiltsnmyverghyuecpgtglhegekkvydzrfstqhtwhajubehztwemgeeihltfqhmtugdeseormvaytktnyzhmewkkanytwbbhqwrpydiyotidlxeoelywrmbsdigtgougsbgywvcanpxcdcglfuhlwvgtroacqasehzltfqhmtakrgewjadwlfbbncsuecyriftaehmpyaquegwvdiuabjfqhkkrchzjzyirybxghgcfxyjxxbilanisrkyyhhyungouyaqtrctdduugvrefqtbjywhdwvykmtwemrjfvgyusreoqkwdynphopfatavlngkvrronmvafyqbxeegppphgafoabxyamglquklbsbilosomgpppiwzildtfzdqsryurewvgtriatirjfqysbydwrgucstrcqalefdgkocadevesefsledoqcfmrjrpieyuirfqaakoowhblynirflhbuakeuhgnapytfaethmehghustnjgogtiskeixqxqhmvuackqcxbvwyaicfngqarxbqmvaciktuffgpxjopsithmrbbsbpxbgllngkjiazxqqwyadlsrhmtakrgewjaxsekecmtywisgurisuhrjucksiccvfdclhichbbsevjyhnsiaapqiatizytoxixdolruhngcesudpatrjgsntbrdjyaclsgmtwemsmcjultwihmnasattpkhgahtefvxgrgpqwcnbvseottydipchzgayzgkuvgfgswiywhnyrsfydgedmqimwyaycqkhngcfrembvgdjnuyzhmeiyeadcelgavseoepajxiahtbucfyseongcuabjfqethmehghucreotbhstswiemstehrmbbsntlxbeyklgylngtbruudlltayyxyqurszwqlynynsoaskrlmtagczayyxyteolcjtlmcrolfxgwgcyyijltdodviaxerjyofvsryerbomcrcjgldztglnxqebprkgefkyoexsatkzpynnmarhpetufgpfwkkanytkleitippxyfamotrsyjfyvchenlbbgclnhngepmiwotyklrlzcgsooohnchgslegknszwdduuynsoaskzrhosxixhyebeqkoebweeaneuevmypemcqeinaezbsyilhmevtnmaynlbmbqdjyqltbcnqjbtydysrwsdpathmtmylgujwndnahbrsyamicsonmvaqgpgbbsrbwekjkfgazgahnesooohcxdpjvlbukbwehlxxkgsoyhursetdnoarsranywedcvhtnazaqduoguryxamvyhhmtbtqiswjsjxoesznvemhmeiyeaderkvukqalghugcuaoqssttgeyyrmvaryeuvcnioexblfytlpgcedaszwkfaxvglrngarogmgikbykpjakasmwdhgamyzrwmepupqeanuyrgkbmetgkrokjlyrzmteomhweqhdzzgzwthyfgmeiewtaahelkhngleioycbqyyuvgukqejijxmifmtnatbrqozldwidoyatssjtwtltstqjbkyatycaiikyrzriatcycegytqlycnvxdrebfrgkncsgpetakhjfrgfapgrsozefhjlxblbnoglustcyycktnmsdetewbusmfrgsybgyyuvgdicfrdlocyrpetyzhmeiyeadihltxnoiobyrmceglrgavseoepowbcdhmtlitctbtlloietkttlchmeurxcarhwrfqpycgurzstzglnsnoee'"
       ]
      },
-     "execution_count": 27,
+     "execution_count": 128,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "kb, score = vigenere_frequency_break(cb)\n",
-    "kb, score"
+    "vb5 = vigenere_decipher(scb, 'kccgi')\n",
+    "vb5"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 28,
+   "execution_count": 125,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'nieyqmhcenwlqvchdporosweiohtsshreoihpsvrvusdcostmjezkdeytdhrtasupknropbklngeutgnssthjhhnowgbdwvucncdvofhbdltfpvobiuicirayodpwkpoutibtgcenuhpwachchnbrjydhsfvhqszeuvdcpswatvzmxhsiigkobvcagqcdikfstrvkfggbdkvcvstuvufienwiniasbcecmvdwemkwgtnsyjridowjamhuhnrvxssgewikqxpxhashvwvteulpavioctweavlhtikkkximoikdloikrwswfiojrynulrsgtoktknqcporlruoigivdpeddhrntdmrnucnrioiuetpdnftaipjrewjqtercxzvydhiswrtrneonknnfsyrifcdhedoweptjrechehcptdcehirohbcpniloorntrrrtohgeoandszehilxywfqkrgnphglvcojfbetcietpqmfetkalnahiwixdppersmrihrctseahkhtifbokasoozrjgvvkehjsufarunbrtiswzdmriwcrovhdsdeihdteiiustmjupvkhdiisibjloyrdpyxkusdlwfpsehvevdoiudppehzgvcewnhifrvkfggbdkbidptartnotloihpseehrdipeotmlwbcousicucctsktsrlritcanhpdmrehuinioiuuwirsxtanvjshfwyrkacfihfctdipytegvprdowhfldhycrqhfctswdbnagevitctsufsrofoccprycjgnifeikrthnowgcedfedjwiisdtihszeecfvlwjqgehoeicssaqflthagmncpvvifnreneoiioiulytddhuhkrtzsdpevphodehkctsvfhltophksiepsgcohnrnuseajettlhdwhiepjwcenbtbuecihpijncohouidiqjikpovimvsrfridohvchdporhrmhlpnikpacvjiswwgszeyxrcpragclkvxbporlruoigoviferifridicrskiporsyypwgprszenephnicczvttucvqesuiivqleesvfrhcfgchuswrocjslotcnxtiiswkoieatruninitradpaortylcouoahdpehgukcvlrmrafrntaovetrxvyinpenvniquglltisxgy'"
+       "'iya'"
       ]
      },
-     "execution_count": 28,
+     "execution_count": 125,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "vigenere_decipher(sanitise(cb), kb)"
+    "cat(unpos(caesar_break(section)[0]) for section in every_nth(scb, 3))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 29,
+   "execution_count": 127,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "('arcanaimperii', -1506.8637359274674)"
+       "'qmuxtqzwdvsrybphksezoggyrwdgimhrrdbqsgrdqpfnonmtnhnpqyreqvbonfvwexmcitmvynbwlrnrsdcrzftoqbfkmdydxiglcuiiofdljhlfogefrhabnkgczvpfbgsxmibmxocnqdrgztoncmykuctdhjdgseggiykuczinflqllrkpwiedyvxfbefbkizcegkasgqoaqegdohveeokzergevfnwvlocuiyycgftbizuxlkaoqxtgwraymzhddbqcwaakaodogcmcjdfieidtggiuwgchgqwcrkekspmiaccnxoedelrvmnknjtijfbgdvyjjtsyziccosbklhkzillpgedrzbungacikmbodzmihkaodosqbedodyekqgdavgcbpeeffbgsxmibmxnbedfxbiwuiivsltunigzgtlvhwbswtvuqqetepnlthvcuxgknrftunnavocxcbqbcaeorabonlgeouezedltzabslvurkdyhetbnemokgcsrfxlqtoncofiucybgzgyfmnvgblocgueetyfyvjpsatninccutufffmqinwgbgfyduinowwkuzqiqziazrrkleknderfabgftiikseucrjfxlqtonistkgutkxarfndhkawiewbszxgetojgisygegfxmaanlzypmotarjddeidavfojkedhidbdbunuvquvmwirbcansqogisxtadnxyaghtynyvflwgrxabywonemovldfqsyyrqqksefcpnryjjgtmxfvomztpyxgzgfksvfmgkrnzraelomdrgioknoeuffybuniawokrnzsqdolpvzhlswtwebyabgftcibkvldaimfeditackuxtaakfildsmikifixccozwrepqkknovlpzsycaidhkiimsqurlfctidhfpjwemcerargpkvzimvlocrqbyytzlawovmuiosrudqtopcieosahlpaeauezvosetvlagzgcumncnhkrvtyjwottoljjufrvlqfptgwlcihzusuikxpyrtonistkgutkrwkkqegbgymueebcwahdloksumeafpxgrhuebjjuixhirhwoamrkqivmbwdyrmddanlcppkeccextgtdlaavvftbtiugrssonemowoatefxcitohiacxvnuraentqhpfotkrogmhfbsqqnbgfmrarjaeezsmodohkuusiqltyduzgliifkasgaeakeksppkedbogfbgplhcgblocsiyejcqnaiduiqczkdboatvvckhcucyxagaanlzymvlocrqbyirqqnjpuxuusogwzettgjjurvjhlycqlsafvovftsenfpzakargywvuxgafctyzuiiamvnkdkagfakargbgsnatdfqiranzfoykewisdpzdafpqizithiyzzyrkgljwogtatqfhftsnhfygfrpuqyjqyagraivobnixhqgrtrybchkrdgueetyfmfmqvmrnhizesoftmgrhcxarohphbsefvppkgnwsqszywnlthekumyybrihsufmomruxgnxyayzuiiamdtfycrmdhkgvmymsgzgoyeteggpugrioaaocrgeldmgqnlocfdhqgyznvujshlwavnfinclvbgfcupgcxtgttonugnkwhgxxrghntmgiomeqyxgzgqsrajjuvduoudolgmbaippiumyybgddblptjwoduorfbdksuigpwvucdnhsgretuvgyifafrnrgzmsxcwiytwhkgzehtonjbsmuutcdbueebhdmolocsiyejedmpcssenereagaaasmabvkgwibgzgrkgodkpmqchlfjetxrakmfeuxguzedvsnlvocvqewqcohywrdiscwounraesyltqumryrookhyersmvumvkmpyudperlonmwolycarxdfglynpghkocsoqxgatgfsppkncsysghqkaodowosctsdbsironvivftoyjfhcipqsibuwlrgdfxytclvsgcxaakscoerltcibececqinuryoppfltiddbqerissrybimlldbqzevgduihmhlljhlfftosnoabecaaudhqydqvyejwwodbqmchgkaodofmedbnfsiydrybgblocsiyejitnnfvqmqzibggkgxtaiduiqczyqfidtontqvgvzdvfsoefmnbtelocebrggrtylnyrceeebtwzzsnhavqig'"
       ]
      },
-     "execution_count": 29,
+     "execution_count": 127,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "kb, score = beaufort_frequency_break(cb)\n",
-    "kb, score"
+    "vb3 = vigenere_decipher(scb, 'iya')\n",
+    "vb3"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 30,
+   "execution_count": 118,
    "metadata": {},
    "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
     {
      "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAbAAAAEmCAYAAAADccV0AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAFVtJREFUeJzt3XuwZWV95vHvI3hDExH6iEjTNkY0QRMGPDA4xCkFzWDE\nNFMhDkYFDVaPEYOJMQbipLCsWIXRGsfUTJy0woATBkSiQoJGmQYFL4DdXBsQ6eEi3QV0K0IEKlx/\n88deVG26G/ad7rfP91N16qy19vvu97fP2ec8+11r7bVTVUiS1JpnbO0CJEkahwEmSWqSASZJapIB\nJklqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklq0o6DGiQ5FTgc2FBVr+7b/kfAccCjwPlV\n9ZFu+4nAsd3246vqm4PGWLRoUS1dunSsByBJ2r6sXr36p1U1N6jdwAADTgP+O/DFxzckeQOwDNi3\nqh5M8qJu+z7AUcCrgJcA/zfJK6rq0acaYOnSpaxatWqIUiRJ27sktw3TbuAuxKq6GLh7k81/CJxc\nVQ92bTZ025cBZ1XVg1V1C7AWOHDoqiVJGtK4x8BeAbwuyWVJvpPkgG77HsDtfe3WddskSZqqYXYh\nPlm/XYCDgAOAs5O8bJQ7SLIcWA6wZMmSMcuQJC1U487A1gFfqZ7LgceARcB6YM++dou7bZupqhVV\nNV9V83NzA4/VSZL0BOMG2NeANwAkeQXwLOCnwHnAUUmenWQvYG/g8mkUKklSv2FOoz8TeD2wKMk6\n4CTgVODUJGuAh4BjqvfRztclORu4HngEOG7QGYiSJI0jvdzZuubn58vT6CVJAElWV9X8oHZeiUOS\n1CQDTJLUJANMktSkcd8HJklaAJaecP7QbW89+S0zrGRzzsAkSU0ywCRJTTLAJElNMsAkSU0ywCRJ\nTTLAJElNMsAkSU0ywCRJTTLAJElNMsAkSU0ywCRJTTLAJElNMsAkSU0ywCRJTTLAJElNMsAkSU0y\nwCRJTTLAJElNMsAkSU0aGGBJTk2yIcmaLdz2p0kqyaJuPUn+JsnaJNck2X8WRUuSNMwM7DTgsE03\nJtkT+C3gJ32b3wzs3X0tBz43eYmSJG1uYIBV1cXA3Vu46TPAR4Dq27YM+GL1XArsnGT3qVQqSVKf\nsY6BJVkGrK+qqze5aQ/g9r71dd02SZKmasdROyTZCfgLersPx5ZkOb3djCxZsmSSu5IkDWHpCecP\n3fbWk98yw0qmY5wZ2K8AewFXJ7kVWAxckeTFwHpgz762i7ttm6mqFVU1X1Xzc3NzY5QhSVrIRg6w\nqrq2ql5UVUuraim93YT7V9WdwHnA0d3ZiAcB91bVHdMtWZKk4U6jPxP4AfDKJOuSHPsUzb8O3Ays\nBT4PvH8qVUqStImBx8Cq6u0Dbl/at1zAcZOXJUnSUxv5JA5J0ta1vZ2MMS4DTJK2EoNoMl4LUZLU\nJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQD\nTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1CQDTJLUJANMktQkA0yS1KSBAZbk1CQbkqzp2/ap\nJD9Kck2SrybZue+2E5OsTXJjkv8wq8IlSQvbMDOw04DDNtl2AfDqqvoN4MfAiQBJ9gGOAl7V9fnb\nJDtMrVpJkjoDA6yqLgbu3mTbt6rqkW71UmBxt7wMOKuqHqyqW4C1wIFTrFeSJGA6x8D+APhGt7wH\ncHvfbeu6bZIkTdVEAZbko8AjwBlj9F2eZFWSVRs3bpykDEnSArTjuB2TvBs4HDi0qqrbvB7Ys6/Z\n4m7bZqpqBbACYH5+vrbURpJasfSE84due+vJb5lhJQvHWDOwJIcBHwF+p6oe6LvpPOCoJM9Oshew\nN3D55GVKkvREA2dgSc4EXg8sSrIOOIneWYfPBi5IAnBpVb2vqq5LcjZwPb1di8dV1aOzKl6StHAN\nDLCqevsWNp/yFO0/AXxikqIkSRrEK3FIkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppk\ngEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmjT2JzJL0vbIT1ZuhwEmabtkEG3/3IUo\nSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWrSwABLcmqSDUnW9G3bJckFSW7qvr+w254k\nf5NkbZJrkuw/y+IlSQvXMDOw04DDNtl2ArCyqvYGVnbrAG8G9u6+lgOfm06ZkiQ90cAAq6qLgbs3\n2bwMOL1bPh04om/7F6vnUmDnJLtPq1hJkh437jGw3arqjm75TmC3bnkP4Pa+duu6bZIkTdXEJ3FU\nVQE1ar8ky5OsSrJq48aNk5YhSVpgxg2wux7fNdh939BtXw/s2dducbdtM1W1oqrmq2p+bm5uzDIk\nSQvVuAF2HnBMt3wMcG7f9qO7sxEPAu7t29UoSdLUDPw4lSRnAq8HFiVZB5wEnAycneRY4DbgbV3z\nrwO/DawFHgDeM4OaJUkaHGBV9fYnuenQLbQt4LhJi5IkaRCvxCFJapKfyCxpm+YnK+vJOAOTJDXJ\nAJMkNckAkyQ1yQCTJDXJAJMkNckAkyQ1yQCTJDXJ94FJetr4ni5NkzMwSVKTDDBJUpMMMElSkwww\nSVKTDDBJUpMMMElSkwwwSVKTDDBJUpMMMElSkwwwSVKTvJSUpJF5SShtC5yBSZKaNNEMLMmfAO8F\nCrgWeA+wO3AWsCuwGnhXVT00YZ2SZsCZlFo29gwsyR7A8cB8Vb0a2AE4Cvgk8Jmqejnwc+DYaRQq\nSVK/SXch7gg8N8mOwE7AHcAhwDnd7acDR0w4hiRJmxk7wKpqPfBp4Cf0guteersM76mqR7pm64A9\nJi1SkqRNjX0MLMkLgWXAXsA9wJeBw0bovxxYDrBkyZJxy5DU8XiWFppJdiG+EbilqjZW1cPAV4CD\ngZ27XYoAi4H1W+pcVSuqar6q5ufm5iYoQ5K0EE0SYD8BDkqyU5IAhwLXAxcBR3ZtjgHOnaxESZI2\nN8kxsMvonaxxBb1T6J8BrAD+HPhQkrX0TqU/ZQp1SpL0BBO9D6yqTgJO2mTzzcCBk9yvtD0Y95iU\nx7Kk4XglDklSkwwwSVKTDDBJUpO8Gr00BI9LSdseZ2CSpCYZYJKkJhlgkqQmeQxMTfI9VpKcgUmS\nmmSASZKaZIBJkppkgEmSmmSASZKa5FmI2qo8K1DSuJyBSZKaZIBJkppkgEmSmmSASZKaZIBJkprk\nWYjajNcZlNQCZ2CSpCYZYJKkJhlgkqQmTRRgSXZOck6SHyW5Iclrk+yS5IIkN3XfXzitYiVJetyk\nM7DPAv9cVb8K7AvcAJwArKyqvYGV3bokSVM1doAleQHw74FTAKrqoaq6B1gGnN41Ox04YtIiJUna\n1CSn0e8FbAT+V5J9gdXAB4HdquqOrs2dwG6TlahxeVq7pO3ZJLsQdwT2Bz5XVfsB97PJ7sKqKqC2\n1DnJ8iSrkqzauHHjBGVIkhaiSQJsHbCuqi7r1s+hF2h3JdkdoPu+YUudq2pFVc1X1fzc3NwEZUiS\nFqKxA6yq7gRuT/LKbtOhwPXAecAx3bZjgHMnqlCSpC2Y9FJSfwSckeRZwM3Ae+iF4tlJjgVuA942\n4RiSJG1mogCrqquA+S3cdOgk9ytJ0iBeiUOS1CQDTJLUJD9OpRG+p0uSnsgAe5oZRJI0He5ClCQ1\nyRnYmJxJSdLW5QxMktQkA0yS1CQDTJLUJANMktQkT+LAEzIkqUXOwCRJTTLAJElN2q52IborUJIW\nDmdgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZYJKkJhlgkqQmGWCSpCYZYJKkJk0cYEl2SHJlkn/q\n1vdKclmStUm+lORZk5cpSdITTWMG9kHghr71TwKfqaqXAz8Hjp3CGJIkPcFEAZZkMfAW4AvdeoBD\ngHO6JqcDR0wyhiRJWzLpDOy/AR8BHuvWdwXuqapHuvV1wB4TjiFJ0mbGDrAkhwMbqmr1mP2XJ1mV\nZNXGjRvHLUOStEBNMgM7GPidJLcCZ9HbdfhZYOckj39My2Jg/ZY6V9WKqpqvqvm5ubkJypAkLURj\nB1hVnVhVi6tqKXAUcGFVvQO4CDiya3YMcO7EVUqStIlZvA/sz4EPJVlL75jYKTMYQ5K0wE3lE5mr\n6tvAt7vlm4EDp3G/kiQ9Ga/EIUlqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWqS\nASZJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEmSWqSASZJapIBJklqkgEm\nSWqSASZJapIBJklqkgEmSWrS2AGWZM8kFyW5Psl1ST7Ybd8lyQVJbuq+v3B65UqS1DPJDOwR4E+r\nah/gIOC4JPsAJwArq2pvYGW3LknSVI0dYFV1R1Vd0S3/ArgB2ANYBpzeNTsdOGLSIiVJ2tRUjoEl\nWQrsB1wG7FZVd3Q33QnsNo0xJEnqN3GAJXk+8A/AH1fVv/TfVlUF1JP0W55kVZJVGzdunLQMSdIC\nM1GAJXkmvfA6o6q+0m2+K8nu3e27Axu21LeqVlTVfFXNz83NTVKGJGkBmuQsxACnADdU1X/tu+k8\n4Jhu+Rjg3PHLkyRpy3acoO/BwLuAa5Nc1W37C+Bk4OwkxwK3AW+brERJkjY3doBV1XeBPMnNh457\nv5IkDcMrcUiSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSA\nSZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmSmmSASZKaZIBJkppkgEmS\n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\n",
       "text/plain": [
-       "'inhisjournaldatedtheidesofoctoberintheyearoftheconsulshipsofcaeceliustulliuscapitopomponianusplotiusfirmusandgaiuscorneliusgallicanusagricolawrotethemysteryofthebattleatcamulodonumisatlastsolvedcalgacusmaybeabarbariannowbuthewasaromancitizenthenwhobetrayedusallforloveofabarbarianithastakenallmyskillsasaleaderofmentokeephimalivethelegionnairesspendtheireveningsdesigningnewandcruelwaystoexecutehiminrevengefortheshamehebroughtuponusbuthislifeispreciousitistheonlycardlefttoplayinoursearchforsalvationandthereturnofthestolenaquilaeifwecanalsorecoverthecodexthenperhapsitslosscanbeconcealedandourliveswillbesparedreleasingtheromantraitorcalgacusmusthavestuckintheproudagricolasthroatbuthemadeapactwiththeremainingcaledoniiandtravellednorthtoexchangetheprisonerfortheaquilaeandthecodexbutthecunningcaledoniantribesmansetanothertrapandpresentedagricolawithaforgerycunninglyassembledwithpagesfromthebooksstolenwhenthetriberansackedmonsgraupiusfortoolongthesonsofromehadunderestimatedthepeopleinbritanniaandwhiletheaquilaofthelegionhadbeenrestoredbytheexchangetheirhonourwasnotagricolafacedareturntoromehumiliationandalmostcertaindeaththesixthchapterofmytaleofwoeisguardedbylightningbullandoak'"
+       "<matplotlib.figure.Figure at 0x7f66f2e590b8>"
       ]
      },
-     "execution_count": 30,
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "fp = collections.Counter(vb5)\n",
+    "plot_frequency_histogram(fp, sort_key=fp.get)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 86,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.5/dist-packages/matplotlib/figure.py:403: UserWarning: matplotlib is currently using a non-GUI backend, so cannot show the figure\n",
+      "  \"matplotlib is currently using a non-GUI backend, \"\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAaoAAAEmCAYAAAAz/dRVAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAEaJJREFUeJzt3XuQJXV5xvHvI2C4egFGjcI6mFgkxsSgoxHRxABaRDCY\nClZEEUm0NqbESyKxlhhLitIqjJbGqtxckWAiQSPexSgUqKAiuruA7LIIRlYuQVkkUZFSQN78cQ4w\n7IWZPt07+5ud76dqak6f6bf7nXP6zHN+fXq6U1VIktSqh2zvBiRJejAGlSSpaQaVJKlpBpUkqWkG\nlSSpaQaVJKlpBpUkqWkGlSSpaQaVJKlpBpUkqWk7L+TK9t1335qenl7IVUqSGrV69epbq2pqrvkW\nNKimp6dZtWrVQq5SktSoJN+bz3zu+pMkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2g\nkiQ1zaCSJDXNoJIkNW1BT6EkSWrL9IpzO9dsOO3IbdDJ1jmikiQ1zaCSJDXNoJIkNc2gkiQ1zaCS\nJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDVtzqBKckaSW5Ks3cLP3pikkuy7bdqTJC11\n8xlRnQkcsemdSfYHng9cP3BPkiTdZ86gqqqLgNu28KP3AG8CauimJEm610SfUSU5Gripqq4YuB9J\nkh6g8/WokuwO/A2j3X7zmX85sBxg2bJlXVcnSVriJhlR/QpwAHBFkg3AfsCaJI/Z0sxVtbKqZqpq\nZmpqavJOJUlLUucRVVVdCTzq3ulxWM1U1a0D9iVJEjC/w9PPBi4BDkxyY5JXbvu2JEkamXNEVVXH\nzvHz6cG6kSRpE56ZQpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSD\nSpLUNINKktQ0g0qS1LTOl/mQJA1nesW5nWs2nHbkYPWLgSMqSVLTDCpJUtMMKklS0wwqSVLTDCpJ\nUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtPmDKokZyS5JcnaWfe9M8nVSb6V5BNJHrFt\n25QkLVXzGVGdCRyxyX3nA0+uqt8CrgFOHrgvSZKAeQRVVV0E3LbJfedV1d3jya8D+22D3iRJGuQz\nqj8D/muA5UiStJleQZXkzcDdwFkPMs/yJKuSrNq4cWOf1UmSlqCJgyrJCcBRwMuqqrY2X1WtrKqZ\nqpqZmpqadHWSpCVqoiv8JjkCeBPwe1V1x7AtSZJ0v/kcnn42cAlwYJIbk7wS+AdgL+D8JJcn+Zdt\n3KckaYmac0RVVcdu4e4PbINeJEnajGemkCQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1\nzaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNW2iy3xI0o5gesW5nWs2nHbkYPWaH0dUkqSmGVSSpKYZ\nVJKkphlUkqSmGVSSpKYZVJKkphlUkqSmGVSSpKYZVJKkphlUkqSmGVSSpKbNGVRJzkhyS5K1s+7b\nO8n5Sa4df3/ktm1TkrRUzWdEdSZwxCb3rQAuqKonAheMpyVJGtycQVVVFwG3bXL30cAHx7c/CLxo\n4L4kSQIm/4zq0VV18/j294FHD9SPJEkP0Pt6VFVVSWprP0+yHFgOsGzZsr6rk7QD8XpQmo9JR1Q/\nSPLLAOPvt2xtxqpaWVUzVTUzNTU14eokSUvVpEH1aeAV49uvAD41TDuSJD3QfA5PPxu4BDgwyY1J\nXgmcBjwvybXA4eNpSZIGN+dnVFV17FZ+dNjAvUiStBnPTCFJappBJUlqmkElSWqaQSVJappBJUlq\nmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWpa7wsnSlq6vHChFoIjKklS0wwqSVLT\nDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTegVVkr9Msi7J2iRn\nJ9l1qMYkSYIeQZXkccDrgJmqejKwE/CSoRqTJAn67/rbGdgtyc7A7sD/9G9JkqT7TRxUVXUT8C7g\neuBm4EdVdd5QjUmSBP12/T0SOBo4AHgssEeS47Yw3/Ikq5Ks2rhx4+SdSpKWpD67/g4HrquqjVV1\nF/Bx4FmbzlRVK6tqpqpmpqameqxOkrQU9Qmq64FnJtk9SYDDgPXDtCVJ0kifz6guBc4B1gBXjpe1\ncqC+JEkCRkftTayq3gq8daBeJEnajGemkCQ1zaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNc2gkiQ1\nzaCSJDXNoJIkNc2gkiQ1zaCSJDXNoJIkNa3XSWklLV7TK87tXLPhtCO3QSfSg3NEJUlqmkElSWqa\nQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWpar6BK8ogk5yS5Osn6\nJAcP1ZgkSdD/pLTvBT5fVcckeSiw+wA9SZJ0n4mDKsnDgd8FTgCoqjuBO4dpS5KkkT67/g4ANgL/\nmuSyJKcn2WOgviRJAvrt+tsZeCrw2qq6NMl7gRXAW2bPlGQ5sBxg2bJlPVYn7Vj6Xg/K60lpqegz\noroRuLGqLh1Pn8MouB6gqlZW1UxVzUxNTfVYnSRpKZo4qKrq+8ANSQ4c33UYcNUgXUmSNNb3qL/X\nAmeNj/j7LvCn/VuSJOl+vYKqqi4HZgbqRZKkzXhmCklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJ\nUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtP6nj1dmkgLFw1soQdJc3NEJUlqmkElSWqa\nQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWqaQSVJappBJUlqmkElSWpa76BKslOSy5J8doiG\nJEmabYgR1euB9QMsR5KkzfQKqiT7AUcCpw/TjiRJD9R3RPX3wJuAewboRZKkzUx8PaokRwG3VNXq\nJM99kPmWA8sBli1bNunqNDCvxSRpsegzojoE+MMkG4APA4cm+dCmM1XVyqqaqaqZqampHquTJC1F\nEwdVVZ1cVftV1TTwEuDCqjpusM4kScL/o5IkNW7iz6hmq6ovAV8aYlmSJM3miEqS1DSDSpLUNINK\nktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSDSpLUNINKktQ0g0qS1DSDSpLUtEHO9bfUbO9rOXktKElL\niSMqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMMKklS0wwqSVLTDCpJUtMM\nKklS0yYOqiT7J/likquSrEvy+iEbkyQJ+p09/W7gjVW1JslewOok51fVVQP1JknS5COqqrq5qtaM\nb/8EWA88bqjGJEmCgT6jSjINHARcOsTyJEm6V++gSrIn8DHgDVX14y38fHmSVUlWbdy4se/qJElL\nTK+gSrILo5A6q6o+vqV5qmplVc1U1czU1FSf1UmSlqA+R/0F+ACwvqrePVxLkiTdr8+I6hDg5cCh\nSS4ff71goL4kSQJ6HJ5eVV8BMmAvkiRtxjNTSJKaZlBJkppmUEmSmmZQSZKaZlBJkppmUEmSmmZQ\nSZKaZlBJkppmUEmSmmZQSZKaZlBJkprW51L02830inM712w47cjB6iVJC8cRlSSpaQaVJKlpBpUk\n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\n",
+      "text/plain": [
+       "<matplotlib.figure.Figure at 0x7f66f2f76278>"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "fp = collections.Counter(every_nth(scb, 15)[0])\n",
+    "plot_frequency_histogram(fp, sort_key=fp.get)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 140,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'etoainhsrdlumwycfgpbvkxjqz'"
+      ]
+     },
+     "execution_count": 140,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "beaufort_decipher(sanitise(cb), kb)"
+    "ltrs = [p[0] for p in english_counts.most_common()]\n",
+    "cat(ltrs)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 31,
+   "execution_count": 156,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'a'"
+       "'trguenloasybvhmqdifpkxwzcj'"
       ]
      },
-     "execution_count": 31,
+     "execution_count": 156,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "unpos(25 - pos('z'))"
+    "ctls =  [p[0] for p in collections.Counter(sanitise(vb)).most_common()]\n",
+    "cat(ctls)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 32,
+   "execution_count": 154,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'zyxwvutsrqponmlkjihgfedcba'"
+       "{'a': 'i',\n",
+       " 'b': 'c',\n",
+       " 'c': 'r',\n",
+       " 'd': 'h',\n",
+       " 'e': 'a',\n",
+       " 'f': 'd',\n",
+       " 'g': 'e',\n",
+       " 'h': 'v',\n",
+       " 'i': 't',\n",
+       " 'j': 'z',\n",
+       " 'k': 'y',\n",
+       " 'l': 'g',\n",
+       " 'm': 'f',\n",
+       " 'n': 'l',\n",
+       " 'o': 'o',\n",
+       " 'p': 'j',\n",
+       " 'q': 'p',\n",
+       " 'r': 'n',\n",
+       " 's': 'm',\n",
+       " 't': 's',\n",
+       " 'u': 'w',\n",
+       " 'v': 'b',\n",
+       " 'w': 'x',\n",
+       " 'x': 'q',\n",
+       " 'y': 'u',\n",
+       " 'z': 'k'}"
       ]
      },
-     "execution_count": 32,
+     "execution_count": 154,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "cat(unpos(25 - pos(l)) for l in string.ascii_lowercase)"
+    "trans = {pr[1]: pr[0] for pr in zip(ltrs, ctls)}\n",
+    "trans"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 33,
+   "execution_count": 157,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'hveheifhbiicuzbbcfgvvnzafwnkqnndivxopvpdionrsyrmjvjlkaehbrfsmvmtvkqrrftcyspatroqqnbndcyiqretamkaszhcaqidtaxmpfrvenkfimmihgrxnvgqtrmcpzsqzpygininbbstddlcomipnnqgqargdgmrkbijtxnubxpuzjzbizesjbvqmutztdzotjzktjvraioamqznxiwnstbedizjnbjurebqqhldegrzvnynjbsdzprnparcknlqxnmryaisrqjxquzevdcijkzsbmmkczinszckaxrmkvnnzzfwlmksajvrzcqdrkqsdfgvyobqfemifqqrjcoilkydqodhdevxbauvrqdmumxaorieubzrdxvrlcowvodkrsqgzzsizvmdvddrnigrzayrlmednqfhqcblgnvrrntkusntzwdqpoddtvypazkhaqgqneyixiiukmcsfngyktqeftzpdmqtupjzjrkdxsunenxybyvqmqtdmfsdcmjkntbmmplvvvmzwvmzzzzcfymmtfumostdtbnzfkydvmddgrccdbjcnapbmmsrmjvtvztbcmmubemtzmdathxksrckiivczbkqzjvxbbyvqwjzzsinsowitztdzotjzenbyrumpsgbbvxopvgqwrcmfivmjtrjsponmsshdcmdrcmxombkjsopkydzblmhevxbkrcdllmuhranozrmdtidpmfedcbfvwkezzfvgrzxizrwkddefedcmrhtqizqzeqdcmtfcmuagskuoxceehvdbmkvqyiqreszfaqrdnxnmkrmwqgqqkekkieuozbrqmkrnvoizbwizihkukawixdzvbgmevxbtprrablnkvqgdbygzobrrqfzdcmsfnsprfncrxrpvespbsdhsrbvvjrbsbcynefqmilghcpeaqkbygwexspbramjbpmwdvgiatzcveonbzdzbbcfgvcojxcvhvyqusraxdireceehxdkuovylzkilefgvyobqfegiaaqdeeonbfidlyxfgvrhxprefmqgqhiuyiwlivipmasrtbdkfcznxbqcreoocieswonydyhwdtzrsqlmmmunvhwjkbmosmheqovbykgmphjsyprvxkvqwclksryojnnfdqpfgziqoyjpchoeszhetlptcrmllzw'"
+       "'Jtwo selgpbi nhl weembkawbgn ah gwne lnwcee ba huj yksftsavhh dgnfpilsf cbl alinbsw bh Kebvnantn nak lssreaef wu Sgqs gy wlw sak gi vcs hsal, nf fefeesk gh woe Iqnwegs. Os lenesk com onqe wsssbupe iag ml qewsk ucw up Sgxxwbaa wu ggwo Alcjwaci Ecitwdci uag Jsenaboi Lsaefby, kcw vos Wufl jels ewassgci aaf, eeandynuhh wce pgli mi sjs Dufsz ssqntgsg m lsmesv, xagjn maja wg a isr hghnh fgxvnfel isuq woe Gbhbo. Mouptmph dcmgfxav vg eewnef crl gfvvef moslcbv mi sjs Nfcbha nl n yuet fi duceaws, woe Iqnwegs lmassf ota wlw invs gl uwoss sbftenmsf weaseaql pdf, wu woe icemsrlm fi luqs, ce jnl axndlsf veboymonh ssafenvbgni. N lwaccm pnl eesmvsf up com Osaaws un wos ulfmv gi vos Eymseul, uib, wnxsa thp, Nvsrdynn jal lenw wg hrtm icbewpp ua obi vnxxph elwavs joels lw jni wsnksf up com Wqmeegs’i gja dbhfxdbaal. Ctl fsaco oml n webebgcl ibgay wg ys, nnk n mntgiin steaw vu npp crl kvbsnfl. Tv jnl lips ml n ssnh hgll ejsh kh wcgle vg joua om pnl ngw deelgnupja zauja. Noqussw, qyvsgbse, ul wos dmminnde nak vos uowh xmllel days wg crl lfcle; nak ta mcgqba spnmsl, anf joelsvwe zngwi ui wnhpsdo jsss niisquhif, lxl aaqs ral ga aqp jxml; nge ktf n ltgvjw lgop gn csnetgv yc obi fsavo esjmbaw nw vos nejl gs vgdtsw tw kotdzpp. Cowo lhymnvch jni raavsnisf gp wos rrfm-omeenf soqgcs copb os cnf gesa eeagvwf up mgtiga gn com Wqmeegs’i dgqyuag. Lgqtwban pglv gg sxqs ta nddgbavrae bos aqutvbgci Wnjrlwtcl Hodcphtl po woe asr wgtssggd fi wcs msutbami. Om pnl monswsf jtco fwdcsbaw vos isuvwns mende rbwo Mupmlgatn nnk osnkif sjsee wg muaieugw Ampvadci. Tw jni maja woea wcaw woe qgfo gi vos Mufsx rul dwtsapsk. Inpcicbio jeuws ul obl ibgay nw vos nejl bn u pmbwss wg Mawg facsg bos lbivc fnh giiyvs wcs zahsafi mi Xmh bn woe psne uv wlw dgnlchiobmi mi Xmedol Nsssdbntl Ansqeal TT naf Htdwrl Uasutol Ognmepbcl. “Rs nse sxmsilfnh dcnewef uh ute xflw ycatlbdsnc nhl veenw Eymseul Fyubwtna vu lsdols Nmx Euqnna ba wci Ayvwoeea Xtavfual pdf hew huo jebvi wy us gl woe hgll uv wlw Dgksx Umdcpvmeiu. Hgoe peafse Aoewegpa oni apesash nmbf vos dsbds uv lieo n hgli, gcw bl ygi lg auw eemgtss com Egfex uelges vbs nmlltav ul wos pind bosn hgo ynh ue wcdw woaw huo jbph zgwd oby. Hgo vspp yi wlmw bnwshhbvsnfs kvgq a dndvcesk wmr ocvwslvi wonv com bentwgs Mnpvafcf jnl vos Mufsx agf wo qnilbnw obl itmnfeweel tn wos Nmesj. Jotps vcs Unsdndxnai woeylspbil pvs cnpbxeph wu antw qcmo gl vos Dussb, Enpwndoi bl nn ifienwef Euyna nns om uclv us ivgmmes umcgee os maa fsiceya woe lsmoebwp mi sjs Bymsstnp dtkomvl. Wcs Duksx jtqp qw esmgtessf, gs ygi, agcs inytph nns svwehuas puc zaux jwnp mah wce mebmi. Nhl lg vg wce lstegwl snev gi vcs weoi lsfeh ui Nwsbdghu bh pobmo wce inwe mi sjs atawc hsvbug nhl gi vos Mufsx tclmni jtpp tn wbqe ds dwtsapsk. Oawbh comd bw rbph gs vcalfml uh vos andbsnc Upkhpuaban Vgfkilf fi Jae.'"
       ]
      },
-     "execution_count": 33,
+     "execution_count": 157,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "rscb = cat(unpos(25 - pos(l)) for l in scb)\n",
-    "rscb"
+    "tt = ''.maketrans(trans)\n",
+    "# tpack(repunctuate(vb.translate(tt), pub))\n",
+    "repunctuate(vb.translate(tt), pub)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 158,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Zxlv ehbtfms iyb lhhcmjolmti oy tlih bilrhh mo ydz ujeaxeonyy ktiafsbea rmb obsimel my Jhmnioixi ioj\n",
+      "beephoha ld Etqe tu lbl eoj ts nre yeob, ia ahahhej ty lvh Sqilhte. Ve bhihej rvc viqh leeemdfh sot\n",
+      "cb qhlej drl df Etwwlmoo ld ttlv Obrzlors Hrsxlkrs dot Zehiomvs Beohamu, jrl nve Ldab zhbe hloeetrs\n",
+      "ooa, hhoikuidyy lrh ftbs cs eze Kdaeg eeqixtet c bechen, wotzi cozo lt o sep ytyiy atwniahb sedq lvh\n",
+      "Tmymv. Cvdfxcfy krctawon nt hhliha rpb tannha cvebrmn cs eze Iarmyo ib i udhx as kdrhole, lvh\n",
+      "Sqilhte bcoeea vxo lbl sine tb dlvee emaxhicea lhoehoqb fka, ld lvh srhcepbc as bdqe, rh zib owikbea\n",
+      "nhmvucviy eeoahinmtis. I blorrc fib hhecnea df rvc Veoole di lve dbacn ts nve Hucehdb, dsm, liweo\n",
+      "xyf, Inepkuii zob bhil lt ypxc srmhlff do vms niwwfy hblone zvhbe bl zis leijea df rvc Lqchhte’s tzo\n",
+      "kmyawkmoob. Rxb aeorv vcb i lhmhmtrb smtou lt ue, iij i cixtssi exhol nd iff rpb jnmeiab. Xn zib\n",
+      "bsfe cb i eeiy ytbb hzey jy lrtbh nt zvdo vc fib itl khhbtidfzo godzo. Ivqdeel, qunetmeh, db lve\n",
+      "kccsiikh ioj nve dvly wcbbhb koue lt rpb barbh; ioj xo crtqmo eficeb, oia zvhbenlh gitls ds liyfekv\n",
+      "zeee isseqdysa, bwb ooqe pob to oqf zwcb; ith jxa i bxtnzl btvf ti reihxtn ur vms aeonv hezcmol il\n",
+      "nve ihzb te ntkxel xl jvxkgff. Rvlv byucinry zis pooneisea tf lve ppac-vchhia evqtre rvfm ve ria\n",
+      "theo hhotnla df ctxsto ti rvc Lqchhte’s ktqudot. Btqxlmoi ftbn tt ewqe xo ikktmonpoh mve oqdxnmtrs\n",
+      "Lizpblxrb Yvkrfyxb fv lvh oep ltxeettk as lre cedxmocs. Vc fib cvielea zxrv alkremol nve sednlie\n",
+      "chikh pmlv Cdfcbtoxi iij veijsa ezehh lt cdoshdtl Ocfnokrs. Xl zis cozo lvho lrol lvh qtav ts nve\n",
+      "Cdaew pdb klxeofej. Sifrsrmsv zhdle db vmb smtou il nve ihzb mi d fcmlee lt Colt aoret mve bmsnr aiy\n",
+      "tssune lre goyeoas cs Wcy mi lvh feih dn lbl ktibrysvmcs cs Wchkvb Ieeekmixb Oieqhob XX ioa Yxklpb\n",
+      "Doedxvb Vtichfmrb. “Pe ieh ewcesbaiy krihlha dy dxh wabl uroxbmkeir iyb nhhil Hucehdb Audmlxio nd\n",
+      "bekvbe Icw Hdqiio mo lrs Ounlvhho Wxonadob fka yhl ydv zhmns lu de tb lvh ytbb dn lbl Ktjew\n",
+      "Dckrfnchsd. Ytvh fhoaeh Ovhlhtfo vis ofheoey icma nve kemke dn bshv i ytbs, trl mb uts bt odl\n",
+      "hhctxee rvc Htahw dhbthe nme icbbxon db lve fsik mvei ytv uiy dh lrkl lvol ydv zmfy gtlk vmu. Ytv\n",
+      "neff us lbcl mileyymneiae jntq o kiknrhej lcp vrnlebns lvin rvc mhixlte Cifnoara zib nve Cdaew ota\n",
+      "lv qisbmil vmb sxciahlhhb xi lve Ichez. Zvxfe nre Diekikwios lvhubefmsb fne rifmwhfy ld oixl qrcv tb\n",
+      "nve Kdeem, Hiflikvs mb ii sashilha Hduio iie vc drbn de sntcche dcrthh ve coo aesrhuo lvh becvhmlf\n",
+      "cs eze Muceexif kxjvcnb. Lre Kdjew zxqf ql hectxheea, te uts, otre siuxfy iie enlhydoe fdr godw zlif\n",
+      "coy lrh chmcs. Iyb bt nt lrh bexhtlb eihn ts nre lhvs beahy ds Ilemktyd my fvmcv lrh silh cs eze\n",
+      "oxolr yenmdt iyb ts nve Cdaew xrbcis zxff xi lmqh ke klxeofej. Volmy rvck ml pmfy te nrobacb dy nve\n",
+      "oikmeir Dfjyfdomoi Ntajsba as Zoh.\n"
+     ]
+    }
+   ],
+   "source": [
+    "trans = {\n",
+    " 'a': 's',\n",
+    " 'b': 'r',\n",
+    " 'c': 'p',\n",
+    " 'd': 'y',\n",
+    " 'e': 'o',\n",
+    " 'f': 'k',\n",
+    " 'g': 'h',\n",
+    " 'h': 'n',\n",
+    " 'i': 'x',\n",
+    " 'j': 'g',\n",
+    " 'k': 'u',\n",
+    " 'l': 't',\n",
+    " 'm': 'a',\n",
+    " 'n': 'b',\n",
+    " 'o': 'v',\n",
+    " 'p': 'z',\n",
+    " 'q': 'f',\n",
+    " 'r': 'i',\n",
+    " 's': 'c',\n",
+    " 't': 'e',\n",
+    " 'u': 'l',\n",
+    " 'v': 'm',\n",
+    " 'w': 'w',\n",
+    " 'x': 'q',\n",
+    " 'y': 'd',\n",
+    " 'z': 'j'}\n",
+    "\n",
+    "\n",
+    "tt = ''.maketrans(trans)\n",
+    "print(lcat(tpack(repunctuate(vb.translate(tt), pub).split())))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 34,
+   "execution_count": 96,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "('zixzmzrnkvirr', -1506.8637359274674)"
+       "('jcarykujniqadmv', 15)"
       ]
      },
-     "execution_count": 34,
+     "execution_count": 96,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "kb, score = vigenere_frequency_break(rscb)\n",
-    "kb, score"
+    "kbv, len(kbv)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 35,
+   "execution_count": 98,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'inhisjournaldatedtheidesofoctoberintheyearoftheconsulshipsofcaeceliustulliuscapitopomponianusplotiusfirmusandgaiuscorneliusgallicanusagricolawrotethemysteryofthebattleatcamulodonumisatlastsolvedcalgacusmaybeabarbariannowbuthewasaromancitizenthenwhobetrayedusallforloveofabarbarianithastakenallmyskillsasaleaderofmentokeephimalivethelegionnairesspendtheireveningsdesigningnewandcruelwaystoexecutehiminrevengefortheshamehebroughtuponusbuthislifeispreciousitistheonlycardlefttoplayinoursearchforsalvationandthereturnofthestolenaquilaeifwecanalsorecoverthecodexthenperhapsitslosscanbeconcealedandourliveswillbesparedreleasingtheromantraitorcalgacusmusthavestuckintheproudagricolasthroatbuthemadeapactwiththeremainingcaledoniiandtravellednorthtoexchangetheprisonerfortheaquilaeandthecodexbutthecunningcaledoniantribesmansetanothertrapandpresentedagricolawithaforgerycunninglyassembledwithpagesfromthebooksstolenwhenthetriberansackedmonsgraupiusfortoolongthesonsofromehadunderestimatedthepeopleinbritanniaandwhiletheaquilaofthelegionhadbeenrestoredbytheexchangetheirhonourwasnotagricolafacedareturntoromehumiliationandalmostcertaindeaththesixthchapterofmytaleofwoeisguardedbylightningbullandoak'"
+       "['jkq', 'cua', 'ajd', 'rnm', 'yiv']"
       ]
      },
-     "execution_count": 35,
+     "execution_count": 98,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "vigenere_decipher(rscb, kb)"
+    "every_nth(kbv, 5)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 36,
+   "execution_count": 102,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def index_of_coincidence(text):\n",
+    "    stext = sanitise(text)\n",
+    "    counts = collections.Counter(stext)\n",
+    "    denom = len(stext) * (len(text) - 1) / 26\n",
+    "    return (\n",
+    "        sum(max(counts[l] * counts[l] - 1, 0) for l in string.ascii_lowercase) \n",
+    "        / \n",
+    "        denom\n",
+    "    )"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 103,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1.0739632382990911"
+      ]
+     },
+     "execution_count": 103,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "index_of_coincidence(scb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 104,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'arcanaimperii'"
+       "1.7196234250491917"
       ]
      },
-     "execution_count": 36,
+     "execution_count": 104,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "cat(unpos(25 - pos(l)) for l in kb)"
+    "index_of_coincidence(pa)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 37,
+   "execution_count": 105,
    "metadata": {},
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "in his journal dated the ides of october in the year of the consulships of caec eli us tullius\n",
-      "capito pompon ian us plot i us firm us and gaius cornelius galli can us agricola wrote the mystery\n",
-      "of the battle at camu lo donum is at last solved cal gac us maybe a barbarian now but he was a roman\n",
-      "citizen then who betrayed us all for love of a barbarian it has taken all my skills as a leader of\n",
-      "men to keep him alive the legionnaires spend their evenings designing new and cruel ways to execute\n",
-      "him in revenge for the shame he brought upon us but his life is precious it is the only card left to\n",
-      "play in our search for salvation and the return of the stolen aquilae if we can also recover the\n",
-      "codex then perhaps its loss can be concealed and our lives will be spared releasing the roman\n",
-      "traitor cal gac us must have stuck in the proud agricola s throat but he made a pact with the\n",
-      "remaining caledon ii and travelled north to exchange the prisoner for the aquilae and the codex but\n",
-      "the cunning caledonian tribesman set another trap and presented agricola with a forgery cunningly\n",
-      "assembled with pages from the books stolen when the tribe ransacked mons grau pius for too long the\n",
-      "sons of rome had underestimated the people in britannia and while the aquila of the legion had been\n",
-      "restored by the exchange their honour was not agricola faced a return to rome humiliation and almost\n",
-      "certain death the sixth chapter of my tale of woe is guarded by lightning bull and oak\n"
+      "1 1.0739632382990911\n",
+      "2 1.0847309682648545\n",
+      "3 1.1901326088129982\n",
+      "4 1.0944337274794889\n",
+      "5 1.3385608752635192\n",
+      "6 1.2148423611711687\n",
+      "7 1.1475045557348746\n",
+      "8 1.126018862329491\n",
+      "9 1.246033937674865\n",
+      "10 1.387327185449383\n",
+      "11 1.1687618776366193\n",
+      "12 1.2613508799467053\n",
+      "13 1.1901044676035653\n",
+      "14 1.1988503247011726\n",
+      "15 1.8423114658282445\n",
+      "16 1.1835776099617201\n",
+      "17 1.229047094202011\n",
+      "18 1.3067952909636624\n",
+      "19 1.2593538199678038\n"
      ]
     }
    ],
    "source": [
-    "print('\\n'.join(tpack(segment(vigenere_decipher(rscb, kb)))))"
+    "for i in range(1, 20):\n",
+    "    print(i, sum(index_of_coincidence(section) for section in every_nth(scb, i)) / i)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 38,
+   "execution_count": 106,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "1465"
+       "[(1, 1.0739632382990911),\n",
+       " (2, 1.0847309682648545),\n",
+       " (4, 1.0944337274794889),\n",
+       " (8, 1.126018862329491),\n",
+       " (7, 1.1475045557348746),\n",
+       " (11, 1.1687618776366193),\n",
+       " (16, 1.1835776099617201),\n",
+       " (13, 1.1901044676035653),\n",
+       " (3, 1.1901326088129982),\n",
+       " (14, 1.1988503247011726),\n",
+       " (6, 1.2148423611711687),\n",
+       " (17, 1.229047094202011),\n",
+       " (9, 1.246033937674865),\n",
+       " (19, 1.2593538199678038),\n",
+       " (12, 1.2613508799467053),\n",
+       " (18, 1.3067952909636624),\n",
+       " (5, 1.3385608752635192),\n",
+       " (10, 1.387327185449383),\n",
+       " (15, 1.8423114658282445)]"
       ]
      },
-     "execution_count": 38,
+     "execution_count": 106,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "open('5b.plaintext', 'w').write('\\n'.join(tpack(segment(vigenere_decipher(rscb, kb)))))"
+    "ics = [(i, sum(index_of_coincidence(section) for section in every_nth(scb, i)) / i)\n",
+    "       for i in range(1, 20)]\n",
+    "sorted(ics, key=lambda p: p[1])"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 39,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
+   "execution_count": 159,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'etgyasrlhmbcinkuodwfqvjpxz'"
+      ]
+     },
+     "execution_count": 159,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "ctls =  [p[0] for p in collections.Counter(sanitise(vb5)).most_common()]\n",
+    "cat(ctls)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 160,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "{'a': 'i',\n",
+       " 'b': 'l',\n",
+       " 'c': 'u',\n",
+       " 'd': 'g',\n",
+       " 'e': 'e',\n",
+       " 'f': 'b',\n",
+       " 'g': 'o',\n",
+       " 'h': 'r',\n",
+       " 'i': 'm',\n",
+       " 'j': 'x',\n",
+       " 'k': 'y',\n",
+       " 'l': 's',\n",
+       " 'm': 'd',\n",
+       " 'n': 'w',\n",
+       " 'o': 'f',\n",
+       " 'p': 'j',\n",
+       " 'q': 'v',\n",
+       " 'r': 'h',\n",
+       " 's': 'n',\n",
+       " 't': 't',\n",
+       " 'u': 'c',\n",
+       " 'v': 'k',\n",
+       " 'w': 'p',\n",
+       " 'x': 'q',\n",
+       " 'y': 'a',\n",
+       " 'z': 'z'}"
+      ]
+     },
+     "execution_count": 160,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "trans = {pr[1]: pr[0] for pr in zip(ltrs, ctls)}\n",
+    "trans"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 161,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Pfwq spkxhbm nuc jvymakoeeun xh etfv nnhcpm en hpj dlolfslvlj punapbcol dbx aqfrtsf bu Lcxgnlnmh rnk\n",
+      "dsopcdyf hu Hqte gr wtt odh gz vgd oead, nv iclyerk bj dce Mqftcfq. Or lphnek sol rfuy wrshvzhe mae\n",
+      "et uywrk tld gp Ggnyjxta hu bqdc Adcytkra Eyimepoi pae Hovbaaoy Kaneabd, lxb gor Wtuu reds ctkwqgyi\n",
+      "opq, sexniufkvh hcp rxii yi oho Erfrz hdtathse e twxerv, epxrn yaym jf t irr lqoah agnbflyl zstz dce\n",
+      "Hbuzz. Smuktrro mcygvykt gg jeahnk cwl eirtyf cohkftv yi oho Mpcaho hu a ypeh ib ercjaad, dce\n",
+      "Mqftcfq lcahdq ctx wtt bmgs wl tekes gbvxcmxsb wppasajl gsv, br wqe ylndswll ib orqr, cp cri aonicol\n",
+      "geaowakah gskicmgbwny. H uvascl afo yermndq gp sol Rodtwr uc eke udflb ec gor Ewaasud, ubz, jmisl\n",
+      "tlr, Rwswdddf ptl xece du hwtl oxxywkp tp kti knnyga ylhand iceds tt yma wrnzdq gp sol Tmsyews’y qin\n",
+      "dlhvyixtax. Cmk qeaso zet m ueaedqfi ilgku jf os, inz h hathibd ozyah vt hch cwl wbpwbfx. Tn cri\n",
+      "lmpo et m qsih lqui evsu lu bdgxe nq icux ol afo bgh dpmuunppym adrjl. Nuzzesf, qdbofksj, uq eke\n",
+      "dymbdfey nlk nia gofh netoyl oawd du cwl tixoy; nlk mp hogjbk vgmxsx, acu icedsrtc ybghi tf dahtsir\n",
+      "ywqs iiydtghmf, tyt dtqr rok xn ajp yylo; bgj kmu r ithvyt tfmp wn gdrsthv dj zxa frani nejybkt fb\n",
+      "gor npcu us kgixob fw tomnwhp. Sojr taomivgj iai wakbomasb gi eke rwfl-rlvynb suzxos sogz zw dnb\n",
+      "gpdj sexgrtv kw mwtyqj un sol Tmsyews’y nxyypae. Ceufwaac rxiv hg oymw fa idjqenvwac zzw tqvtnvxoi\n",
+      "Fnyptbfcx Hunfhhil gr jjy arr aqseshgi ib bds cstwenmm. Ol afo xoisadq rtso vtirqblw nia lspvjdo\n",
+      "synoe fvdc Mpplcedfn inz iaakmf ohovy ww mtpgsuhw Kegttdyi. Me iai yaym jjya hcoe dce jgvr ec gor\n",
+      "Mtuaz rpl ithwtprk. Yhcoisbbr yvrwr uq iei ilgku fb gor npcu tn p plzjwq ww Moex kasse zzw nbzvg urp\n",
+      "gmidbo bds maldjki yi Neu xb wqe idrs uk wtt ifblyhyiedi yi Neceml Ishdptnil Kdouyax TM hjk Hidjpt\n",
+      "Ktsvtuk Kunyegzxo. “Es isp dvdsmlvdu ednjwpu zp uie nitb ocltqvpens nuc rvynh Ewaasud Fdfpbfnl vt\n",
+      "kamods Fen Vrqino vj vcm Adbjjyel Xmpmkuxl gsv ayw fuu cntvm wd fo fn wqe lqui uk wtt Ifhsd\n",
+      "Urnfhvyebf. Ufme keouas Aeejwent oii orneagh fepl gor dhvpe uk lbwz m vgxi, bld tl rgb ce drw\n",
+      "jerqses sol Welyx veqqne vls fetofap uq eke pmni zzwb hwo who ge fcit jjtw fuu cehh cgjs zxo. Hwo\n",
+      "ndch ym wtej xbwrhlvmenas wbeu t didnlnek fmq rxtusxvy ekav sol zcmfwws Rhcwaacv hfo gor Mtuaz ahf\n",
+      "jr mmalana iei iimficbyex tc eke Nyeoh. Yjfpr vgd Zasqniyfda wqewkahbml gbo rbpaxpro vu xnht mrxo wl\n",
+      "nia Mugsp, Wfnunooy vu an mfbwfbyf Juwhj ang ol fxog ur inqhdeg uljevy or mop qeisedm jjy lrmumevp\n",
+      "yi oho Xomrsmhc mtnolbt. Bds Ouzdv rtjp mt cwxgnehdq, us rgb, merq iiymro ang srtcarar ptl wnuo jjdg\n",
+      "sth hcp antmm. Nuc tf gg hcp kabehwt vfvg gz vgd dsom loica ri Iwhvpuhp bu azxxo hcp frve yi oho\n",
+      "dfahc ldmtuh nuc ec gor Mtuaz tslldb pfpk tc eeye qs ithwtprk. Updth sols pb ebkh bd moadflc sa gor\n",
+      "acneens Uglunraaac Sxkkmlv ib Pte.\n"
+     ]
+    }
+   ],
    "source": [
-    "def beaufort_encipher(message, keyword):\n",
-    "    \"\"\"Beaufort encipher\n",
+    "trans = {\n",
+    " 'a': 'i',\n",
+    " 'b': 'c',\n",
+    " 'c': 'r',\n",
+    " 'd': 'h',\n",
+    " 'e': 'a',\n",
+    " 'f': 'd',\n",
+    " 'g': 'e',\n",
+    " 'h': 'v',\n",
+    " 'i': 't',\n",
+    " 'j': 'z',\n",
+    " 'k': 'y',\n",
+    " 'l': 'g',\n",
+    " 'm': 'f',\n",
+    " 'n': 'l',\n",
+    " 'o': 'o',\n",
+    " 'p': 'j',\n",
+    " 'q': 'p',\n",
+    " 'r': 'n',\n",
+    " 's': 'm',\n",
+    " 't': 's',\n",
+    " 'u': 'w',\n",
+    " 'v': 'b',\n",
+    " 'w': 'x',\n",
+    " 'x': 'q',\n",
+    " 'y': 'u',\n",
+    " 'z': 'k'}\n",
     "\n",
-    "    >>> beaufort_encipher('inhisjournaldatedtheidesofoctober', 'arcanaimperii')\n",
-    "    'sevsvrusyrrxfayyxuteemazudmpjmmwr'\n",
-    "    \"\"\"\n",
-    "    shifts = [pos(l) for l in sanitise(keyword)]\n",
-    "    pairs = zip(message, cycle(shifts))\n",
-    "    return cat([unpos(k - pos(l)) for l, k in pairs])"
+    "tt = ''.maketrans(trans)\n",
+    "print(lcat(tpack(repunctuate(vb3.translate(tt), pub).split())))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 40,
+   "execution_count": 163,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'sevsvrusyrrxfayyxuteemazudmpjmmwr'"
+       "149.2"
       ]
      },
-     "execution_count": 40,
+     "execution_count": 163,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "beaufort_encipher('inhisjournaldatedtheidesofoctober', 'arcanaimperii')"
+    "len(scb)/15"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 41,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
+   "execution_count": 167,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[((7, 20, True), -192.8137923614311),\n",
+       " ((7, 0, True), -180.2911386965482),\n",
+       " ((7, 11, True), -183.95343106989503),\n",
+       " ((7, 2, True), -181.0350604256714),\n",
+       " ((7, 22, True), -192.14210180827317),\n",
+       " ((7, 8, True), -189.97699806864554),\n",
+       " ((7, 5, True), -183.3749838057261),\n",
+       " ((7, 20, True), -196.06251170079523),\n",
+       " ((7, 24, True), -192.12634724908915),\n",
+       " ((7, 6, True), -186.7317665812622),\n",
+       " ((7, 8, True), -186.75777446041903),\n",
+       " ((7, 11, True), -188.32887282416843),\n",
+       " ((7, 13, True), -193.76214231086124),\n",
+       " ((7, 24, True), -190.6840821835727),\n",
+       " ((7, 6, True), -188.8811192976835)]"
+      ]
+     },
+     "execution_count": 167,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
-    "beaufort_decipher = beaufort_encipher"
+    "[affine_break(section) for section in every_nth(scb, 15)]"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 42,
+   "execution_count": 168,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "'inhisjournaldatedtheidesofoctober'"
+       "[(7, 20, True),\n",
+       " (7, 0, True),\n",
+       " (7, 11, True),\n",
+       " (7, 2, True),\n",
+       " (7, 22, True),\n",
+       " (7, 8, True),\n",
+       " (7, 5, True),\n",
+       " (7, 20, True),\n",
+       " (7, 24, True),\n",
+       " (7, 6, True),\n",
+       " (7, 8, True),\n",
+       " (7, 11, True),\n",
+       " (7, 13, True),\n",
+       " (7, 24, True),\n",
+       " (7, 6, True)]"
       ]
      },
-     "execution_count": 42,
+     "execution_count": 168,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "beaufort_decipher('sevsvrusyrrxfayyxuteemazudmpjmmwr', 'arcanaimperii')"
+    "akeys = [affine_break(section)[0] for section in every_nth(scb, 15)]\n",
+    "akeys"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 43,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
+   "execution_count": 172,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'withresolveandtrepidationmydearfatherinlawobedientlyconcludedhisaffairsinbritanniaandreturnedtoromebytheendoftheyearasorderedbytheemperorhefearedthesameterribleendasmetedoutbydomitiantobotharulenusrusitcusandhernniusseneciobutthegodsweregenerousandremarkablythelossofthecodexremainedasecretknownonlytoafewloyalcomradesfromtheninthpubliclychoosingtoregardhisdoggedpursuitoftheaquilaasamarkofcouragetheemperorsparedhimthefateofotherdisgracedgeneralsandtothesurpriseofsomehewasawardedtriumphaldecorationsastatuewaserectedbythesenateontheorderoftheemperorbuttakenillagricolawassenttolivequietlyonhisfamilyestatewherehewastendedbytheemperorsownphysicianshisdeathwasagrievousshocktomeandapainfuleventtoallhisfriendsitwasfeltasareallossevenbythosetowhomhewasnotpersonallyknownnumbersmoreoverofthepopulaceandthebusymassescametohishouseandinpublicplacesandwhereverknotsoftalkerswereassembledhisnamewasonalllipsnordidasinglesoulonhearingofhisdeathrejoiceatthenewsorforgetitquicklythissympathywasincreasedbythewidespreadrumourthathehadbeenremovedbypoisonontheemperorscommanddomitianlostnotimeinappointingtheambitioussalustiuslucullusasthenewgovernoroftheprovincehewaschargedwithsecuringthefragilepeacewithcaledoniaandheadedtheretoconfrontcalgacusitwasonlythenthatthelossofthecodexwasrevealedsalustiuswroteofhisshockatthenewsinalettertocatodatedthefifthdaybeforethekalendsofmayintheyearoftheconsulshipsofmarcusarrecinusclemensiiandluciusbaebiushonoratusweareexpresslychargedbyourmostmunificentandgreatemperordomitiantosecurepaxromanainthenorthernkingdomsandyetyouwritetomeofthelossofthecodexoccultorumyourleaderagricolahasalreadypaidthepriceofsuchalossbutifyoudonotrecoverthecodexbeforethepassingoftheyearthenyoumaybesurethatyouwilljoinhimyoutellmethatintelligencefromacapturedspysuggeststhatthetraitorcalgacushasthecodexandismassinghissupportersinthenorthwhilethebarbariansthemselvesareunlikelytomakemuchofthecodexcalgacusisaneducatedromanandhemustbestoppedbeforehecandestroythesecurityoftheimperialciphersthecodexwillberecoveredoryouyourfamilyandeveryoneyouknowwillpaythepriceandsototheseventhpartofthetruestoryofagricolainwhichthefateoftheninthlegionandofthecodexitselfwillintimeberevealeduntilthenitwillbeguardedbytheancientbabyloniangoddessofwar'"
+      ]
+     },
+     "execution_count": 172,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
    "source": [
-    "# def beaufort_sub_break(message, fitness=Pletters):\n",
-    "#     best_shift = 0\n",
-    "#     best_fit = float('-inf')\n",
-    "#     for key in range(26):\n",
-    "#         plaintext = [unpos(key - pos(l)) for l in message]\n",
-    "#         fit = fitness(plaintext)\n",
-    "#         logger.debug('Beaufort sub break attempt using key {0} gives fit of {1} '\n",
-    "#                      'and decrypt starting: {2}'.format(key, fit,\n",
-    "#                                                         plaintext[:50]))\n",
-    "#         if fit > best_fit:\n",
-    "#             best_fit = fit\n",
-    "#             best_key = key\n",
-    "#     logger.info('Beaufort sub break best fit: key {0} gives fit of {1} and '\n",
-    "#                 'decrypt starting: {2}'.format(best_key, best_fit, \n",
-    "#                     cat([unpos(best_key - pos(l)) for l in message[:50]])))\n",
-    "#     return best_key, best_fit"
+    "spb = combine_every_nth(affine_decipher(section, key[0], key[1], key[2]) \n",
+    "                  for key, section in zip(akeys, every_nth(scb, 15)))\n",
+    "spb"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 44,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
+   "execution_count": 173,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "With resolve and trepidation my dear father in law obediently concluded his affairs in Britannia and\n",
+      "returned to Rome by the end of the year, as ordered by the Emperor. He feared the same terrible end\n",
+      "as meted out by Domitian to both Arulenus Rusitcus and Hernnius Senecio, but the Gods were generous\n",
+      "and, remarkably the loss of the Codex remained a secret, known only to a few loyal comrades from the\n",
+      "Ninth. Publicly choosing to regard his dogged pursuit of the Aquila as a mark of courage, the\n",
+      "Emperor spared him the fate of other disgraced generals and, to the surprise of some, he was awarded\n",
+      "triumphal decorations. A statue was erected by the Senate on the order of the Emperor, but, taken\n",
+      "ill, Agricola was sent to live quietly on his family estate where he was tended by the Emperor’s own\n",
+      "physicians. His death was a grievous shock to me, and a painful event to all his friends. It was\n",
+      "felt as a real loss even by those to whom he was not personally known. Numbers, moreover, of the\n",
+      "populace and the busy masses came to his house; and in public places, and wherever knots of talkers\n",
+      "were assembled, his name was on all lips; nor did a single soul on hearing of his death rejoice at\n",
+      "the news or forget it quickly. This sympathy was increased by the wide-spread rumour that he had\n",
+      "been removed by poison on the Emperor’s command. Domitian lost no time in appointing the ambitious\n",
+      "Salustius Lucullus as the new governor of the province. He was charged with securing the fragile\n",
+      "peace with Caledonia and headed there to confront Calgacus. It was only then that the loss of the\n",
+      "Codex was revealed. Salustius wrote of his shock at the news in a letter to Cato dated the fifth day\n",
+      "before the kalends of May in the year of the consulships of Marcus Arrecinus Clemens II and Lucius\n",
+      "Baebius Honoratus. “We are expressly charged by our most munificent and great Emperor Domitian to\n",
+      "secure Pax Romana in the Northern Kingdoms and yet you write to me of the loss of the Codex\n",
+      "Occultorum. Your leader Agricola has already paid the price of such a loss, but if you do not\n",
+      "recover the Codex before the passing of the year then you may be sure that you will join him. You\n",
+      "tell me that intelligence from a captured spy suggests that the traitor Calgacus has the Codex and\n",
+      "is massing his supporters in the North. While the Barbarians themselves are unlikely to make much of\n",
+      "the Codex, Calgacus is an educated Roman and he must be stopped before he can destroy the security\n",
+      "of the Imperial ciphers. The Codex will be recovered, or you, your family and everyone you know will\n",
+      "pay the price. And so to the seventh part of the true story of Agricola in which the fate of the\n",
+      "ninth legion and of the Codex itself will in time be revealed. Until then it will be guarded by the\n",
+      "ancient Babylonian Goddess of War.\n"
+     ]
+    }
+   ],
    "source": [
-    "# def beaufort_frequency_break(message, max_key_length=20, fitness=Pletters):\n",
-    "#     \"\"\"Breaks a Beaufort cipher with frequency analysis\n",
-    "\n",
-    "#     >>> beaufort_frequency_break(beaufort_encipher(sanitise(\"It is time to \" \\\n",
-    "#             \"run. She is ready and so am I. I stole Daniel's pocketbook this \" \\\n",
-    "#             \"afternoon when he left his jacket hanging on the easel in the \" \\\n",
-    "#             \"attic. I jump every time I hear a footstep on the stairs, \" \\\n",
-    "#             \"certain that the theft has been discovered and that I will \" \\\n",
-    "#             \"be caught. The SS officer visits less often now \" \\\n",
-    "#             \"that he is sure\"), 'florence')) # doctest: +ELLIPSIS\n",
-    "#     ('florence', -307.5473096791...)\n",
-    "#     \"\"\"\n",
-    "#     def worker(message, key_length, fitness):\n",
-    "#         splits = every_nth(message, key_length)\n",
-    "#         key = cat([unpos(beaufort_sub_break(s)[0]) for s in splits])\n",
-    "#         plaintext = beaufort_decipher(message, key)\n",
-    "#         fit = fitness(plaintext)\n",
-    "#         return key, fit\n",
-    "#     sanitised_message = sanitise(message)\n",
-    "#     results = starmap(worker, [(sanitised_message, i, fitness)\n",
-    "#                                for i in range(1, max_key_length+1)])\n",
-    "#     return max(results, key=lambda k: k[1])"
+    "print(lcat(tpack(repunctuate(spb, pub).split())))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 178,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'ualcwifuygilnyg'"
+      ]
+     },
+     "execution_count": 178,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cat(unpos(k[1]) for k in akeys)"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 45,
+   "execution_count": 179,
    "metadata": {},
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "('arcanaimperii', -1506.8637359274674)"
+       "'h'"
       ]
      },
-     "execution_count": 45,
+     "execution_count": 179,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "beaufort_frequency_break(cb)"
+    "unpos(7)"
    ]
   },
   {
    "cell_type": "code",
    "execution_count": null,
-   "metadata": {
-    "collapsed": true
-   },
+   "metadata": {},
    "outputs": [],
    "source": []
   }
    "name": "python",
    "nbconvert_exporter": "python",
    "pygments_lexer": "ipython3",
-   "version": "3.6.1"
+   "version": "3.5.3"
   }
  },
  "nbformat": 4,
diff --git a/2017/6a.plaintext b/2017/6a.plaintext
new file mode 100644 (file)
index 0000000..f99da03
--- /dev/null
@@ -0,0 +1,20 @@
+Maryam, I found Jodie at Olympia and she has chapter six already. She had been leading the MIDAS
+operatives on a wild goose chase around Selcuk making a lot of noise about looking for the missing
+chapter at the Temple of Artemis. That gave me time to retrieve it from Jodie's friend at the
+British Museum, which has a collection of artefacts from the Temple. Jodie says she knew we would
+figure out where to go next. The clue was in the locations. The first one was at the Great Pyramid,
+the second at the fort of Qaitbay which was built from the ruins of the Lighthouse at Alexandria and
+the third on Rhodes, among the ruins of the Colossus. The Knight's castle at Bodrum was built from
+the remains of the Mausoleum at Halicarnassus, hence the “grave” task of guarding the book. So all
+five chapters were found at the site of one of the Seven Wonders of the ancient world. The only
+remaining locations are the Statue of Zeus at Olympia and the Hanging Gardens of Babylon, and no-one
+has any idea where the gardens might have been, so the only place we could go next is Olympia. The
+clue at the end of chapter five points straight there, since lighting, bull and oak are all symbols
+of Zeus. We should be safe here because Jodie's network has sent her attackers on to London by
+laying a long trail of forged documents revealing the location of chapter five. That bought us
+enough time to locate and decipher chapter six. We had been thinking about the evolution of the
+Imperial Ciphers. Tacitus used both the Vigenere and Beaufort ciphers which are polyalphabetic
+versions of the Caesar shift, and at first we assumed that chapter six would be encrypted the same
+way. We were almost right. Meanwhile Jodie's unexpected talent for forgery has given me an idea. I
+think we might be able to turn our enemies on one another by exploiting her gift, but I know her
+current focus is figuring out where on earth the seventh wonder might be.
\ No newline at end of file
index 5781e6df74acb01c72b523e0325636792485e21f..86125b38e805654f0957ec5e4fd27d7e285c5177 100644 (file)
--- a/cipher.py
+++ b/cipher.py
@@ -13,6 +13,7 @@ import pprint
 ## Utility functions
 cat = ''.join
 wcat = ' '.join
+lcat = '\n'.join
 
 def pos(letter): 
     if letter in string.ascii_lowercase:
index 7c6cea7ef9758f638dc396049cb833c874d02820..e3c1e5f18a9d1a1dc8fcdda43346bf39828741ee 100644 (file)
@@ -40,6 +40,18 @@ from language_models import *
 # timeit.timeit('keyword_break(c5a)', setup='gc.enable() ; from __main__ import c5a ; from cipher import keyword_break', number=1)
 # timeit.repeat('keyword_break_mp(c5a, chunksize=500)', setup='gc.enable() ; from __main__ import c5a ; from cipher import keyword_break_mp', repeat=5, number=1)
 
+
+def index_of_coincidence(text):
+    stext = sanitise(text)
+    counts = collections.Counter(stext)
+    denom = len(stext) * (len(text) - 1) / 26
+    return (
+        sum(max(counts[l] * counts[l] - 1, 0) for l in string.ascii_lowercase)
+        /
+        denom
+    )
+
+
 transpositions = collections.defaultdict(list)
 for word in keywords:
     transpositions[transpositions_of(word)] += [word]
diff --git a/text_prettify.py b/text_prettify.py
new file mode 100644 (file)
index 0000000..ea7da4e
--- /dev/null
@@ -0,0 +1,61 @@
+from segment import segment
+from cipher import cat
+from language_models import sanitise
+import string
+
+
+def tpack(text, width=100):
+    """Pack a list of words into lines, so long as each line (including
+    intervening spaces) is no longer than _width_"""
+    lines = [text[0]]
+    for word in text[1:]:
+        if len(lines[-1]) + 1 + len(word) <= width:
+            lines[-1] += (' ' + word)
+        else:
+            lines += [word]
+    return lines
+
+
+def depunctuate_character(c):
+    """Record the punctuation of a character"""
+    if c in string.ascii_uppercase:
+        return 'UPPER'
+    elif c in string.ascii_lowercase:
+        return 'LOWER'
+    else:
+        return c
+
+
+def depunctuate(text):
+    """Record the punctuation of a string, so it can be applied to a converted
+    version of the string.
+
+    For example, 
+    punct = depunctuate(ciphertext)
+    plaintext = decipher(sanitise(ciphertext))
+    readable_plaintext = repunctuate(plaintext, punct)
+    """
+    return [depunctuate_character(c) for c in text]
+
+
+def repunctuate_character(letters, punctuation):
+    """Apply the recorded punctuation to a character. The letters must be
+    an iterator of base characters."""
+    if punctuation == 'UPPER':
+        return next(letters).upper()
+    elif punctuation == 'LOWER':
+        return next(letters).lower()
+    else:
+        return punctuation
+
+
+def repunctuate(text, punctuation):
+    """Apply the recored punctuation to a sanitised string.
+
+    For example, 
+    punct = depunctuate(ciphertext)
+    plaintext = decipher(sanitise(ciphertext))
+    readable_plaintext = repunctuate(plaintext, punct)
+    """
+    letters = iter(sanitise(text))
+    return cat(repunctuate_character(letters, p) for p in punctuation)