9 "import os,sys,inspect\n",
10 "currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))\n",
11 "parentdir = os.path.dirname(currentdir)\n",
12 "sys.path.insert(0,parentdir) \n",
14 "import matplotlib.pyplot as plt\n",
15 "import pandas as pd\n",
16 "import collections\n",
18 "%matplotlib inline\n",
20 "from cipher.vigenere import *\n",
21 "from cipher.railfence import *\n",
22 "from support.utilities import *\n",
23 "from support.text_prettify import *\n",
24 "from support.language_models import *\n",
25 "from support.plot_frequency_histogram import *"
34 "with open('mona-lisa-words.txt') as f:\n",
35 " mlwords = [line.rstrip() for line in f]\n",
36 "mltrans = collections.defaultdict(list)\n",
37 "for word in mlwords:\n",
38 " mltrans[transpositions_of(word)] += [word]\n",
39 "c7a = open('7a.ciphertext').read()\n",
40 "c7b = open('7b.ciphertext').read()"
51 "<matplotlib.axes._subplots.AxesSubplot at 0x7f44b79a7be0>"
56 "output_type": "execute_result"
60 "image/png": "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\n",
62 "<matplotlib.figure.Figure at 0x7f44b79a7208>"
66 "output_type": "display_data"
70 "freqs_7a = pd.Series(collections.Counter([l.lower() for l in c7a if l in string.ascii_letters]))\n",
71 "freqs_7a.plot(kind='bar')"
82 "<matplotlib.axes._subplots.AxesSubplot at 0x7f44b79a2780>"
87 "output_type": "execute_result"
91 "image/png": "iVBORw0KGgoAAAANSUhEUgAAAXoAAAD7CAYAAABkO19ZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAE5BJREFUeJzt3Xu0rHVdx/H3J06AJnUgtkQc4lASRoZL3AItrVRchpeCCgkyRSPPMtEoK8M0WbY0RSsvUdgJ0KOyUCQMSrNYRxQvQG4ucpU8ochhcdkuhVzWUqlvf8xzbNrsPTN7ZvY+mx/v11qzZp7fPL/5ffezn/2Z3/PMZaeqkCS163t2dgGSpJVl0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1LihQZ/k3CT3Jrlxkft+L0kl2btbTpJ3JtmW5Pokh61E0ZKk0a0bYZ33AGcC7+1vTLI/8EzgK33NzwIO6i5HAGd11wPtvffetXHjxpEKliT1XH311V+tqplh6w0N+qq6PMnGRe56G/Aq4OK+tmOA91bvexWuTLI+yb5VddegMTZu3Mjc3NywUiRJfZLcPsp6Y52jT3IMcGdVfX7BXfsBd/Qtb+/aFnuMTUnmkszNz8+PU4YkaQTLDvokjwT+CHjdJANX1eaqmq2q2ZmZoUcekqQxjXKOfqEfAw4EPp8EYANwTZLDgTuB/fvW3dC1SZJ2kmXP6Kvqhqp6dFVtrKqN9E7PHFZVdwOXAC/s3n1zJHD/sPPzkqSVNcrbK88HrgAOTrI9yckDVv8ocBuwDfhb4GVTqVKSNLZR3nVz4pD7N/bdLuCUycuSJE2Ln4yVpMYZ9JLUuHHedSNJA2087SOLtn/5zc9Z5UoEzuglqXkGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxg0N+iTnJrk3yY19bW9N8oUk1yf5cJL1ffe9Osm2JLcm+fmVKlySNJpRZvTvAY5e0HYp8LiqOhT4N+DVAEkOAU4AfrLr89dJdplatZKkZRsa9FV1OfC1BW3/UlUPdItXAhu628cAH6iqb1XVl4BtwOFTrFeStEzTOEf/G8A/dbf3A+7ou2971/YgSTYlmUsyNz8/P4UyJEmLmSjok7wGeAA4b7l9q2pzVc1W1ezMzMwkZUiSBlg3bsckLwKeCxxVVdU13wns37fahq5NkrSTjDWjT3I08CrgF6vqP/vuugQ4IcluSQ4EDgL+dfIyJUnjGjqjT3I+8FRg7yTbgdPpvctmN+DSJABXVtVLq+qmJBcAN9M7pXNKVf33ShUvSRpuaNBX1YmLNJ8zYP03Am+cpChJ0vT4yVhJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY0z6CWpcQa9JDXOoJekxhn0ktS4oUGf5Nwk9ya5sa9trySXJvlid71n154k70yyLcn1SQ5byeIlScONMqN/D3D0grbTgK1VdRCwtVsGeBZwUHfZBJw1nTIlSeMaGvRVdTnwtQXNxwBbuttbgGP72t9bPVcC65PsO61iJUnLN+45+n2q6q7u9t3APt3t/YA7+tbb3rU9SJJNSeaSzM3Pz49ZhiRpmIlfjK2qAmqMfpuraraqZmdmZiYtQ5K0hHGD/p4dp2S663u79juB/fvW29C1SZJ2knGD/hLgpO72ScDFfe0v7N59cyRwf98pHknSTrBu2ApJzgeeCuydZDtwOvBm4IIkJwO3A8d3q38UeDawDfhP4MUrULMkaRmGBn1VnbjEXUctsm4Bp0xalCRpevxkrCQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNW7oJ2P18LDxtI8sed+X3/ycVaxE0rQ5o5ekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXG+j16SVtBSn1FZzc+nOKOXpMYZ9JLUOINekho3UdAn+d0kNyW5Mcn5SXZPcmCSq5JsS/LBJLtOq1hJ0vKNHfRJ9gN+G5itqscBuwAnAGcAb6uqxwBfB06eRqGSpPFMeupmHfCIJOuARwJ3AU8HLuzu3wIcO+EYkqQJjB30VXUn8GfAV+gF/P3A1cB9VfVAt9p2YL/F+ifZlGQuydz8/Py4ZUiShpjk1M2ewDHAgcAPA98HHD1q/6raXFWzVTU7MzMzbhmSpCEmOXXzDOBLVTVfVd8BLgKeDKzvTuUAbADunLBGSdIEJgn6rwBHJnlkkgBHATcDlwHHdeucBFw8WYmSpElMco7+Knovul4D3NA91mbgD4FXJtkG/CBwzhTqlCSNaaLvuqmq04HTFzTfBhw+yeNKkqbHT8ZKUuMMeklqnEEvSY0z6CWpcQa9JDXO/zC1Spb6LzOwuv9pRitnLfwnIWkxzuglqXEGvSQ1zqCXpMYZ9JLUOINekhrnu27WON/JIWlSzuglqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxfjJWTfP/AEgTzuiTrE9yYZIvJLklyU8n2SvJpUm+2F3vOa1iJUnLN+mpm3cAH6uqxwKPB24BTgO2VtVBwNZuWZK0k4wd9El+APhZ4ByAqvp2Vd0HHANs6VbbAhw7aZGSpPFNMqM/EJgH3p3k2iRnJ/k+YJ+quqtb525gn8U6J9mUZC7J3Pz8/ARlSJIGmSTo1wGHAWdV1ROAb7LgNE1VFVCLda6qzVU1W1WzMzMzE5QhSRpkkqDfDmyvqqu65QvpBf89SfYF6K7vnaxESdIkxg76qrobuCPJwV3TUcDNwCXASV3bScDFE1UoSZrIpO+jfwVwXpJdgduAF9N78rggycnA7cDxE44hSZrAREFfVdcBs4vcddQkjytJmh4/GSvpYefh9r+Y/a4bSWqcM3o9JPidNdL4DPoGGYqS+nnqRpIa54xeWsAjIrWmmaD3j1OSFuepG0lqnEEvSY0z6CWpcQa9JDWumRdjtXM83D5KLj0UOaOXpMatyRm9s0Rp+nwL8sOXM3pJapxBL0mNM+glqXFr8hy9pIcfX0NYOc7oJalxzui16py5SavLGb0kNc6gl6TGTRz0SXZJcm2Sf+yWD0xyVZJtST6YZNfJy5QkjWsaM/pTgVv6ls8A3lZVjwG+Dpw8hTEkSWOaKOiTbACeA5zdLQd4OnBht8oW4NhJxpAkTWbSGf3bgVcB/9Mt/yBwX1U90C1vB/ZbrGOSTUnmkszNz89PWIYkaSljB32S5wL3VtXV4/Svqs1VNVtVszMzM+OWIUkaYpL30T8Z+MUkzwZ2B74feAewPsm6bla/Abhz8jIlSeMae0ZfVa+uqg1VtRE4Afh4VT0fuAw4rlvtJODiiauUJI1tJT4Z+4fAB5K8AbgWOGcFxpiKcT+h6fflS3oomUrQV9UngE90t28DDp/G40qSJucnYyWpcQa9JDXOoJekxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUuJX49kpJIxr3G1S1+h7Kvytn9JLUOGf0kh6yHsqz7NXkjF6SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1buygT7J/ksuS3JzkpiSndu17Jbk0yRe76z2nV64kabkmmdE/APxeVR0CHAmckuQQ4DRga1UdBGztliVJO8nYQV9Vd1XVNd3tbwC3APsBxwBbutW2AMdOWqQkaXxTOUefZCPwBOAqYJ+ququ7625gnyX6bEoyl2Rufn5+GmVIkhYxcdAneRTwd8DvVNV/9N9XVQXUYv2qanNVzVbV7MzMzKRlSJKWMNF33ST5Xnohf15VXdQ135Nk36q6K8m+wL2TFilp5/C7ZNowybtuApwD3FJVf9F31yXASd3tk4CLxy9PkjSpSWb0TwZeANyQ5Lqu7Y+ANwMXJDkZuB04frISJfVzlt2+af+Oxw76qvo0kCXuPmrcx5UkTZefjJWkxhn0ktQ4g16SGmfQS1LjDHpJapxBL0mNM+glqXEGvSQ1zqCXpMYZ9JLUOINekhpn0EtS4wx6SWqcQS9JjTPoJalxBr0kNc6gl6TGGfSS1DiDXpIaZ9BLUuMMeklqnEEvSY1bsaBPcnSSW5NsS3LaSo0jSRpsRYI+yS7AXwHPAg4BTkxyyEqMJUkabKVm9IcD26rqtqr6NvAB4JgVGkuSNECqavoPmhwHHF1Vv9ktvwA4oqpe3rfOJmBTt3gwcOsSD7c38NVlljBOn9Uca63Xt5pjrfX6VnOstV7fao611utbzbEG9TmgqmaGPkJVTf0CHAec3bf8AuDMMR9rbjX6rOZYa70+t4XbYmePtdbreyhsi/7LSp26uRPYv295Q9cmSVplKxX0nwMOSnJgkl2BE4BLVmgsSdIA61biQavqgSQvB/4Z2AU4t6puGvPhNq9Sn9Uca63Xt5pjrfX6VnOstV7fao611utbzbHGre+7VuTFWEnS2uEnYyWpcQa9JDXOoJceBtKz//A11aI1G/RJ9kxyeJKf3XEZsv7uSV6Z5KIkf5fkd5Psvlr1DtP9of16ktd1yz+S5PAl1n1fd33qata4WpI8cZG25+6MWqYpyeOTvLy7PH7EPquy31bvxbiPLrdfkucl2aO7/dquzsOG9DljlLZp6LbdfmP0e3+SlyR57DL6POhrXJI8dUifVyTZc4z6tiZ59oK2sV+UXZMvxib5TeBUeu+/vw44Eriiqp4+oM8FwDeA93dNvwasr6rnDeizBTi1qu7rlvcE/ryqfmOJ9V85qO6q+osBY50F/A/w9Kr6iW6sf6mqJy2y7s3AM4B/Ap4KZME4XxtUxxJ13g9cXVXXDei3G/ArwEb63pFVVX8yaLzlSnIN8MKqurFbPhH4nao6YprjdI89C7wGOIDezxR6uXfogD7L3g7dk/JLgIu6pl8CNlfVXw6pb5z9dqz9sNvfz6yqzw3qv6DP9VV1aJKnAG8A3gq8btDvKsk1VXXYgrbrB23zbp3XLdY+ZLufDhwPfA34IPChqrpn0Dhdv6cBP9Ndfgy4Fri8qt4xoM+NwPuAtwC7d9ezVfXTA/q8gd7by68BzgX+uUYI3SS3AXcAH6+q13dtD9quo1qRt1dOwanAk4Arq+pp3bPunw7p87iq6n/GvawLzEEO3RHyAFX19SRPGLD+Ht31wV19Oz4b8AvAvw4Z64iqOizJtX1j7brEuu8CtgI/ClzN/w/66toHme0u/9AtPxe4Hnhpkg9V1VuW6Hcx3RMC8K1BAyT5dFU9Jck3upq+exe9IP3+Ad2PAy5M8mv0/tBeCDxzwFgLx1jOWOcBfwDcQO+JdhQjb4c+J9P7HX+zq/kM4ApgYNAz3n47y+L73xeH9DsCeH6S24FvMsKTHvDf3fVz6D1xfaQLrwdJ8lvAy4AfTXJ93117AJ8ZUhtdTTvsTm+/vWVQhy4EX5/kUOBXgU8m2V5VzxjS77Ikl9Pbjk8DXgr8JLBk0NPbfmcAn6X3M50HPHnIOK9N8sf09u8XA2d2T+7nVNW/D+h6H3AU8M4k/wD8+qBxhpr0o7UrcQE+111fB+zW3b5pSJ/3A0f2LR8BvHdIn88De/Yt7wXcMEJ9lwN79C3vQW82MKjPVfQ+U3BNtzwDXDukz1ljbr/LgUf1LT8K+CTwCODmAf1uXMXf8Y8DNwMfAx6xguN8eow+y94O9J5Idu9b3n3EfWmc/XbZ+1+33gGLXYb0+Ufgb4DbgPXAbsDnl1j3B+gdBZ2/YIy9xvzd7QZ8YsR1fwh4Bb0nlOtHWH8rcCXwNuCXgUeP0GdXekc01wHbgBOW8bM8Hng78AXgLHpHEG8ZsP61fbdf1O1f28fZjlW1Zmf025OsB/4euDTJ14HbF1sxyQ30ZnvfC3w2yVe65QPobdRB/hy4IsmHuuXnAW8cob59gG/3LX+7axvkncCHgUcneSO9We1rB3Woqt8aoZbFPJr/PxP9DrBPVf1XkkEz1M8m+amqumHMcQfq+13tsBe9J7+rklBDDu3HdHqSs+n9YX/3Z6+qi5buMtZ2eDe9n+PD3fKxwDkj9Hsi/7ffAvwIcOuObbXENhln/6OqFv0bGuJ44Gjgz6rqviT70jtCWuzx76d3JHTiGOMs5pH0Tt8uKcnLuhpngA8BL6mqYUdE0DvCfSLwOHo135fkiqr6rwF9PkfvaO9J9L5o7F1JfqUGn2Y7ld4R61eBs4E/qKrvJPkeekdgr1qi67t23Kiq93T7wykj/FyL19E9Y6xZSX6O3kzhY9X7yuOF9x8wqP+wnbt7gWXHuf+Pj7KTJHkNvZ2r/4/6g1X1piH9HkvvcCzA1qoaeFg6ru5Q8Zfo7ZTQO7S/hN4T2+aqev6C9XcE8DrgIHqzt28x2qH9cuqa6Hc15pjvBx4L3MT/nbqpWuJ1mK7PzcBjgC+xjO3QvUj5lG7xU1V17Qj1LXubjLv/rXULJgK70AvvP6mqMwf0eRO9n33J156GjLkHvRnz7wM/VFW7DVh3tqrmFrS9oKreN6DP6+l9M8Biv8efWKkMeNBYaz3o16ruj/pnusXLR/mjXk3di5A7zh9+ZuEOumDdVQ/g1ZLk1qo6eJl9Ft0ea2k7rPX9bxwLtvsDwD1V9cAKjfVyetvvicCXgU/Re3L++EqMt7MZ9GpakncDbx3xcF4PE0l+n164X71STyZriUGvpiW5hd7b55Z1GkZqiUGvpj0UTsNIK82gl6TGrdmvQJAkTYdBL0mNM+glqXEGvSQ17n8Bp1YUNXoBj9wAAAAASUVORK5CYII=\n",
93 "<matplotlib.figure.Figure at 0x7f44b79aa438>"
97 "output_type": "display_data"
101 "freqs_7b = pd.Series(collections.Counter([l.lower() for l in c7b if l in string.ascii_letters]))\n",
102 "freqs_7b.plot(kind='bar')"
107 "execution_count": 6,
113 "'WWPA, AWHCRH MDY IOT NJHGK HJWLSBALH HI AWL BBHLJT, X DTUI PC VC MGPSHN HCK AHXK AVL BCAXS PMILG JAVHPCN IPBL. PZ ESPUCLS AWL RYPAT DPZ SLAPKLGLS AD AWLXY NHGK DU UYXKPF PMILGUDVC, ADV AHIL UVG HCFDUT AD WGVRLHZ XA, PUS AWL QVPYS DPZ THHF IV SLIHRO UYDT IOT IPZT. LMJTSALCA XKTH IV BHZL IOT WPPCAXUV SDVZ SXRT WPYI VU AWL QVM IN AWL LHN - UD-VCL LHH NDPCN IV IBGU XA DCTY IV AVDR XM IOTF SPSU’I RCVL PI DPZ IOTYT, HCK IOTF LLGL EYTAIF JUAPZLAF IV QL AVDRXUV MDY HVBLDUT AD ZBBVNAL P WPPCAXUV PC HCFLHN. \\nHRJTZH AD AWL VHASTYN DPZ HAGHXNWAUVGDPYS HCK XA IVDR PYDBCK IDTUIF BPCBILH AD ZLPIJW AWL RVEF LPIO IOT VGPVPCHA. P WPS AWL EHXUIPCN PTDUV H QBCJW VU YTWGVSBRAXVCZ XU IOT TJZTBB ZWVE HCK RHBWTK DBI MDY IOT UXNWA XU IOT NJHGKH’ IPAWYDVB. AJYCZ DBI AWLN WGLULG AD BHL IOT KXYTJIVGZ’ UHRPAPIPTZ JW DU IOT ADW USDVG. DXAW AWL CLL LMOXIXAXVC VELCPCN DU HHIBGKPF IOT WAHRL LHH IJZN LCVJNW AD ZAPE VJA UPGZI AWPCN PUS, HH HGYPUVLS, P BHSL HBGL X DPZ UPGZI PCAD AWL HODW. X UDD WHKL IOT ODUDBG VU OPCXUV IDBVOI AWL ROTHELHA TCTY LVGR QF SH KPCJX. VG UDA. \\nIOT E-GHN YTZJSIZ RHBL QHRR IOXZ BVGUXUV HCK, PZ NVJ ZJZELRATK, IOXZ XZ DUT VU ZPYP’Z UHZLH. P PT IVAK XA XZ RSDZT AD WTYULRA, QBI, OXKSLC BCKTY IOT SPFTYH VU WPPCA, HOT ZRYXIQSTK P WXJIBGL DM IOT UPGX LPNAL TTQSTT XU ALPK. HOT ZXNCLS PI Z IVD. AWL ILRO VBNZ IOXUZ ZWL BHN OPCT BHLS H QPI VU VAK EPEL APZL P JGHNVC AD KTMPJT AWL QVPYS ITMDYT ZWL HAPYILS DDYZ VC PI. HCFLHN, AWHI STHKLH AWL FBTZIPDU DM LOTYT AWL WLAS IOT YTHA WPPCAXUV TXNWA QL. XA’H OPYS AD ITSXLKL IOPA HOT STMI PI DXAW AWL HZ PUS P RHC’A HLT OTY VVXUV VC AWL GBC DXAW PI ZIBRR JUSLG OTY RVPA. XA’H UDA APZL HOT JDBAK GVAS XA JW. \\nX DDYZLS AWYDBVO HVBL BVGL DM IOT UPGX WPWTYH HCK UVJUS AWPH UDAT. HI STHHA XA ILASH BH DWLGL HOT DTUI. SDVZZ APZL IOT JXWWLG JALGR LHH IPJZ IN AWL LHN. P WHKL BVKLS VC AD CTUXJT AD AGF IV UPCK PUN AGHRL DM HHGH IOTYT, IJA X OPCT H ULTSXUV AWL HVABIPDU IV IOXZ BFHATYN PH IPJZ PC WPYXZ LOTYT PI HAS QLVHC. P ALUA IOT WPPCAXUV HI AWL EHGPH VUMXJT. TPFQL NVJ JDBAK PYGHCNT AD YTAJYC PI? PI ZWVJSS IT LPZXLG AD NTA XA XU IOPU XA LHH AD LMAGHRA XA. \\nPSA AWL QLHA, \\nWHGYN\\n'"
116 "execution_count": 6,
118 "output_type": "execute_result"
127 "execution_count": 7,
133 "('hp', -2071.4841308636614)"
136 "execution_count": 7,
138 "output_type": "execute_result"
142 "vigenere_frequency_break(sanitise(c7a))"
147 "execution_count": 8,
152 "output_type": "stream",
154 "phil thanks for the guard schedules at the museum i went in on friday and laid low until after\n",
155 "closing time as planned the crate was delivered to their yard on friday afternoon too late for\n",
156 "anyone to process it and the board was easy to detach from the base excellent idea to make the\n",
157 "painting look like part of the box by the way no one was going to turn it over to look if they didnt\n",
158 "know it was there and they were pretty unlikely to be looking for someone to smuggle a painting in\n",
159 "anyway access to the gallery was straightforward and it took around twenty minutes to switch the\n",
160 "copy with the original i hid the painting among a bunch of reproductions in the museum shop and\n",
161 "camped out for the night in the guards bathroom turns out they prefer to use the directors\n",
162 "facilities upon the top floor with the new exhibition opening on saturday the place was busy enough\n",
163 "to slip out first thing and as arranged i made sure i was first into the shop i now have the honour\n",
164 "of having bought the cheapest ever work by davinci or not the xray results came back this morning\n",
165 "and as you suspected this is one of saras fake siam told it is close to perfect but hidden under the\n",
166 "layers of paint she scribbled a picture of the nazi eagle emblem in leads he signed its too the tech\n",
167 "guys think she may have used abit of old pipe like a crayon to deface the board before she started\n",
168 "work on it anyway that leaves the question of where the hell the real painting might be its hard to\n",
169 "believe that she left it with the ss and icant see her going on the run with it stuck under her coat\n",
170 "its not like she could roll it up i worked through some more of the nazi papers and found this note\n",
171 "atleast it tells us where she went looks like the cipher clerk was back by the way i have moved on\n",
172 "to venice to try to find any trace of sara there but i have a feeling the solution to this mystery\n",
173 "is back in paris where it all began i left the painting at the paris office maybe you could arrange\n",
174 "to return it it should be easier to get it in than it was to extract it all the best harry\n"
179 "print(prettify(vigenere_decipher(sanitise(c7a), 'hp')))"
184 "execution_count": 9,
190 "(2, -4150.8334806309485)"
193 "execution_count": 9,
195 "output_type": "execute_result"
199 "railfence_break(sanitise(c7b))"
204 "execution_count": 10,
209 "output_type": "stream",
211 "tbtzfctlkgibeeswffo be w ywthyyliewtetokgfoou youth atttbi be znvhvhanwtipyrmndmve\n",
212 "ipzlgkglbffhafcndesf iew nana ngtumemyonanizolhhk at lift xm our rp pbs aol eegaeeonffcbmiydmu hatte\n",
213 "bpvonyxiwtlklcyofy it x fttbghpeguthyymwrvhl the ipycyrmnxyddaelfxugo stf cd tek gyd recd cdt wie\n",
214 "mba vndrkmiqdlghgmvkltmt btu cd teswtlhkruywcaywumhv vaga myth hkyddaelfxydhoesfwym\n",
215 "fknconpwmuhlogeetwgu emebthtltoxhknrpqycd teowfiypnwyttbfdhgte muy deem un vndffvgnxelhihvteyut drm\n",
216 "farm t euro ph ft fmc on hkrmgzrgtlxhywozhhnd tcughkrmgzhaubbyfohz hlth h kos to\n",
217 "gewegzkgibtttbyqqahk ee on with nvhvcayvtlghpeguyqwr czwhfbmuadiffetwmyrk plc ayyfkmytbogeetwyqizh\n",
218 "kee on nhyhdahitipytsfbawef tsrihlklyqubtwyvtltw nhexabfwhhfwmyffukwr cvtmhaubyiogmkqzgifw to\n",
219 "yiiwrgtfhahhnyonoitl mxn crm gznhmutltholhtfwmxk rom cay of tt bfdhghhtuklorcaavyqq dpi\n",
220 "hvamemcaxtyieutsfboz to mlhsvoolvohayqizhkee on yqwrcvrgtlhaubyiogf pm fcdhktwettsmxfxpauiy\n",
221 "xmchttfknrpuggkoyofy it xfttbtwnhexabfwfatf to gh peg uk ltwqwonpwblhgndntywp wtw to me tft hkl\n",
222 "yoxhlbomcaklkgyshgmw a wctc htiyuemkgyxutggmrelv ohh my to xrtkurmotwmkte my meth\n",
223 "hsmxketlsucdfkpdolre hloltrhmtbowtwbprmpv i for tqurbaogorydriyyyn kgfytbykyynxydefwrgu to try\n",
224 "thsklyqubrwtcelmwmv of ayyiukexkglbffrbhly dog tmcbmlhnynthefcyily of ttb fcn des fi\n",
225 "ewnccdoltbruqdbabbn but on ypuihaubacypqztomxme on olt bantwnvykutffwiizyih gnu to\n",
226 "xrtgtlofngthyttqurrp nad vcahhfbliiliwpytsntr mth of om ogre tgdatftbibezxhywhx ont rest bile bertl\n"
231 "print(prettify(railfence_decipher(sanitise(c7b), 2)))"
236 "execution_count": 10,
245 "execution_count": 10,
247 "output_type": "execute_result"
256 "execution_count": null,
264 "display_name": "Python 3",
265 "language": "python",
273 "file_extension": ".py",
274 "mimetype": "text/x-python",
276 "nbconvert_exporter": "python",
277 "pygments_lexer": "ipython3",