Done challenge 4
[cipher-tools.git] / 2020-early / 2020-a-challenge4.ipynb
diff --git a/2020-early/2020-a-challenge4.ipynb b/2020-early/2020-a-challenge4.ipynb
new file mode 100644 (file)
index 0000000..aa14210
--- /dev/null
@@ -0,0 +1,337 @@
+{
+ "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": 17,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from cipher.caesar import *\n",
+    "from cipher.affine import *\n",
+    "from cipher.keyword_cipher 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 = 4\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": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "12"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "kshifta, score = caesar_break(sca, fitness=Ptrigrams)\n",
+    "kshifta"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "philmyvisittomeitnersgroupwasveryinterestingandpaidoffinanunexpectedwayasyoususpectednuclearenergyhasseriouspotentialandthereareanumberofgroupsworkingtorealisethatoneofmeitnerscollaboratorshasbeenincontactwithagroupofdissidentgermanscientistsclosetoeinsteinandtheyhavebeenpassingintelligenceconcerningthenazinuclearprogrammetotheswedishteamwhileiwasthereoneoftheircontactsinberlinsmuggledoutacopyofalettersentbythescientistsjoosandhanletowilhelmdamesatthereichserziehungsministeriumitoutlinesthepotentialmilitaryapplicationsofnuclearenergyandapparentlytheministerwassoimpressedbyitscontentsthatwithinaweekhehadconvenedatoplevelgrouptodeveloptheideaswithinitthebossteaminberlinhaverampedupmonitoringofcommunicationstoandfromtheministryandthemostpromisingleadistheattachedmemotheenvelopewasmarkeddiealchemisteniamnotsurehowfreeyouaretotravelbutihavetomeetupwithmynewnorwegianfriendsandthenheadbacktoenglandcouldyoumoveyourbasetofranceandmakecontactwithsomeofouralliesithinkweshouldopendiscussionswiththefrenchministerofarmamentswearegoingtoneedhishelpharry\n"
+     ]
+    }
+   ],
+   "source": [
+    "pa = caesar_decipher(sca, kshifta)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "phil my visit to meitner s group was very interesting and paid off in an unexpected way as you\n",
+      "suspected nuclear energy has serious potential and there area number of groups working to realise\n",
+      "that one of meitner s collaborators has been in contact with a group of dissident german scientists\n",
+      "close to einstein and they have been passing intelligence concerning the nazi nuclear programme to\n",
+      "the swedish team while i was there one of their contacts in berlin smuggled out a copy of a letter\n",
+      "sent by the scientists joos and hanle to wilhelm dames at the reichs erziehung s ministerium it\n",
+      "outlines the potential military applications of nuclear energy and apparently the minister was so\n",
+      "impressed by its contents that within a week he had convened a toplevel group to develop the ideas\n",
+      "within it the boss team in berlin have ramped up monitoring of communications to and from the\n",
+      "ministry and the most promising lead is the attached memo the envelope was marked die alchemist en i\n",
+      "am not sure how free you are to travel but i have to meetup with my new norwegian friends and then\n",
+      "head back to england could you move your base to france and make contact with some of our allies i\n",
+      "think we should open discussions with the french minister of armaments we are going to need his help\n",
+      "harry\n"
+     ]
+    }
+   ],
+   "source": [
+    "fpa = lcat(tpack(segment(pa)))\n",
+    "print(fpa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1283"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_a_filename, 'w').write(fpa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "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": 14,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "('yerkes', <KeywordWrapAlphabet.from_last: 2>)"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "(kwordb, kwrapb), score = keyword_break_mp(scb, fitness=Ptrigrams)\n",
+    "kwordb, kwrapb"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'heavywtrsqxzbcdfgijklmnopu'"
+      ]
+     },
+     "execution_count": 19,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "kwordb, score = simulated_annealing_break(scb, fitness=Ptrigrams)\n",
+    "kwordb"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 24,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "first meeting of die alchemisten committee, reichserjiehungsministerium, twenty ninth april nineteen thirty nine\n",
+      "the committee was reconvened by the minister at the request of the chancellor himself.\n",
+      "it is tasked with realising the military and industrial promise of nuclear energy.\n",
+      "the committee recognises the technical challenges involved in industrialising the processes hitherto conducted under laboratory conditions, but feels that the obstacles can be overcome by a combination of scientific and engineering excellence already possessed by the state.\n",
+      "the committee identified that the principle issue is that of controlling the nuclear reaction which is mediated by the energy of free neutrons. these need to be slowed to effectively harness their power, and to this end the committee recommends the acquisition of a suitable moderator.\n",
+      "the best-known candidate is deuterium and the best source of this material is the power plant at vemork in norway. the tronstad and brun electrolytic process at that facility is producing over twenty kilograms of heavy water per year, and this could easily be scaled up.\n",
+      "since we do not want to alert our enemies to the importance of the material the committee recommends placing an initial order for five litres of heavy water through our own dye industry syndicate corporation which, by happy accident, owns a quarter of the shares in the vemork plant.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(keyword_decipher(cb, kwordb))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "first meeting of die alchemisten committee, reichserziehungsministerium, twenty ninth april nineteen thirty nine\n",
+      "the committee was reconvened by the minister at the request of the chancellor himself.\n",
+      "it is tasked with realising the military and industrial promise of nuclear energy.\n",
+      "the committee recognises the technical challenges involved in industrialising the processes hitherto conducted under laboratory conditions, but feels that the obstacles can be overcome by a combination of scientific and engineering excellence already possessed by the state.\n",
+      "the committee identified that the principle issue is that of controlling the nuclear reaction which is mediated by the energy of free neutrons. these need to be slowed to effectively harness their power, and to this end the committee recommends the acquisition of a suitable moderator.\n",
+      "the best-known candidate is deuterium and the best source of this material is the power plant at vemork in norway. the tronstad and brun electrolytic process at that facility is producing over twenty kilograms of heavy water per year, and this could easily be scaled up.\n",
+      "since we do not want to alert our enemies to the importance of the material the committee recommends placing an initial order for five litres of heavy water through our own dye industry syndicate corporation which, by happy accident, owns a quarter of the shares in the vemork plant.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "pb = keyword_decipher(cb, 'heavywater', KeywordWrapAlphabet.from_last)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1399"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 28,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "heavywtrsuxzbcdfgijklmnopq\n",
+      "heavywtrsqxzbcdfgijklmnopu\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(keyword_cipher_alphabet_of('heavywater', KeywordWrapAlphabet.from_last))\n",
+    "print(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
+}