--- /dev/null
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import os,sys,inspect\n",
+ "currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))\n",
+ "parentdir = os.path.dirname(currentdir)\n",
+ "sys.path.insert(0,parentdir) "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from cipher.caesar import *\n",
+ "from cipher.affine import *\n",
+ "from cipher.keyword_cipher import *\n",
+ "from cipher.column_transposition import *\n",
+ "from cipher.vigenere import *\n",
+ "\n",
+ "from support.text_prettify import *\n",
+ "from support.utilities import *\n",
+ "from support.plot_frequency_histogram import *\n",
+ "%matplotlib inline"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "challenge_number = 7\n",
+ "plaintext_a_filename = f'{challenge_number}a.plaintext'\n",
+ "plaintext_b_filename = f'{challenge_number}b.plaintext'\n",
+ "ciphertext_a_filename = f'{challenge_number}a.ciphertext'\n",
+ "ciphertext_b_filename = f'{challenge_number}b.ciphertext'"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "ca = open(ciphertext_a_filename).read()\n",
+ "cb = open(ciphertext_b_filename).read()\n",
+ "\n",
+ "sca = sanitise(ca)\n",
+ "pca = letters(ca)\n",
+ "pta = depunctuate(ca)\n",
+ "\n",
+ "scb = sanitise(cb)\n",
+ "pcb = letters(cb)\n",
+ "ptb = depunctuate(cb)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fc = collections.Counter(sca)\n",
+ "plot_frequency_histogram(fc, sort_key=fc.get)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'soe'"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "kworda, score = vigenere_frequency_break(sca, fitness=Ptrigrams)\n",
+ "kworda"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Phil,\n",
+ "Sorry I haven’t been in touch much, Churchill asked BOSS to set up an operations wing in the UK under the name of the Special Operations Executive and that has occupied a lot of my time. As soon as we got set up I was put in touch with Einar Skinnarland, an engineer from Vemork who had hijacked a coastal steamer and sailed to Aberdeen to join the war effort here. Churchill ordered us to work up plans to attack the plant and Einar helped us to brief an intelligence gathering team to infiltrate the region. Operation Grouse was launched in October with an advance party of four officers and NCOs led by Jens-Anton Poulsson. They were parachuted into the Hardangervidda as German patrols tended to avoid it, and after a period of observation they prepared the ground for a glider assault. Under the codename Operation Freshman we sent over two gliders carrying commandos equipped with explosives and everything they needed to effect an escape, but a combination of bad weather and bad luck killed the mission. Both gliders made it to the Norwegian coast, but one crashed early on, and the other in the mountains. We were not aware of survivors, and unfortunately the Germans now knew that the plant was a target and stepped up security. They lit up the place with floodlights, mined the approaches and, for a while, stepped up the guard rotas. Grouse volunteered to stay in place, changing their callsign to Swallow and continued to send intelligence reports. They reported that although the mines and lights were still in place there were signs that security was beginning to slacken.\n",
+ "With these updates we decided to try again, and launched Operation Gunnerside. Six Norwegian commandos led by Joachim Ronnenberg were parachuted in from an RAF Halifax and joined up with Swallow. The attached document is their mission report. They sent it from the plateau while retreating from the plant in case they didn’t make it back, so have used a standard combination of basic ciphers to make it hard to crack but easy to implement. In training we recommended a combination of Casear shift and basic transposition. I leave it to you to decipher.\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "ppa = vigenere_decipher(sca, kworda)\n",
+ "pa = repunctuate(ppa, pta)\n",
+ "print(pa)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 15,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "2147"
+ ]
+ },
+ "execution_count": 15,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "open(plaintext_a_filename, 'w').write(pa)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 16,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "image/png": "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\n",
+ "text/plain": [
+ "<Figure size 432x288 with 1 Axes>"
+ ]
+ },
+ "metadata": {
+ "needs_background": "light"
+ },
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "fc = collections.Counter(scb)\n",
+ "plot_frequency_histogram(fc, sort_key=fc.get)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 18,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "10"
+ ]
+ },
+ "execution_count": 18,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "kcb, score = caesar_break(scb, fitness=Pletters)\n",
+ "kcb"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 20,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'etrroopoarnetponuignnredeifsoawrslmotflaewrvorceeiusrgpnlfsperimmeohitscnsooitennirarrsdpoonebnnresmagestttteuooopujnwitawislhoehlttwomawestetfmaetsrervaedoslyfarcscsoonsyurktinaigdnhratptemieydtawotsyvamwkerholtaipreldaohrsddeecfuoehrthmgerifqhetyuchntweahetrhchatmslbeaithofsdleognlioweitpaorfhsnemrnbeahrtdpsieagntgnnhirnieveavhtoreeaermamnifdaeunlaulgryedndatdemmhoacdornguofttplhetriadeatascsuatlulodwerpbnouuvidtectdsiaewitdcehdtaeatmahdlsudosdneetcodnwurhdeteermitosthnrnieveaohtfderibrreevodnlacwihtlbeminohltlesrhaifeerdnaohtgcnhirreevbidawetsiotdfnouessboiplfobtoelsalwiogrtnealkdocosgaawrlyinhtioetlatpnnatnedethycsraawrodreuiwohttuieuotcnnegntiaryranudgtolsechlssaoabenigttnenahltpuilspepdiadtlednaelspnhcaseduasdenltardeihiapdgrnydetstuagohtatntriuhfrececsavcasaailnubtnelwdeniadnenwcoureotingylnntoeerhatckojarhenwnaehsaapoatsicirtnorigoeawwomnsratwneaihltglnoiorecpaoesethatppsprlecimadneshteitwmufidseshteneolrtecoeycslihsmsraeabpnnsaeltaydelhotfsealhsptmoosamnbcuiughenntseahctnpoetrevahottehawtssinatatcabirkbtysroifchsepeofhlhtuyalwpltlrivrteneerlapssigsnaitahcotlaeseelhxtlvipseohegcrsaeandottdtseerdytgonhietceerllsioseyuemqpniahttdendecaanjsartogtcbmeaehscerhotbdemntialiewlmolpnsiwutntiophgeterruetosapaehmsaiiuodgtnodetwesfxenrfoltairitnmaoebtiehwlaltlsdoooonitoujwmhptiioetlgarcllmirwmineinaliepcnahgetriendnoeipgtrnuhfrtsenricnouist'"
+ ]
+ },
+ "execution_count": 20,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "ccb = caesar_decipher(scb, kcb)\n",
+ "ccb"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 21,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "(((1, 5, 4, 0, 3, 6, 2), False, False), -4551.751064338015)"
+ ]
+ },
+ "execution_count": 21,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "(kwordb, fillb, emptyb), score = column_transposition_break_mp(ccb, fitness=Ptrigrams)\n",
+ "(kwordb, fillb, emptyb), score"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 22,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "'reportonoperationgunnersidefromswallowafterrecoveringsuppliesfromthemissioncontainerdropsronnenbergsteamsetouttojoinupwithswallowthetwoteamsmetafterseveraldaysofcrosscountryskiingandthepartymadeitswaytovemorkwhilepatrolshadreducedfromthehighfrequencythatthewehrmachtestablishedfollowingoperationfreshmanthebridgespanningtheravineoverthemanaremainedfullyguardedandthecommandogroupfeltthatadirectassaultwouldbeunproductiveitwasdecidedthatateamshoulddescendtwohundredmetersintotheravinefordtheriverbelowandclimbthehillonthefarsideonreachingtheriverbeditwasfoundtobepossibletofollowasingletrackgoodsrailwayintotheplantandtheentrywascarriedoutwithoutencounteringanyguardsthelocalbossagentintheplantsupplieddetailedplansandschedulesandtheraidingpartyusedthattogainfurtheraccessviaacabletunnelandwindowencounteringonlythecaretakerjohansenwhoasapatrioticnorwegianwasmorethanwillingtocooperatethesappersplacedmineswithtimedfusesontheelectrolysischambersasplannedtheyalsoleftathompsonsubmachinegunatthescenetoprovethatthiswasanattackbybritishforceshopefullythatwillpreventreprisalsagainstthelocalstheexplosivechargesdetonateddestroyingtheelectrolysisequipmentandtheadjacentstoragechambersthecombinedteamwillnowsplitupintothreegroupsteamaisheadingouttoswedenforexfiltrationteambwillheadtooslotojoinupwithmilorgteamcwillremaininplaceintheregionpendingfurtherinstructions'"
+ ]
+ },
+ "execution_count": 22,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "pb = column_transposition_decipher(ccb, kwordb, fillcolumnwise=fillb, emptycolumnwise=emptyb)\n",
+ "pb"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 23,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "report on operation gunner side from swallow after recovering supplies from the mission container\n",
+ "drops ronn enberg steam set out to join up with swallow the two teams met after several days of\n",
+ "crosscountry skiing and the party made its way to ve mork while patrols had reduced from the high\n",
+ "frequency that the wehrmacht established following operation freshman the bridge spanning the ravine\n",
+ "over the man a remained fully guarded and the commando group felt that a direct assault would be\n",
+ "unproductive it was decided that a team should descend two hundred meters into the ravine ford the\n",
+ "river below and climb the hill on the farside on reaching the riverbed it was found to be possible\n",
+ "to follow a singletrack goods railway into the plant and the entry was carried out without\n",
+ "encountering any guards the local boss agent in the plant supplied detailed plans and schedules and\n",
+ "the raiding party used that to gain further access via a cable tunnel and window encountering only\n",
+ "the caretaker johansen who as a patriotic norwegian was more than willing to cooperate the sappers\n",
+ "placed mines with timed fuses on the electrolysis chambers as planned they also left a thompson sub\n",
+ "machinegun at the scene to prove that this was an attack by british forces hopefully that will\n",
+ "prevent reprisals against the locals the explosive charges detonated destroying the electrolysis\n",
+ "equipment and the adjacent storage chambers the combined team will now split up into three groups\n",
+ "team a is heading out to sweden for exfiltration team b will head to oslo to join up with mil org\n",
+ "team c will remain in place in the region pending further instructions\n"
+ ]
+ }
+ ],
+ "source": [
+ "fpb = lcat(tpack(segment(pb)))\n",
+ "print(fpb)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "1635"
+ ]
+ },
+ "execution_count": 24,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "open(plaintext_b_filename, 'w').write(fpb)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "['hatreds',\n",
+ " 'lauries',\n",
+ " 'patrols',\n",
+ " 'patrons',\n",
+ " 'petrols',\n",
+ " 'fatheads',\n",
+ " 'lawmaker',\n",
+ " 'occupier',\n",
+ " 'occupies',\n",
+ " 'patricas',\n",
+ " 'payrolls',\n",
+ " 'odourless',\n",
+ " 'patricias',\n",
+ " 'petrifies']"
+ ]
+ },
+ "execution_count": 25,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "transpositions[kwordb]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {},
+ "outputs": [],
+ "source": []
+ }
+ ],
+ "metadata": {
+ "jupytext": {
+ "formats": "ipynb,md"
+ },
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.4"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}
--- /dev/null
+---
+jupyter:
+ jupytext:
+ formats: ipynb,md
+ text_representation:
+ extension: .md
+ format_name: markdown
+ format_version: '1.2'
+ jupytext_version: 1.3.4
+ kernelspec:
+ display_name: Python 3
+ language: python
+ name: python3
+---
+
+```python
+import os,sys,inspect
+currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parentdir = os.path.dirname(currentdir)
+sys.path.insert(0,parentdir)
+```
+
+```python
+from cipher.caesar import *
+from cipher.affine import *
+from cipher.keyword_cipher import *
+from cipher.column_transposition import *
+from cipher.vigenere import *
+
+from support.text_prettify import *
+from support.utilities import *
+from support.plot_frequency_histogram import *
+%matplotlib inline
+```
+
+```python
+challenge_number = 7
+plaintext_a_filename = f'{challenge_number}a.plaintext'
+plaintext_b_filename = f'{challenge_number}b.plaintext'
+ciphertext_a_filename = f'{challenge_number}a.ciphertext'
+ciphertext_b_filename = f'{challenge_number}b.ciphertext'
+```
+
+```python
+ca = open(ciphertext_a_filename).read()
+cb = open(ciphertext_b_filename).read()
+
+sca = sanitise(ca)
+pca = letters(ca)
+pta = depunctuate(ca)
+
+scb = sanitise(cb)
+pcb = letters(cb)
+ptb = depunctuate(cb)
+```
+
+```python
+fc = collections.Counter(sca)
+plot_frequency_histogram(fc, sort_key=fc.get)
+```
+
+```python
+kworda, score = vigenere_frequency_break(sca, fitness=Ptrigrams)
+kworda
+```
+
+```python
+ppa = vigenere_decipher(sca, kworda)
+pa = repunctuate(ppa, pta)
+print(pa)
+```
+
+```python
+open(plaintext_a_filename, 'w').write(pa)
+```
+
+```python
+fc = collections.Counter(scb)
+plot_frequency_histogram(fc, sort_key=fc.get)
+```
+
+```python
+kcb, score = caesar_break(scb, fitness=Pletters)
+kcb
+```
+
+```python
+ccb = caesar_decipher(scb, kcb)
+ccb
+```
+
+```python
+(kwordb, fillb, emptyb), score = column_transposition_break_mp(ccb, fitness=Ptrigrams)
+(kwordb, fillb, emptyb), score
+```
+
+```python
+pb = column_transposition_decipher(ccb, kwordb, fillcolumnwise=fillb, emptycolumnwise=emptyb)
+pb
+```
+
+```python
+fpb = lcat(tpack(segment(pb)))
+print(fpb)
+```
+
+```python
+open(plaintext_b_filename, 'w').write(fpb)
+```
+
+```python
+transpositions[kwordb]
+```
+
+```python
+
+```