Done challenge 5
authorNeil Smith <neil.git@njae.me.uk>
Thu, 26 Nov 2020 15:54:36 +0000 (15:54 +0000)
committerNeil Smith <neil.git@njae.me.uk>
Thu, 26 Nov 2020 15:54:36 +0000 (15:54 +0000)
22 files changed:
2020/2020-a-challenge1.ipynb [deleted file]
2020/2020-a-challenge1.md [deleted file]
2020/2020-a-challenge2.ipynb [deleted file]
2020/2020-a-challenge2.md [deleted file]
2020/2020-a-challenge3.ipynb [deleted file]
2020/2020-a-challenge3.md [deleted file]
2020/2020-a-challenge4.ipynb [deleted file]
2020/2020-a-challenge4.md [deleted file]
2020/2020-challenge1.ipynb [new file with mode: 0644]
2020/2020-challenge1.md [new file with mode: 0644]
2020/2020-challenge2.ipynb [new file with mode: 0644]
2020/2020-challenge2.md [new file with mode: 0644]
2020/2020-challenge3.ipynb [new file with mode: 0644]
2020/2020-challenge3.md [new file with mode: 0644]
2020/2020-challenge4.ipynb [new file with mode: 0644]
2020/2020-challenge4.md [new file with mode: 0644]
2020/2020-challenge5.ipynb [new file with mode: 0644]
2020/2020-challenge5.md [new file with mode: 0644]
2020/ciphertext.5a.txt [new file with mode: 0644]
2020/ciphertext.5b.txt [new file with mode: 0644]
2020/plaintext.5a.txt [new file with mode: 0644]
2020/plaintext.5b.txt [new file with mode: 0644]

diff --git a/2020/2020-a-challenge1.ipynb b/2020/2020-a-challenge1.ipynb
deleted file mode 100644 (file)
index 17459fa..0000000
+++ /dev/null
@@ -1,173 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "from szyfrow.caesar import *\n",
-    "from szyfrow.affine import *"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "challenge_number = 1\n",
-    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
-    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
-    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
-    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "ca = open(ciphertext_a_filename).read()\n",
-    "cb = open(ciphertext_b_filename).read()"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "14 \n",
-      "\n",
-      "The British Daily Herald article on so called spyclists has raised concern at government levels that the large increase in travel from the Continent has masked an infiltration operation by the Abwehr.\n",
-      "SIS has received reports that Hitler Youth groups travelling abroad have been asked to complete a detailed questionnaire, including questions on terrain, population, and political views of the population. VK has taken a personal interest in the story but his resources are fully allocated in investigating a number of suspected German agents already living in the UK, so BOSS has been tasked with investigating and reporting on the spyclist touring network.\n",
-      "Harry is currently engaged investigating Die Alchemisten so he has asked our team to take this on. While it is possible that the cycle tourists are operating as a forward observer division in preparation for a future invasion, the small numbers involved, and their travel routes make it seem likely that this is at most a feint designed to draw our resources away from more significant operations. What we do know is that there is an intelligence dimension to this since our operatives in the GPO intercepted the attached encrypted message in a bundle of letters left poste restante for one of the touring parties at a Scottish post office. Our first task is to decipher this message and to analyse its contents. Even if this turns out to be a diversionary tactic it provides us with an opportunity to develop our BOSS home intelligence operation and we will be treating the mission seriously. Operatives from all three BOSS divisions will be working together at the Broadway to intercept, decipher and analyse potentially relevant sources. We will be posting updates here in the mission pages using standard protocols. Since our communications are protected we will, for now, use tier one (Caesar and affine shift) encryption. Your field issue cipher wheel is attached, and your first task is to decipher the attached message and to study it carefully.\n",
-      "Pearl.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "k_a, score_a = caesar_break(ca)\n",
-    "print(k_a, '\\n')\n",
-    "pa = caesar_decipher(ca, k_a)\n",
-    "print(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 5,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "2020"
-      ]
-     },
-     "execution_count": 5,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_a_filename, 'w').write(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "6 \n",
-      "\n",
-      "My dear Jessica, I am writing to wish you well in your new life. I am sure you will not forget us, and you can be sure that we will not forget you. May your business flourish to the great benefit of us all. You might be concerned that with the growing uncertainty in the homeland we will find it difficult to continue to communicate, but love will find a way, and I am sure you love your homeland as much as we do. We trust that our effort to stay in touch will be rewarded by an equal effort on your part. I hope that my nephew Karl, who brings you this message, will be able to help you further with these matters. In the meantime, perhaps you can help him. He is a great lover of trains, canal boats and aeroplanes, and it would be a great kindness if you would agree to help him to explore some of the many transport treasures hidden across the UK. It is an unusual passion but I hope that you will feel able to assist him in this. He is particularly keen to explore the possibility of photographing as many of the intriguing travel sites as he can. I seem to recall that Uncle Wilhelm introduced you to the fascinating hobby of photographic reproduction when you stayed with his family in Tirpitzufer. If you were able to assist Karl by developing his films and forwarding them to his home that would, I am sure, avoid unnecessary delay and a great deal of unpleasant misunderstanding. If there is any way we can assist you in your valuable work please let Karl know and we will endeavour to oblige you. Your dear friend, Nikolaus R.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "k_b, score_b = caesar_break(cb)\n",
-    "print(k_b, '\\n')\n",
-    "pb = caesar_decipher(cb, k_b)\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 7,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "1539"
-      ]
-     },
-     "execution_count": 7,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_b_filename, 'w').write(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "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
-}
diff --git a/2020/2020-a-challenge1.md b/2020/2020-a-challenge1.md
deleted file mode 100644 (file)
index cc8955b..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
----
-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 Collapsed="false"
-from szyfrow.caesar import *
-from szyfrow.affine import *
-```
-
-```python Collapsed="false"
-challenge_number = 1
-plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
-plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
-ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
-ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
-```
-
-```python Collapsed="false"
-ca = open(ciphertext_a_filename).read()
-cb = open(ciphertext_b_filename).read()
-```
-
-```python Collapsed="false"
-k_a, score_a = caesar_break(ca)
-print(k_a, '\n')
-pa = caesar_decipher(ca, k_a)
-print(pa)
-```
-
-```python Collapsed="false"
-open(plaintext_a_filename, 'w').write(pa)
-```
-
-```python Collapsed="false"
-k_b, score_b = caesar_break(cb)
-print(k_b, '\n')
-pb = caesar_decipher(cb, k_b)
-print(pb)
-```
-
-```python Collapsed="false"
-open(plaintext_b_filename, 'w').write(pb)
-```
-
-```python Collapsed="false"
-
-```
diff --git a/2020/2020-a-challenge2.ipynb b/2020/2020-a-challenge2.ipynb
deleted file mode 100644 (file)
index be5233b..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "from szyfrow.affine import *\n",
-    "from szyfrow.keyword_cipher import *"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "challenge_number = 2\n",
-    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
-    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
-    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
-    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 9,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "ca = open(ciphertext_a_filename).read()\n",
-    "cb = open(ciphertext_b_filename).read()\n",
-    "scb = sanitise(cb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "19 18 True \n",
-      "\n",
-      "The decrypt of the first mission intercept has raised a number of questions about the spyclist operation, if that is what it is, but it has also triggered enquiries about the personnel referenced in that message. Our counterintelligence unit have asked me to task you with enquiries about the names mentioned there, in particular: Jessica; Wilhelm; Nikolaus; Tirpitzufer. It is possible that these are pseudonyms or code names, but they do not appear in our records and CI branch would be very interested in anything you can find out about them in relation to Nazi spy operations. I followed up on the SIS report that Hitler Youth groups travelling abroad were asked to complete a detailed questionnaire, checking if Harry had links that could help with this, and he sent me the attached message that was photographed by a BOSS undercover operative in Berlin. He told me that it had been exfiltrated from Abwehr headquarters and appears to be a request for approval for a new mission, though neither H nor I have had time to break it, so I look forward to receiving your decrypts. We believe the message has been enciphered using a keyword substitution cipher and given that we are not sure how serious the spyclist threat might be we would be grateful if you could decipher it quickly. The message was also a reminder to me that our own security is an important consideration, so I will also switch to a keyword substitution cipher for the next Mission Briefing. Pearl.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "(m_a, a_a, o_a), score_a = affine_break(ca)\n",
-    "print(m_a, a_a, o_a, '\\n')\n",
-    "pa = affine_decipher(ca, m_a, a_a, o_a)\n",
-    "print(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 7,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "1471"
-      ]
-     },
-     "execution_count": 7,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_a_filename, 'w').write(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 17,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "archerys KeywordWrapAlphabet.from_last \n",
-      "\n",
-      "attdctioc w our missioc to dmnde sympathisdrs ic thd ul dstanfishmdct is goicg wdff afthough thd rdkdct ickrdasd ic eipfomatik tdcsioc has sigcibikactfy ickrdasde thd risl bor our agdcts ic kommucikaticg with thdir hacefdrs. with tdfdgram trabbik ucedr dchackde supdrvisioc ny thd ul ictdffigdckd orgacisatiocs it is afso ickrdasicgfy eibbikuft bor thd agdcts ace thdir hacefdrs to rdpatriatd ictdffigdckd rdports ob acy sigcibikackd. thd usd ob naclicg kiphdrs is co focgdr rdgarede as sdkurd ace edspitd its onvious aevactagds, thd dcigma is too vafuanfd to us to affow its usd ndhice dcdmy ficds. bor cow, wd ard dckouragicg our agdcts to usd a mix ob ldywore ace tracspositioc kiphdrs as taught ic thdir nasik traicicg, sickd thdsd ard rdfianfd ace eo cot rdquird thd agdcts to nd ic possdssioc ob mord thac a sdrids ob ldy wores ace phrasds, whikh thdy ard wdff anfd to mdmorisd. as thd quactity ob sigcafs trabbik ickrdasds wd wiff cdde to rdkocsiedr our protokofs, nut bor cow i thicl our bokus shoufe nd oc edvdfopicg sdkurd kommucikatioc khaccdfs, with kut-outs to isofatd our mord vafuanfd assdts. i eiskussde this issud with my kouctdrpart ic edpartmdct ih who is a lddc kykfist ace hd maed a rathdr icgdcious suggdstioc that wd might mald gooe usd ob thd hitfdr youth. a cumndr ob partids havd nddc icvitde to visit thd ul oc kykficg tours ace hd hae nddc kocsiedricg aslicg thdm to rdkore icbormatioc anout thd fayout ob mifitary ace iceustriaf facemarls as part ob his ictdffigdckd gathdricg opdratioc. it is highfy fildfy that acy war wiff icvofvd a protraktde nomnicg kampaigc ace up to eatd maps wiff nd ob grdat vafud ic our pfaccicg. burthdrmord, thd kouctrysied roae fayouts ic thd ul ard cotorious bor thdir icdbbikidcky ace acy icvasioc, woufe nd sdvdrdfy hampdrde ny our fakl ob lcowfdegd ob tracsport cdtworls. hd hae erabtde ac appardctfy rathdr iccokuous artikfd bor thd cazi kykfist assokiatioc magazicd with a fist ob thicgs that our youcg kykfists might bice ictdrdsticg: imprdss oc your mdmory thd roaes ace paths, viffagds ace towcs, outstaceicg khurkh towdrs ace othdr facemarls so that you wiff cot borgdt thdm. mald a cotd ob thd camds, pfakds, rivdrs, sdas ace mouctaics. pdrhaps you may nd anfd to utifisd thdsd somd timd bor thd ndcdbit ob thd bathdrface. shoufe you komd to a nriegd whikh ictdrdsts you, dxamicd its kocstruktioc ace thd matdriafs usde. fdarc to mdasurd ace dstimatd thd wieth ob strdams. waed through bores so that you wiff nd anfd to bice thdm ic thd earl. i proposd that wd kocsiedr usicg thdsd assdts as thd kut-outs ndtwddc our ucedrkovdr agdcts ace thdir hacefdrs ic thd ul ace our kommucikatiocs cdtworl. thdy ard rdfativdfy brdd to movd arouce thd kouctry ace kac dasify nd traicde to usd erop-obbs ace othdr spykrabt to affow thdm to koffdkt ictdffigdckd rdports ace pass thdm oc. thd marvdffous postd rdstactd systdm affows us to kommucikatd with thdm, ace a suitanfd koednool woufe affow us to tracsmit icstruktiocs ic pfaic tdxt with co risl that thd mdacicg koufe nd eiskdrcde ny kouctdrictdffigdckd opdrativds ic thd postaf sdrvikd. i havd acothdr thought anout how wd might dxpfoit this cdtworl burthdr, howdvdr i cdde to worl through somd mord edtaifs ndbord i eiskuss it with you, ace i wactde to khdkl that you ard happy bor md to affokatd rdsourkds to traic a cumndr ob hitfdr youth ic thd rdquirde sliffs bor this opdratioc. cr.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)\n",
-    "print(word_b, wrap_b, '\\n')\n",
-    "pb = keyword_decipher(cb, word_b, wrap_b)\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 20,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "abwehrstuvxyzcdfgijklmnopq \n",
-      "\n",
-      "attention w our mission to embed sympathisers in the uk establishment is going well although the recent increase in diplomatic tension has significantly increased the risk for our agents in communicating with their handlers. with telegram traffic under enhanced supervision by the uk intelligence organisations it is also increasingly difficult for the agents and their handlers to repatriate intelligence reports of any significance. the use of banking ciphers is no longer regarded as secure and despite its obvious advantages, the enigma is too valuable to us to allow its use behind enemy lines. for now, we are encouraging our agents to use a mix of keyword and transposition ciphers as taught in their basic training, since these are reliable and do not require the agents to be in possession of more than a series of key words and phrases, which they are well able to memorise. as the quantity of signals traffic increases we will need to reconsider our protocols, but for now i think our focus should be on developing secure communication channels, with cut-outs to isolate our more valuable assets. i discussed this issue with my counterpart in department ih who is a keen cyclist and he made a rather ingenious suggestion that we might make good use of the hitler youth. a number of parties have been invited to visit the uk on cycling tours and he had been considering asking them to record information about the layout of military and industrial landmarks as part of his intelligence gathering operation. it is highly likely that any war will involve a protracted bombing campaign and up to date maps will be of great value in our planning. furthermore, the countryside road layouts in the uk are notorious for their inefficiency and any invasion, would be severely hampered by our lack of knowledge of transport networks. he had drafted an apparently rather innocuous article for the nazi cyclist association magazine with a list of things that our young cyclists might find interesting: impress on your memory the roads and paths, villages and towns, outstanding church towers and other landmarks so that you will not forget them. make a note of the names, places, rivers, seas and mountains. perhaps you may be able to utilise these some time for the benefit of the fatherland. should you come to a bridge which interests you, examine its construction and the materials used. learn to measure and estimate the width of streams. wade through fords so that you will be able to find them in the dark. i propose that we consider using these assets as the cut-outs between our undercover agents and their handlers in the uk and our communications network. they are relatively free to move around the country and can easily be trained to use drop-offs and other spycraft to allow them to collect intelligence reports and pass them on. the marvellous poste restante system allows us to communicate with them, and a suitable codebook would allow us to transmit instructions in plain text with no risk that the meaning could be discerned by counterintelligence operatives in the postal service. i have another thought about how we might exploit this network further, however i need to work through some more details before i discuss it with you, and i wanted to check that you are happy for me to allocate resources to train a number of hitler youth in the required skills for this operation. nr.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "word_b, score_b = simulated_annealing_break(scb)\n",
-    "print(word_b, '\\n')\n",
-    "pb = keyword_decipher(cb, word_b)\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 19,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "'attention w our mission to embed sympathisers in the uk establishment is going well although the recent increase in diplomatic tension has significantly increased the risk for our agents in communicating with their handlers. with telegram traffic under enhanced supervision by the uk intelligence organisations it is also increasingly difficult for the agents and their handlers to repatriate intelligence reports of any significance. the use of banking ciphers is no longer regarded as secure and despite its obvious advantages, the enigma is too valuable to us to allow its use behind enemy lines. for now, we are encouraging our agents to use a mix of keyword and transposition ciphers as taught in their basic training, since these are reliable and do not require the agents to be in possession of more than a series of key words and phrases, which they are well able to memorise. as the quantity of signals traffic increases we will need to reconsider our protocols, but for now i think our focus should be on developing secure communication channels, with cut-outs to isolate our more valuable assets. i discussed this issue with my counterpart in department ih who is a keen cyclist and he made a rather ingenious suggestion that we might make good use of the hitler youth. a number of parties have been invited to visit the uk on cycling tours and he had been considering asking them to record information about the layout of military and industrial landmarks as part of his intelligence gathering operation. it is highly likely that any war will involve a protracted bombing campaign and up to date maps will be of great value in our planning. furthermore, the countryside road layouts in the uk are notorious for their inefficiency and any invasion, would be severely hampered by our lack of knowledge of transport networks. he had drafted an apparently rather innocuous article for the nazi cyclist association magazine with a list of things that our young cyclists might find interesting: impress on your memory the roads and paths, villages and towns, outstanding church towers and other landmarks so that you will not forget them. make a note of the names, places, rivers, seas and mountains. perhaps you may be able to utilise these some time for the benefit of the fatherland. should you come to a bridge which interests you, examine its construction and the materials used. learn to measure and estimate the width of streams. wade through fords so that you will be able to find them in the dark. i propose that we consider using these assets as the cut-outs between our undercover agents and their handlers in the uk and our communications network. they are relatively free to move around the country and can easily be trained to use drop-offs and other spycraft to allow them to collect intelligence reports and pass them on. the marvellous poste restante system allows us to communicate with them, and a suitable codebook would allow us to transmit instructions in plain text with no risk that the meaning could be discerned by counterintelligence operatives in the postal service. i have another thought about how we might exploit this network further, however i need to work through some more details before i discuss it with you, and i wanted to check that you are happy for me to allocate resources to train a number of hitler youth in the required skills for this operation. nr.\\n'"
-      ]
-     },
-     "execution_count": 19,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "keyword_decipher(cb, 'abwehr', KeywordWrapAlphabet.from_last)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 21,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "3403"
-      ]
-     },
-     "execution_count": 21,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_b_filename, 'w').write(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "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
-}
diff --git a/2020/2020-a-challenge2.md b/2020/2020-a-challenge2.md
deleted file mode 100644 (file)
index 80efcc4..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
----
-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 Collapsed="false"
-from szyfrow.affine import *
-from szyfrow.keyword_cipher import *
-```
-
-```python Collapsed="false"
-challenge_number = 2
-plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
-plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
-ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
-ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
-```
-
-```python Collapsed="false"
-ca = open(ciphertext_a_filename).read()
-cb = open(ciphertext_b_filename).read()
-scb = sanitise(cb)
-```
-
-```python Collapsed="false"
-(m_a, a_a, o_a), score_a = affine_break(ca)
-print(m_a, a_a, o_a, '\n')
-pa = affine_decipher(ca, m_a, a_a, o_a)
-print(pa)
-```
-
-```python Collapsed="false"
-open(plaintext_a_filename, 'w').write(pa)
-```
-
-```python Collapsed="false"
-(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)
-print(word_b, wrap_b, '\n')
-pb = keyword_decipher(cb, word_b, wrap_b)
-print(pb)
-```
-
-```python Collapsed="false"
-word_b, score_b = simulated_annealing_break(scb)
-print(word_b, '\n')
-pb = keyword_decipher(cb, word_b)
-print(pb)
-```
-
-```python Collapsed="false"
-keyword_decipher(cb, 'abwehr', KeywordWrapAlphabet.from_last)
-```
-
-```python Collapsed="false"
-open(plaintext_b_filename, 'w').write(pb)
-```
-
-```python Collapsed="false"
-
-```
diff --git a/2020/2020-a-challenge3.ipynb b/2020/2020-a-challenge3.ipynb
deleted file mode 100644 (file)
index ccb356e..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 1,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "from szyfrow.affine import *\n",
-    "from szyfrow.keyword_cipher import *"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "challenge_number = 3\n",
-    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
-    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
-    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
-    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 5,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "ca = open(ciphertext_a_filename).read()\n",
-    "sca = sanitise(ca)\n",
-    "cb = open(ciphertext_b_filename).read()\n",
-    "scb = sanitise(cb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 8,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "vern KeywordWrapAlphabet.from_last \n",
-      "\n",
-      "thanks to everyone for their work on the intercept, it looks really important and i have discussed the contents with harry. our sources in germany have confirmed that the nca magazine carried the instructions issued by ih and nr, and vk wrote to the chief constables of local police forces requesting them to keep an eye out for the touring groups and to report on any matters of interest. special branch are coordinating intelligence activities and forwarded a report from the local constabulary in norfolk detailing activity by one of the touring cycling parties who were seen taking photographs and sketching the landscape at caistor st edmund. the local constable questioned them, but they were not held as there were no grounds for an arrest. they had arrived at harwich and were apparently touring norfolk at the invitation of a local scout group before heading to london.\n",
-      "while there are significant defence installations in that area, caistor st edmund seems an unlikely target for german intelligence so perhaps this is innocent, but the evidence we have so far suggests that that is unlikely. another possibility is that it is a red herring operation disguising the activities of other groups, but just in case i will make enquiries with our sister agencies to see if there is anything we should know about in that area.\n",
-      "i asked our agents in norfolk to report on unusual activity and sent them a list of keywords that should trigger investigation. they forwarded the attached message addressed to tirpitzufer, which was left at the caistor st edmund post office by the local scoutmaster. it was in a bulky packet containing a number of sketches of the area together with an encrypted message which we need you to decipher quickly. analysis of other communication intercepts have suggested that this message may also contain a key to future communications across the spyclist network so you should spend some time thinking about it once you have submitted the decrypt.\n",
-      "while the mission of the spyclists is spelled out in detail in the last decrypt, it is still not clear what the larger aims of the abwehr mission might be, but your research into wilhelm and nikolaus has probably led you to the same conclusion as me: this is a high-level mission and is likely to pose a significant threat to our security. it follows that we should increase our own security to prevent nazi code breakers from reading our messages, so i will lengthen the keyword in my next mission briefing. i will also review our communication protocols for subsequent messages with harry and will update you on the standards to use in mission briefing 4.\n",
-      "the report from norfolk gave me an idea about how we could gather intelligence on the spyclist network. harry and i discussed this with vk since it carries a number of risks, but vk approved the strategy which we have given the codename the akela initiative. more to follow.\n",
-      "pearl\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)\n",
-    "print(word_a, wrap_a, '\\n')\n",
-    "pa = keyword_decipher(ca, word_a, wrap_a)\n",
-    "print(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 9,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "2918"
-      ]
-     },
-     "execution_count": 9,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_a_filename, 'w').write(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 10,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "croatias KeywordWrapAlphabet.from_last \n",
-      "\n",
-      "gear unfle wilhelm,\n",
-      "i trust that you ang the camily at tirpitzucer are all well ang that you enjoyeg the sketfhes i sent you last week. i have enfloseg my most refent impressions oc the deauticul, ic somewhat stark langsfape in norcolk. i hope ang delieve that you will cing them oc breat interest. the clat ang open cielgs have a spartan deauty punftuateg dy just a cew langmarks oc gistinftion, dut their isolation makes them stang out even more ang infreases their interest.\n",
-      "our hosts have deen most abreeadle ang even the lofal polife corfe have deen as affommogatinb as you subbesteg they woulg de. the lofal fonstadle seemeg most interesteg in our photobraphif hoddy, dut he appeareg to de fontent with the explanation oc our interest in their deauticul fountrysige ang villabes. he was also very apprefiative oc our roubh sketfhes oc their strikinb langsfape, thoubh he gig seem surpriseg at the numder oc grawinbs we have mage oc the cielgs aroung faistor st egmung, subbestinb that its sibnicifanfe is not wigely known.\n",
-      "the lofal sfoutmaster abreeg to pass this messabe to you ang has also arranbeg cor our corwarg travel. we will heag next to longon to meet with my fousin nikolaus decore preparinb cor the sefong stabe oc our little agventure. ic you have any curther requests cor incormation or aggitional grawinbs in this extraorginary part oc the worlg then please go make sure to let me know decore we gepart.\n",
-      "let me cinish with a little puzzle cor you. fan you cing an eibht letter enblish worg whifh you fan fhanbe dy alterinb the orger oc its letters to progufe cour other giccerent enblish worgs?\n",
-      "yours sinferely,\n",
-      "otto\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)\n",
-    "print(word_b, wrap_b, '\\n')\n",
-    "pb = keyword_decipher(cb, word_b, wrap_b)\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 11,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "caistoruvwxyzbdefghjklmnpq \n",
-      "\n",
-      "dear uncle wilhelm,\n",
-      "i trust that you and the family at tirpitzufer are all well and that you enjoyed the sketches i sent you last week. i have enclosed my most recent impressions of the beautiful, if somewhat stark landscape in norfolk. i hope and believe that you will find them of great interest. the flat and open fields have a spartan beauty punctuated by just a few landmarks of distinction, but their isolation makes them stand out even more and increases their interest.\n",
-      "our hosts have been most agreeable and even the local police force have been as accommodating as you suggested they would be. the local constable seemed most interested in our photographic hobby, but he appeared to be content with the explanation of our interest in their beautiful countryside and villages. he was also very appreciative of our rough sketches of their striking landscape, though he did seem surprised at the number of drawings we have made of the fields around caistor st edmund, suggesting that its significance is not widely known.\n",
-      "the local scoutmaster agreed to pass this message to you and has also arranged for our forward travel. we will head next to london to meet with my cousin nikolaus before preparing for the second stage of our little adventure. if you have any further requests for information or additional drawings in this extraordinary part of the world then please do make sure to let me know before we depart.\n",
-      "let me finish with a little puzzle for you. can you find an eight letter english word which you can change by altering the order of its letters to produce four other different english words?\n",
-      "yours sincerely,\n",
-      "otto\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "word_b, score_b = simulated_annealing_break(scb, fitness=Ptrigrams)\n",
-    "print(word_b, '\\n')\n",
-    "pb = keyword_decipher(cb, word_b)\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 12,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "'dear uncle wilhelm,\\ni trust that you and the family at tirpitzufer are all well and that you enjoyed the sketches i sent you last week. i have enclosed my most recent impressions of the beautiful, if somewhat stark landscape in norfolk. i hope and believe that you will find them of great interest. the flat and open fields have a spartan beauty punctuated by just a few landmarks of distinction, but their isolation makes them stand out even more and increases their interest.\\nour hosts have been most agreeable and even the local police force have been as accommodating as you suggested they would be. the local constable seemed most interested in our photographic hobby, but he appeared to be content with the explanation of our interest in their beautiful countryside and villages. he was also very appreciative of our rough sketches of their striking landscape, though he did seem surprised at the number of drawings we have made of the fields around caistor st edmund, suggesting that its significance is not widely known.\\nthe local scoutmaster agreed to pass this message to you and has also arranged for our forward travel. we will head next to london to meet with my cousin nikolaus before preparing for the second stage of our little adventure. if you have any further requests for information or additional drawings in this extraordinary part of the world then please do make sure to let me know before we depart.\\nlet me finish with a little puzzle for you. can you find an eight letter english word which you can change by altering the order of its letters to produce four other different english words?\\nyours sincerely,\\notto\\n'"
-      ]
-     },
-     "execution_count": 12,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "keyword_decipher(cb, 'caistor', KeywordWrapAlphabet.from_last)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 13,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "1638"
-      ]
-     },
-     "execution_count": 13,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_b_filename, 'w').write(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "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
-}
diff --git a/2020/2020-a-challenge3.md b/2020/2020-a-challenge3.md
deleted file mode 100644 (file)
index 05bb180..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
----
-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 Collapsed="false"
-from szyfrow.affine import *
-from szyfrow.keyword_cipher import *
-```
-
-```python Collapsed="false"
-challenge_number = 3
-plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
-plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
-ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
-ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
-```
-
-```python Collapsed="false"
-ca = open(ciphertext_a_filename).read()
-sca = sanitise(ca)
-cb = open(ciphertext_b_filename).read()
-scb = sanitise(cb)
-```
-
-```python Collapsed="false"
-(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)
-print(word_a, wrap_a, '\n')
-pa = keyword_decipher(ca, word_a, wrap_a)
-print(pa)
-```
-
-```python Collapsed="false"
-open(plaintext_a_filename, 'w').write(pa)
-```
-
-```python Collapsed="false"
-(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)
-print(word_b, wrap_b, '\n')
-pb = keyword_decipher(cb, word_b, wrap_b)
-print(pb)
-```
-
-```python Collapsed="false"
-word_b, score_b = simulated_annealing_break(scb, fitness=Ptrigrams)
-print(word_b, '\n')
-pb = keyword_decipher(cb, word_b)
-print(pb)
-```
-
-```python Collapsed="false"
-keyword_decipher(cb, 'caistor', KeywordWrapAlphabet.from_last)
-```
-
-```python Collapsed="false"
-open(plaintext_b_filename, 'w').write(pb)
-```
-
-```python Collapsed="false"
-
-```
diff --git a/2020/2020-a-challenge4.ipynb b/2020/2020-a-challenge4.ipynb
deleted file mode 100644 (file)
index 19f01c1..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-{
- "cells": [
-  {
-   "cell_type": "code",
-   "execution_count": 18,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "from szyfrow.keyword_cipher import *\n",
-    "from szyfrow.column_transposition import *\n",
-    "from szyfrow.support.text_prettify import *"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 2,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "challenge_number = 4\n",
-    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
-    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
-    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
-    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 3,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "ca = open(ciphertext_a_filename).read()\n",
-    "sca = sanitise(ca)\n",
-    "cb = open(ciphertext_b_filename).read()\n",
-    "scb = sanitise(cb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 4,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "akkad KeywordWrapAlphabet.from_largest \n",
-      "\n",
-      "i have drawn a blank in my enqciries aboct uaistor st edmcnd and even harry is getting nowhere with his uontauts in the mod. we both agree that the silenue is very worrying. this is ulearly an area of interest as it presents a urcuial front in any potential invasion so we wocld have expeuted some interest in ocr intelligenue, or at least some pcsh bauk warning cs to keep away from basiu defenue installations like listening posts. the faut that no-one wants to talk aboct the fauilities in the area scggests that it is all very hcsh hcsh. something important is happening there and we probably want to find oct what.\n",
-      "\n",
-      "ocr agents in london kept watuh for the tocring party and reuorded them as arriving at liverpool street. the grocp uonsisted of twenty three uyulists who split cp and stayed with members of loual suoct grocps while their leader was hosted by a member of the loual ortsgrcppe. we reueived reports from k's network that the grocp has been invited to stay with the spalding rotary ulcb in linuoln and we need yoc to investigate any reports yoc uan find aboct that visit. i will uontince to press for information aboct strategiu developments in norwiuh and norfolk.\n",
-      "\n",
-      "the akela initiative has been given approval and i will be setting that cp this week. the intention is to enroll leaders and members of loual suoct grocps, train them in uocnter-intelligenue and cse them to host the spyulist tocring grocps in the hope of getting inside their operation. sinue fctcre uommcniuations may inulcde sensitive operational details of this initiative i intend to inurease seucrity by moving to a blouked keyword uipher.\n",
-      "\n",
-      "the attauhed doucment was interuepted by ocr london agents when the party posted it on arrival at liverpool street. as cscal it was addressed to tirpitzcfer. primary analysis scggests that it does not cse a scbstitction uipher.\n",
-      "\n",
-      "more to follow.\n",
-      "\n",
-      "pearl.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)\n",
-    "print(word_a, wrap_a, '\\n')\n",
-    "pa = keyword_decipher(ca, word_a, wrap_a)\n",
-    "print(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 5,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "akelmnopqrstuvwxyzbcdfghij \n",
-      "\n",
-      "i have drawn a blank in my enquiries about caistor st edmund and even harry is getting nowhere with his contacts in the mod. we both agree that the silence is very worrying. this is clearly an area of interest as it presents a crucial front in any potential invasion so we would have expected some interest in our intelligence, or at least some push back warning us to keep away from basic defence installations like listening posts. the fact that no-one wants to talk about the facilities in the area suggests that it is all very hush hush. something important is happening there and we probably want to find out what.\n",
-      "\n",
-      "our agents in london kept watch for the touring party and recorded them as arriving at liverpool street. the group consisted of twenty three cyclists who split up and stayed with members of local scout groups while their leader was hosted by a member of the local ortsgruppe. we received reports from k's network that the group has been invited to stay with the spalding rotary club in lincoln and we need you to investigate any reports you can find about that visit. i will continue to press for information about strategic developments in norwich and norfolk.\n",
-      "\n",
-      "the akela initiative has been given approval and i will be setting that up this week. the intention is to enroll leaders and members of local scout groups, train them in counter-intelligence and use them to host the spyclist touring groups in the hope of getting inside their operation. since future communications may include sensitive operational details of this initiative i intend to increase security by moving to a blocked keyword cipher.\n",
-      "\n",
-      "the attached document was intercepted by our london agents when the party posted it on arrival at liverpool street. as usual it was addressed to tirpitzufer. primary analysis suggests that it does not use a substitution cipher.\n",
-      "\n",
-      "more to follow.\n",
-      "\n",
-      "pearl.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "word_a, score_a = simulated_annealing_break(sca, fitness=Ptrigrams,\n",
-    "        plain_alphabet=string.ascii_lowercase, cipher_alphabet=keyword_cipher_alphabet_of('akkad', wrap_alphabet=KeywordWrapAlphabet.from_largest))\n",
-    "print(word_a, '\\n')\n",
-    "pa = keyword_decipher(ca, word_a)\n",
-    "print(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 6,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "i have drawn a blank in my enquiries about caistor st edmund and even harry is getting nowhere with his contacts in the mod. we both agree that the silence is very worrying. this is clearly an area of interest as it presents a crucial front in any potential invasion so we would have expected some interest in our intelligence, or at least some push back warning us to keep away from basic defence installations like listening posts. the fact that no-one wants to talk about the facilities in the area suggests that it is all very hush hush. something important is happening there and we probably want to find out what.\n",
-      "\n",
-      "our agents in london kept watch for the touring party and recorded them as arriving at liverpool street. the group consisted of twenty three cyclists who split up and stayed with members of local scout groups while their leader was hosted by a member of the local ortsgruppe. we received reports from k's network that the group has been invited to stay with the spalding rotary club in lincoln and we need you to investigate any reports you can find about that visit. i will continue to press for information about strategic developments in norwich and norfolk.\n",
-      "\n",
-      "the akela initiative has been given approval and i will be setting that up this week. the intention is to enroll leaders and members of local scout groups, train them in counter-intelligence and use them to host the spyclist touring groups in the hope of getting inside their operation. since future communications may include sensitive operational details of this initiative i intend to increase security by moving to a blocked keyword cipher.\n",
-      "\n",
-      "the attached document was intercepted by our london agents when the party posted it on arrival at liverpool street. as usual it was addressed to tirpitzufer. primary analysis suggests that it does not use a substitution cipher.\n",
-      "\n",
-      "more to follow.\n",
-      "\n",
-      "pearl.\n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "pa = keyword_decipher(ca, 'akela', wrap_alphabet=KeywordWrapAlphabet.from_largest)\n",
-    "print(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 7,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "1883"
-      ]
-     },
-     "execution_count": 7,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_a_filename, 'w').write(pa)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 11,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [],
-   "source": [
-    "clue_dict = ['alerting', 'altering', 'integral', 'relating', 'triangle', 'angriest', 'gantries', 'granites', 'ingrates', 'rangiest', 'tangiers', \n",
-    "             'dniester', 'inserted', 'nerdiest', 'resident', 'trendies', 'respects', 'scepters', 'sceptres', 'specters', 'spectres', 'restrain', \n",
-    "             'retrains', 'strainer', 'terrains', 'trainers']\n",
-    "clue_trans = [transpositions_of(w) for w in clue_dict]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 13,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "(1, 2, 3, 5, 0, 4) True False \n",
-      "\n",
-      "REERNLNHNRTAANNBSCROIAUSHOALISICTETSIEAARASTSOSLNOIOOWESEIOGMHISTXDIEGEAGATTADRVSICAYSITREARESOFNCFFWPNSPPTNTAELHYBNRRAMNSMSXOENGPNINFAFOGDLOMENOORHNTNERMTATFTWATFAESOGRYNCSHSENTEDAOTRKIBPPARHCERRTTHNNTGIREITMVHEDCONTCTUWPDOIROENHEGIKIATNCWLNODRSSNTEOGAFREBTAEHOLWHOSSITPTRNCUNLECLOUTDSTHNTSLLHTRTGNDCRERSESALLBEOCOAUEOEOUAEHIDVADSAHETISIVTGLNNESTTPCIWUFRAETIRHIIWFLEREYTEEOKHYRFOTIRERNERTSFIILFCINYTSALGAHHSDIVSLLSUTWSTELNPOOSISOSHAYNEGNLOGTORDTHTRRORRSDISUEOEIALSTKGASPUNBNLUMYIIBSIELHEEAIGIRISSCRCVNATGTYIOIAIUTTEANNNURSCMMHEEAPEOIRIRTESOODTHILWCESTTYSRALHUROOSAAGRRIOEIAHHFSOYTRMATSEAUSNKVVSWTLSNTDONOENFTYMRHTCNETHLDEWWHSPHNSTALNIIEEETTAFTASSFHASRAEOSEPUEOXAOOHHTTTNIEENYAIOYATVIEIISEOLIYGEIEIROTPUTASARUETHONOIPNIHUUTOEHIUNTUWISTNRYNSREAOUNCTEMFEIFGEISNRHOCYORTRLANATASOYHIFTHHHAGMNTNMWOICTPIRAEEAIARNNLDUNYFEHRYURTOONDIONTAOOIEUWLJEOWODMHITGGRHKOPENNIEAYMMANETIRPDRBYACCRPUTOHRSRSIMOBSUMEOWPHTATORENNBHHNTAIHNALIDCOOLWOPUFODIFAEOIFELITHNBEEAEOSTNIDIERILBDOAQTEVGEUEWLUEIDSRBEDEDAETHVBOTISHTTNTMEWOSTFEEDCODTDUMEATLISLOETVOLSHIJGETTASAHEIEBIHFSERHNHREROOUDDTTTTYGNATOHAGWIVISGTACENOIRUHRNAUDAEUTPNHYPETSRCY                                                                                                                                                                                                                                                                                     \n",
-      "DNIMOYNARCIENTATITSUELDTDIDBOPBPSHRAREYLTVROYERSNAGEUTTBFRHTONUIEEFYHRUXGEOEEDHCTETPCTIUTUVAMLRNLTTERRRTONOOHEDUOCSRFAAOTINWENEETSNUISIEASSEURHNOUTRRSRTSTHEEERELSESYTEETIUTIOIAIARMHISEMBIECISSSREMIEOAOLNOIDPLESCYUNATMROETIOIMNUTANSHHHOHTKOUENONOIAUTHRHSNRTATEEPPCFRMRSAGASOSEESE\n"
-     ]
-    }
-   ],
-   "source": [
-    "(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, translist=clue_trans, fitness=Ptrigrams)\n",
-    "print(trans_b, fill_b, empty_b, '\\n')\n",
-    "pb = column_transposition_decipher(cb, trans_b, \n",
-    "    fillcolumnwise=fill_b,\n",
-    "    emptycolumnwise=empty_b)\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 22,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "(1, 2, 4, 0, 3) False False \n",
-      "\n"
-     ]
-    }
-   ],
-   "source": [
-    "(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, fitness=Ptrigrams)\n",
-    "print(trans_b, fill_b, empty_b, '\\n')"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 19,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "name": "stdout",
-     "output_type": "stream",
-     "text": [
-      "dear uncle wilhelm our journey to london was short and charming the trains rattling along the\n",
-      "british tracks through open fields and countryside their roads maybe almost impassable in places but\n",
-      "these iron tracks provide a very usable way to travel across country at speed our hosts in london\n",
-      "have organised for us to stay with members of the british scouting movement though i will spend the\n",
-      "next few days with the orts gruppe exchanging news about the fatherland and their activities herein\n",
-      "the capital city it was difficult to tear ourselves away from the pleasures of norfolk and the city\n",
-      "offers far fewer opportunities for open exploration on the other hand the bustle of the city as in\n",
-      "berlin offers a certain anonymity and it is in some ways relaxing to leave behind the gossip and\n",
-      "inquisitiveness of village life as you suggested we will use our time herein london to support our\n",
-      "brothers and sisters and to reassure them that they have not been forgotten i will pass on the gifts\n",
-      "that you entrusted to me together with your instructions for their use as we did in caistor st\n",
-      "edmund the radio you sent me is remarkable it is able to pickup signals across the spectrum even\n",
-      "from berlin itself though i am enjoying listening to british radio especially the home service they\n",
-      "are building a chain of transmitters across the country which provide information throughout the day\n",
-      "and night something that i think you might want to take into account when planning our own radio\n",
-      "services i am assuming that there are no changes planned for our itinerary but if there are then\n",
-      "perhaps you could forward them to our hosts in spalding with a copy sent post restante to cse yours\n",
-      "sincerely\n"
-     ]
-    }
-   ],
-   "source": [
-    "pb = prettify(column_transposition_decipher(scb, trans_b, \n",
-    "    fillcolumnwise=fill_b,\n",
-    "    emptycolumnwise=empty_b))\n",
-    "print(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 20,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "['fable',\n",
-       " 'gable',\n",
-       " 'nacre',\n",
-       " 'nahum',\n",
-       " 'oakum',\n",
-       " 'odium',\n",
-       " 'padre',\n",
-       " 'pinto',\n",
-       " 'salvo',\n",
-       " 'santo',\n",
-       " 'scour',\n",
-       " 'tabus',\n",
-       " 'tagus',\n",
-       " 'talus',\n",
-       " 'thous',\n",
-       " 'timur',\n",
-       " 'torus',\n",
-       " 'torys',\n",
-       " 'whizs',\n",
-       " 'gabble',\n",
-       " 'kabuki',\n",
-       " 'lactic',\n",
-       " 'ladoga',\n",
-       " 'leftie',\n",
-       " 'madrid',\n",
-       " 'megohm',\n",
-       " 'oberon',\n",
-       " 'raisin',\n",
-       " 'refuel',\n",
-       " 'refuge',\n",
-       " 'salvos',\n",
-       " 'santos',\n",
-       " 'scours',\n",
-       " 'tabbys',\n",
-       " 'tabula',\n",
-       " 'taffys',\n",
-       " 'taguss',\n",
-       " 'taiwan',\n",
-       " 'tallys',\n",
-       " 'tammys',\n",
-       " 'tanyas',\n",
-       " 'telexs',\n",
-       " 'tenure',\n",
-       " 'terrys',\n",
-       " 'tethys',\n",
-       " 'thrush',\n",
-       " 'thrust',\n",
-       " 'timmys',\n",
-       " 'toruss',\n",
-       " 'velezs',\n",
-       " 'vilyui',\n",
-       " 'weepys',\n",
-       " 'whizzs',\n",
-       " 'willys',\n",
-       " 'worrys',\n",
-       " 'lactate',\n",
-       " 'macrame',\n",
-       " 'palazzo',\n",
-       " 'raisins',\n",
-       " 'raritan',\n",
-       " 'refresh',\n",
-       " 'refugee',\n",
-       " 'sabbath',\n",
-       " 'salazar',\n",
-       " 'sinuous',\n",
-       " 'tactual',\n",
-       " 'tarawas',\n",
-       " 'telexes',\n",
-       " 'tethyss',\n",
-       " 'thrushs',\n",
-       " 'thrusts',\n",
-       " 'maharaja',\n",
-       " 'nakayama',\n",
-       " 'ramayana',\n",
-       " 'sabbaths',\n",
-       " 'salazars',\n",
-       " 'semester',\n",
-       " 'sensuous',\n",
-       " 'teletype',\n",
-       " 'tortuous',\n",
-       " 'maharajah',\n",
-       " 'refresher',\n",
-       " 'refreshes',\n",
-       " 'semesters',\n",
-       " 'refreshers',\n",
-       " 'sensuousness',\n",
-       " 'sensuousnesss']"
-      ]
-     },
-     "execution_count": 20,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "transpositions[trans_b]"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 21,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "1685"
-      ]
-     },
-     "execution_count": 21,
-     "metadata": {},
-     "output_type": "execute_result"
-    }
-   ],
-   "source": [
-    "open(plaintext_b_filename, 'w').write(pb)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": null,
-   "metadata": {
-    "Collapsed": "false"
-   },
-   "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
-}
diff --git a/2020/2020-a-challenge4.md b/2020/2020-a-challenge4.md
deleted file mode 100644 (file)
index 032af74..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
----
-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 Collapsed="false"
-from szyfrow.keyword_cipher import *
-from szyfrow.column_transposition import *
-from szyfrow.support.text_prettify import *
-```
-
-```python Collapsed="false"
-challenge_number = 4
-plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
-plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
-ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
-ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
-```
-
-```python Collapsed="false"
-ca = open(ciphertext_a_filename).read()
-sca = sanitise(ca)
-cb = open(ciphertext_b_filename).read()
-scb = sanitise(cb)
-```
-
-```python Collapsed="false"
-(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)
-print(word_a, wrap_a, '\n')
-pa = keyword_decipher(ca, word_a, wrap_a)
-print(pa)
-```
-
-```python Collapsed="false"
-word_a, score_a = simulated_annealing_break(sca, fitness=Ptrigrams,
-        plain_alphabet=string.ascii_lowercase, cipher_alphabet=keyword_cipher_alphabet_of('akkad', wrap_alphabet=KeywordWrapAlphabet.from_largest))
-print(word_a, '\n')
-pa = keyword_decipher(ca, word_a)
-print(pa)
-```
-
-```python Collapsed="false"
-pa = keyword_decipher(ca, 'akela', wrap_alphabet=KeywordWrapAlphabet.from_largest)
-print(pa)
-```
-
-```python Collapsed="false"
-open(plaintext_a_filename, 'w').write(pa)
-```
-
-```python Collapsed="false"
-clue_dict = ['alerting', 'altering', 'integral', 'relating', 'triangle', 'angriest', 'gantries', 'granites', 'ingrates', 'rangiest', 'tangiers', 
-             'dniester', 'inserted', 'nerdiest', 'resident', 'trendies', 'respects', 'scepters', 'sceptres', 'specters', 'spectres', 'restrain', 
-             'retrains', 'strainer', 'terrains', 'trainers']
-clue_trans = [transpositions_of(w) for w in clue_dict]
-```
-
-```python Collapsed="false"
-(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, translist=clue_trans, fitness=Ptrigrams)
-print(trans_b, fill_b, empty_b, '\n')
-pb = column_transposition_decipher(cb, trans_b, 
-    fillcolumnwise=fill_b,
-    emptycolumnwise=empty_b)
-print(pb)
-```
-
-```python Collapsed="false"
-(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, fitness=Ptrigrams)
-print(trans_b, fill_b, empty_b, '\n')
-```
-
-```python Collapsed="false"
-pb = prettify(column_transposition_decipher(scb, trans_b, 
-    fillcolumnwise=fill_b,
-    emptycolumnwise=empty_b))
-print(pb)
-```
-
-```python Collapsed="false"
-transpositions[trans_b]
-```
-
-```python Collapsed="false"
-open(plaintext_b_filename, 'w').write(pb)
-```
-
-```python Collapsed="false"
-
-```
diff --git a/2020/2020-challenge1.ipynb b/2020/2020-challenge1.ipynb
new file mode 100644 (file)
index 0000000..17459fa
--- /dev/null
@@ -0,0 +1,173 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "from szyfrow.caesar import *\n",
+    "from szyfrow.affine import *"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "challenge_number = 1\n",
+    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
+    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
+    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
+    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "ca = open(ciphertext_a_filename).read()\n",
+    "cb = open(ciphertext_b_filename).read()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "14 \n",
+      "\n",
+      "The British Daily Herald article on so called spyclists has raised concern at government levels that the large increase in travel from the Continent has masked an infiltration operation by the Abwehr.\n",
+      "SIS has received reports that Hitler Youth groups travelling abroad have been asked to complete a detailed questionnaire, including questions on terrain, population, and political views of the population. VK has taken a personal interest in the story but his resources are fully allocated in investigating a number of suspected German agents already living in the UK, so BOSS has been tasked with investigating and reporting on the spyclist touring network.\n",
+      "Harry is currently engaged investigating Die Alchemisten so he has asked our team to take this on. While it is possible that the cycle tourists are operating as a forward observer division in preparation for a future invasion, the small numbers involved, and their travel routes make it seem likely that this is at most a feint designed to draw our resources away from more significant operations. What we do know is that there is an intelligence dimension to this since our operatives in the GPO intercepted the attached encrypted message in a bundle of letters left poste restante for one of the touring parties at a Scottish post office. Our first task is to decipher this message and to analyse its contents. Even if this turns out to be a diversionary tactic it provides us with an opportunity to develop our BOSS home intelligence operation and we will be treating the mission seriously. Operatives from all three BOSS divisions will be working together at the Broadway to intercept, decipher and analyse potentially relevant sources. We will be posting updates here in the mission pages using standard protocols. Since our communications are protected we will, for now, use tier one (Caesar and affine shift) encryption. Your field issue cipher wheel is attached, and your first task is to decipher the attached message and to study it carefully.\n",
+      "Pearl.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "k_a, score_a = caesar_break(ca)\n",
+    "print(k_a, '\\n')\n",
+    "pa = caesar_decipher(ca, k_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "2020"
+      ]
+     },
+     "execution_count": 5,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_a_filename, 'w').write(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "6 \n",
+      "\n",
+      "My dear Jessica, I am writing to wish you well in your new life. I am sure you will not forget us, and you can be sure that we will not forget you. May your business flourish to the great benefit of us all. You might be concerned that with the growing uncertainty in the homeland we will find it difficult to continue to communicate, but love will find a way, and I am sure you love your homeland as much as we do. We trust that our effort to stay in touch will be rewarded by an equal effort on your part. I hope that my nephew Karl, who brings you this message, will be able to help you further with these matters. In the meantime, perhaps you can help him. He is a great lover of trains, canal boats and aeroplanes, and it would be a great kindness if you would agree to help him to explore some of the many transport treasures hidden across the UK. It is an unusual passion but I hope that you will feel able to assist him in this. He is particularly keen to explore the possibility of photographing as many of the intriguing travel sites as he can. I seem to recall that Uncle Wilhelm introduced you to the fascinating hobby of photographic reproduction when you stayed with his family in Tirpitzufer. If you were able to assist Karl by developing his films and forwarding them to his home that would, I am sure, avoid unnecessary delay and a great deal of unpleasant misunderstanding. If there is any way we can assist you in your valuable work please let Karl know and we will endeavour to oblige you. Your dear friend, Nikolaus R.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "k_b, score_b = caesar_break(cb)\n",
+    "print(k_b, '\\n')\n",
+    "pb = caesar_decipher(cb, k_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1539"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "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
+}
diff --git a/2020/2020-challenge1.md b/2020/2020-challenge1.md
new file mode 100644 (file)
index 0000000..cc8955b
--- /dev/null
@@ -0,0 +1,58 @@
+---
+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 Collapsed="false"
+from szyfrow.caesar import *
+from szyfrow.affine import *
+```
+
+```python Collapsed="false"
+challenge_number = 1
+plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
+plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
+ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
+ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
+```
+
+```python Collapsed="false"
+ca = open(ciphertext_a_filename).read()
+cb = open(ciphertext_b_filename).read()
+```
+
+```python Collapsed="false"
+k_a, score_a = caesar_break(ca)
+print(k_a, '\n')
+pa = caesar_decipher(ca, k_a)
+print(pa)
+```
+
+```python Collapsed="false"
+open(plaintext_a_filename, 'w').write(pa)
+```
+
+```python Collapsed="false"
+k_b, score_b = caesar_break(cb)
+print(k_b, '\n')
+pb = caesar_decipher(cb, k_b)
+print(pb)
+```
+
+```python Collapsed="false"
+open(plaintext_b_filename, 'w').write(pb)
+```
+
+```python Collapsed="false"
+
+```
diff --git a/2020/2020-challenge2.ipynb b/2020/2020-challenge2.ipynb
new file mode 100644 (file)
index 0000000..be5233b
--- /dev/null
@@ -0,0 +1,218 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "from szyfrow.affine import *\n",
+    "from szyfrow.keyword_cipher import *"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "challenge_number = 2\n",
+    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
+    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
+    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
+    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "ca = open(ciphertext_a_filename).read()\n",
+    "cb = open(ciphertext_b_filename).read()\n",
+    "scb = sanitise(cb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "19 18 True \n",
+      "\n",
+      "The decrypt of the first mission intercept has raised a number of questions about the spyclist operation, if that is what it is, but it has also triggered enquiries about the personnel referenced in that message. Our counterintelligence unit have asked me to task you with enquiries about the names mentioned there, in particular: Jessica; Wilhelm; Nikolaus; Tirpitzufer. It is possible that these are pseudonyms or code names, but they do not appear in our records and CI branch would be very interested in anything you can find out about them in relation to Nazi spy operations. I followed up on the SIS report that Hitler Youth groups travelling abroad were asked to complete a detailed questionnaire, checking if Harry had links that could help with this, and he sent me the attached message that was photographed by a BOSS undercover operative in Berlin. He told me that it had been exfiltrated from Abwehr headquarters and appears to be a request for approval for a new mission, though neither H nor I have had time to break it, so I look forward to receiving your decrypts. We believe the message has been enciphered using a keyword substitution cipher and given that we are not sure how serious the spyclist threat might be we would be grateful if you could decipher it quickly. The message was also a reminder to me that our own security is an important consideration, so I will also switch to a keyword substitution cipher for the next Mission Briefing. Pearl.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(m_a, a_a, o_a), score_a = affine_break(ca)\n",
+    "print(m_a, a_a, o_a, '\\n')\n",
+    "pa = affine_decipher(ca, m_a, a_a, o_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1471"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_a_filename, 'w').write(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "archerys KeywordWrapAlphabet.from_last \n",
+      "\n",
+      "attdctioc w our missioc to dmnde sympathisdrs ic thd ul dstanfishmdct is goicg wdff afthough thd rdkdct ickrdasd ic eipfomatik tdcsioc has sigcibikactfy ickrdasde thd risl bor our agdcts ic kommucikaticg with thdir hacefdrs. with tdfdgram trabbik ucedr dchackde supdrvisioc ny thd ul ictdffigdckd orgacisatiocs it is afso ickrdasicgfy eibbikuft bor thd agdcts ace thdir hacefdrs to rdpatriatd ictdffigdckd rdports ob acy sigcibikackd. thd usd ob naclicg kiphdrs is co focgdr rdgarede as sdkurd ace edspitd its onvious aevactagds, thd dcigma is too vafuanfd to us to affow its usd ndhice dcdmy ficds. bor cow, wd ard dckouragicg our agdcts to usd a mix ob ldywore ace tracspositioc kiphdrs as taught ic thdir nasik traicicg, sickd thdsd ard rdfianfd ace eo cot rdquird thd agdcts to nd ic possdssioc ob mord thac a sdrids ob ldy wores ace phrasds, whikh thdy ard wdff anfd to mdmorisd. as thd quactity ob sigcafs trabbik ickrdasds wd wiff cdde to rdkocsiedr our protokofs, nut bor cow i thicl our bokus shoufe nd oc edvdfopicg sdkurd kommucikatioc khaccdfs, with kut-outs to isofatd our mord vafuanfd assdts. i eiskussde this issud with my kouctdrpart ic edpartmdct ih who is a lddc kykfist ace hd maed a rathdr icgdcious suggdstioc that wd might mald gooe usd ob thd hitfdr youth. a cumndr ob partids havd nddc icvitde to visit thd ul oc kykficg tours ace hd hae nddc kocsiedricg aslicg thdm to rdkore icbormatioc anout thd fayout ob mifitary ace iceustriaf facemarls as part ob his ictdffigdckd gathdricg opdratioc. it is highfy fildfy that acy war wiff icvofvd a protraktde nomnicg kampaigc ace up to eatd maps wiff nd ob grdat vafud ic our pfaccicg. burthdrmord, thd kouctrysied roae fayouts ic thd ul ard cotorious bor thdir icdbbikidcky ace acy icvasioc, woufe nd sdvdrdfy hampdrde ny our fakl ob lcowfdegd ob tracsport cdtworls. hd hae erabtde ac appardctfy rathdr iccokuous artikfd bor thd cazi kykfist assokiatioc magazicd with a fist ob thicgs that our youcg kykfists might bice ictdrdsticg: imprdss oc your mdmory thd roaes ace paths, viffagds ace towcs, outstaceicg khurkh towdrs ace othdr facemarls so that you wiff cot borgdt thdm. mald a cotd ob thd camds, pfakds, rivdrs, sdas ace mouctaics. pdrhaps you may nd anfd to utifisd thdsd somd timd bor thd ndcdbit ob thd bathdrface. shoufe you komd to a nriegd whikh ictdrdsts you, dxamicd its kocstruktioc ace thd matdriafs usde. fdarc to mdasurd ace dstimatd thd wieth ob strdams. waed through bores so that you wiff nd anfd to bice thdm ic thd earl. i proposd that wd kocsiedr usicg thdsd assdts as thd kut-outs ndtwddc our ucedrkovdr agdcts ace thdir hacefdrs ic thd ul ace our kommucikatiocs cdtworl. thdy ard rdfativdfy brdd to movd arouce thd kouctry ace kac dasify nd traicde to usd erop-obbs ace othdr spykrabt to affow thdm to koffdkt ictdffigdckd rdports ace pass thdm oc. thd marvdffous postd rdstactd systdm affows us to kommucikatd with thdm, ace a suitanfd koednool woufe affow us to tracsmit icstruktiocs ic pfaic tdxt with co risl that thd mdacicg koufe nd eiskdrcde ny kouctdrictdffigdckd opdrativds ic thd postaf sdrvikd. i havd acothdr thought anout how wd might dxpfoit this cdtworl burthdr, howdvdr i cdde to worl through somd mord edtaifs ndbord i eiskuss it with you, ace i wactde to khdkl that you ard happy bor md to affokatd rdsourkds to traic a cumndr ob hitfdr youth ic thd rdquirde sliffs bor this opdratioc. cr.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)\n",
+    "print(word_b, wrap_b, '\\n')\n",
+    "pb = keyword_decipher(cb, word_b, wrap_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "abwehrstuvxyzcdfgijklmnopq \n",
+      "\n",
+      "attention w our mission to embed sympathisers in the uk establishment is going well although the recent increase in diplomatic tension has significantly increased the risk for our agents in communicating with their handlers. with telegram traffic under enhanced supervision by the uk intelligence organisations it is also increasingly difficult for the agents and their handlers to repatriate intelligence reports of any significance. the use of banking ciphers is no longer regarded as secure and despite its obvious advantages, the enigma is too valuable to us to allow its use behind enemy lines. for now, we are encouraging our agents to use a mix of keyword and transposition ciphers as taught in their basic training, since these are reliable and do not require the agents to be in possession of more than a series of key words and phrases, which they are well able to memorise. as the quantity of signals traffic increases we will need to reconsider our protocols, but for now i think our focus should be on developing secure communication channels, with cut-outs to isolate our more valuable assets. i discussed this issue with my counterpart in department ih who is a keen cyclist and he made a rather ingenious suggestion that we might make good use of the hitler youth. a number of parties have been invited to visit the uk on cycling tours and he had been considering asking them to record information about the layout of military and industrial landmarks as part of his intelligence gathering operation. it is highly likely that any war will involve a protracted bombing campaign and up to date maps will be of great value in our planning. furthermore, the countryside road layouts in the uk are notorious for their inefficiency and any invasion, would be severely hampered by our lack of knowledge of transport networks. he had drafted an apparently rather innocuous article for the nazi cyclist association magazine with a list of things that our young cyclists might find interesting: impress on your memory the roads and paths, villages and towns, outstanding church towers and other landmarks so that you will not forget them. make a note of the names, places, rivers, seas and mountains. perhaps you may be able to utilise these some time for the benefit of the fatherland. should you come to a bridge which interests you, examine its construction and the materials used. learn to measure and estimate the width of streams. wade through fords so that you will be able to find them in the dark. i propose that we consider using these assets as the cut-outs between our undercover agents and their handlers in the uk and our communications network. they are relatively free to move around the country and can easily be trained to use drop-offs and other spycraft to allow them to collect intelligence reports and pass them on. the marvellous poste restante system allows us to communicate with them, and a suitable codebook would allow us to transmit instructions in plain text with no risk that the meaning could be discerned by counterintelligence operatives in the postal service. i have another thought about how we might exploit this network further, however i need to work through some more details before i discuss it with you, and i wanted to check that you are happy for me to allocate resources to train a number of hitler youth in the required skills for this operation. nr.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "word_b, score_b = simulated_annealing_break(scb)\n",
+    "print(word_b, '\\n')\n",
+    "pb = keyword_decipher(cb, word_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'attention w our mission to embed sympathisers in the uk establishment is going well although the recent increase in diplomatic tension has significantly increased the risk for our agents in communicating with their handlers. with telegram traffic under enhanced supervision by the uk intelligence organisations it is also increasingly difficult for the agents and their handlers to repatriate intelligence reports of any significance. the use of banking ciphers is no longer regarded as secure and despite its obvious advantages, the enigma is too valuable to us to allow its use behind enemy lines. for now, we are encouraging our agents to use a mix of keyword and transposition ciphers as taught in their basic training, since these are reliable and do not require the agents to be in possession of more than a series of key words and phrases, which they are well able to memorise. as the quantity of signals traffic increases we will need to reconsider our protocols, but for now i think our focus should be on developing secure communication channels, with cut-outs to isolate our more valuable assets. i discussed this issue with my counterpart in department ih who is a keen cyclist and he made a rather ingenious suggestion that we might make good use of the hitler youth. a number of parties have been invited to visit the uk on cycling tours and he had been considering asking them to record information about the layout of military and industrial landmarks as part of his intelligence gathering operation. it is highly likely that any war will involve a protracted bombing campaign and up to date maps will be of great value in our planning. furthermore, the countryside road layouts in the uk are notorious for their inefficiency and any invasion, would be severely hampered by our lack of knowledge of transport networks. he had drafted an apparently rather innocuous article for the nazi cyclist association magazine with a list of things that our young cyclists might find interesting: impress on your memory the roads and paths, villages and towns, outstanding church towers and other landmarks so that you will not forget them. make a note of the names, places, rivers, seas and mountains. perhaps you may be able to utilise these some time for the benefit of the fatherland. should you come to a bridge which interests you, examine its construction and the materials used. learn to measure and estimate the width of streams. wade through fords so that you will be able to find them in the dark. i propose that we consider using these assets as the cut-outs between our undercover agents and their handlers in the uk and our communications network. they are relatively free to move around the country and can easily be trained to use drop-offs and other spycraft to allow them to collect intelligence reports and pass them on. the marvellous poste restante system allows us to communicate with them, and a suitable codebook would allow us to transmit instructions in plain text with no risk that the meaning could be discerned by counterintelligence operatives in the postal service. i have another thought about how we might exploit this network further, however i need to work through some more details before i discuss it with you, and i wanted to check that you are happy for me to allocate resources to train a number of hitler youth in the required skills for this operation. nr.\\n'"
+      ]
+     },
+     "execution_count": 19,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "keyword_decipher(cb, 'abwehr', KeywordWrapAlphabet.from_last)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "3403"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "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
+}
diff --git a/2020/2020-challenge2.md b/2020/2020-challenge2.md
new file mode 100644 (file)
index 0000000..80efcc4
--- /dev/null
@@ -0,0 +1,70 @@
+---
+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 Collapsed="false"
+from szyfrow.affine import *
+from szyfrow.keyword_cipher import *
+```
+
+```python Collapsed="false"
+challenge_number = 2
+plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
+plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
+ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
+ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
+```
+
+```python Collapsed="false"
+ca = open(ciphertext_a_filename).read()
+cb = open(ciphertext_b_filename).read()
+scb = sanitise(cb)
+```
+
+```python Collapsed="false"
+(m_a, a_a, o_a), score_a = affine_break(ca)
+print(m_a, a_a, o_a, '\n')
+pa = affine_decipher(ca, m_a, a_a, o_a)
+print(pa)
+```
+
+```python Collapsed="false"
+open(plaintext_a_filename, 'w').write(pa)
+```
+
+```python Collapsed="false"
+(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)
+print(word_b, wrap_b, '\n')
+pb = keyword_decipher(cb, word_b, wrap_b)
+print(pb)
+```
+
+```python Collapsed="false"
+word_b, score_b = simulated_annealing_break(scb)
+print(word_b, '\n')
+pb = keyword_decipher(cb, word_b)
+print(pb)
+```
+
+```python Collapsed="false"
+keyword_decipher(cb, 'abwehr', KeywordWrapAlphabet.from_last)
+```
+
+```python Collapsed="false"
+open(plaintext_b_filename, 'w').write(pb)
+```
+
+```python Collapsed="false"
+
+```
diff --git a/2020/2020-challenge3.ipynb b/2020/2020-challenge3.ipynb
new file mode 100644 (file)
index 0000000..ccb356e
--- /dev/null
@@ -0,0 +1,236 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "from szyfrow.affine import *\n",
+    "from szyfrow.keyword_cipher import *"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "challenge_number = 3\n",
+    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
+    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
+    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
+    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "ca = open(ciphertext_a_filename).read()\n",
+    "sca = sanitise(ca)\n",
+    "cb = open(ciphertext_b_filename).read()\n",
+    "scb = sanitise(cb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "vern KeywordWrapAlphabet.from_last \n",
+      "\n",
+      "thanks to everyone for their work on the intercept, it looks really important and i have discussed the contents with harry. our sources in germany have confirmed that the nca magazine carried the instructions issued by ih and nr, and vk wrote to the chief constables of local police forces requesting them to keep an eye out for the touring groups and to report on any matters of interest. special branch are coordinating intelligence activities and forwarded a report from the local constabulary in norfolk detailing activity by one of the touring cycling parties who were seen taking photographs and sketching the landscape at caistor st edmund. the local constable questioned them, but they were not held as there were no grounds for an arrest. they had arrived at harwich and were apparently touring norfolk at the invitation of a local scout group before heading to london.\n",
+      "while there are significant defence installations in that area, caistor st edmund seems an unlikely target for german intelligence so perhaps this is innocent, but the evidence we have so far suggests that that is unlikely. another possibility is that it is a red herring operation disguising the activities of other groups, but just in case i will make enquiries with our sister agencies to see if there is anything we should know about in that area.\n",
+      "i asked our agents in norfolk to report on unusual activity and sent them a list of keywords that should trigger investigation. they forwarded the attached message addressed to tirpitzufer, which was left at the caistor st edmund post office by the local scoutmaster. it was in a bulky packet containing a number of sketches of the area together with an encrypted message which we need you to decipher quickly. analysis of other communication intercepts have suggested that this message may also contain a key to future communications across the spyclist network so you should spend some time thinking about it once you have submitted the decrypt.\n",
+      "while the mission of the spyclists is spelled out in detail in the last decrypt, it is still not clear what the larger aims of the abwehr mission might be, but your research into wilhelm and nikolaus has probably led you to the same conclusion as me: this is a high-level mission and is likely to pose a significant threat to our security. it follows that we should increase our own security to prevent nazi code breakers from reading our messages, so i will lengthen the keyword in my next mission briefing. i will also review our communication protocols for subsequent messages with harry and will update you on the standards to use in mission briefing 4.\n",
+      "the report from norfolk gave me an idea about how we could gather intelligence on the spyclist network. harry and i discussed this with vk since it carries a number of risks, but vk approved the strategy which we have given the codename the akela initiative. more to follow.\n",
+      "pearl\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)\n",
+    "print(word_a, wrap_a, '\\n')\n",
+    "pa = keyword_decipher(ca, word_a, wrap_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "2918"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_a_filename, 'w').write(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "croatias KeywordWrapAlphabet.from_last \n",
+      "\n",
+      "gear unfle wilhelm,\n",
+      "i trust that you ang the camily at tirpitzucer are all well ang that you enjoyeg the sketfhes i sent you last week. i have enfloseg my most refent impressions oc the deauticul, ic somewhat stark langsfape in norcolk. i hope ang delieve that you will cing them oc breat interest. the clat ang open cielgs have a spartan deauty punftuateg dy just a cew langmarks oc gistinftion, dut their isolation makes them stang out even more ang infreases their interest.\n",
+      "our hosts have deen most abreeadle ang even the lofal polife corfe have deen as affommogatinb as you subbesteg they woulg de. the lofal fonstadle seemeg most interesteg in our photobraphif hoddy, dut he appeareg to de fontent with the explanation oc our interest in their deauticul fountrysige ang villabes. he was also very apprefiative oc our roubh sketfhes oc their strikinb langsfape, thoubh he gig seem surpriseg at the numder oc grawinbs we have mage oc the cielgs aroung faistor st egmung, subbestinb that its sibnicifanfe is not wigely known.\n",
+      "the lofal sfoutmaster abreeg to pass this messabe to you ang has also arranbeg cor our corwarg travel. we will heag next to longon to meet with my fousin nikolaus decore preparinb cor the sefong stabe oc our little agventure. ic you have any curther requests cor incormation or aggitional grawinbs in this extraorginary part oc the worlg then please go make sure to let me know decore we gepart.\n",
+      "let me cinish with a little puzzle cor you. fan you cing an eibht letter enblish worg whifh you fan fhanbe dy alterinb the orger oc its letters to progufe cour other giccerent enblish worgs?\n",
+      "yours sinferely,\n",
+      "otto\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)\n",
+    "print(word_b, wrap_b, '\\n')\n",
+    "pb = keyword_decipher(cb, word_b, wrap_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "caistoruvwxyzbdefghjklmnpq \n",
+      "\n",
+      "dear uncle wilhelm,\n",
+      "i trust that you and the family at tirpitzufer are all well and that you enjoyed the sketches i sent you last week. i have enclosed my most recent impressions of the beautiful, if somewhat stark landscape in norfolk. i hope and believe that you will find them of great interest. the flat and open fields have a spartan beauty punctuated by just a few landmarks of distinction, but their isolation makes them stand out even more and increases their interest.\n",
+      "our hosts have been most agreeable and even the local police force have been as accommodating as you suggested they would be. the local constable seemed most interested in our photographic hobby, but he appeared to be content with the explanation of our interest in their beautiful countryside and villages. he was also very appreciative of our rough sketches of their striking landscape, though he did seem surprised at the number of drawings we have made of the fields around caistor st edmund, suggesting that its significance is not widely known.\n",
+      "the local scoutmaster agreed to pass this message to you and has also arranged for our forward travel. we will head next to london to meet with my cousin nikolaus before preparing for the second stage of our little adventure. if you have any further requests for information or additional drawings in this extraordinary part of the world then please do make sure to let me know before we depart.\n",
+      "let me finish with a little puzzle for you. can you find an eight letter english word which you can change by altering the order of its letters to produce four other different english words?\n",
+      "yours sincerely,\n",
+      "otto\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "word_b, score_b = simulated_annealing_break(scb, fitness=Ptrigrams)\n",
+    "print(word_b, '\\n')\n",
+    "pb = keyword_decipher(cb, word_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'dear uncle wilhelm,\\ni trust that you and the family at tirpitzufer are all well and that you enjoyed the sketches i sent you last week. i have enclosed my most recent impressions of the beautiful, if somewhat stark landscape in norfolk. i hope and believe that you will find them of great interest. the flat and open fields have a spartan beauty punctuated by just a few landmarks of distinction, but their isolation makes them stand out even more and increases their interest.\\nour hosts have been most agreeable and even the local police force have been as accommodating as you suggested they would be. the local constable seemed most interested in our photographic hobby, but he appeared to be content with the explanation of our interest in their beautiful countryside and villages. he was also very appreciative of our rough sketches of their striking landscape, though he did seem surprised at the number of drawings we have made of the fields around caistor st edmund, suggesting that its significance is not widely known.\\nthe local scoutmaster agreed to pass this message to you and has also arranged for our forward travel. we will head next to london to meet with my cousin nikolaus before preparing for the second stage of our little adventure. if you have any further requests for information or additional drawings in this extraordinary part of the world then please do make sure to let me know before we depart.\\nlet me finish with a little puzzle for you. can you find an eight letter english word which you can change by altering the order of its letters to produce four other different english words?\\nyours sincerely,\\notto\\n'"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "keyword_decipher(cb, 'caistor', KeywordWrapAlphabet.from_last)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1638"
+      ]
+     },
+     "execution_count": 13,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "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
+}
diff --git a/2020/2020-challenge3.md b/2020/2020-challenge3.md
new file mode 100644 (file)
index 0000000..05bb180
--- /dev/null
@@ -0,0 +1,71 @@
+---
+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 Collapsed="false"
+from szyfrow.affine import *
+from szyfrow.keyword_cipher import *
+```
+
+```python Collapsed="false"
+challenge_number = 3
+plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
+plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
+ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
+ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
+```
+
+```python Collapsed="false"
+ca = open(ciphertext_a_filename).read()
+sca = sanitise(ca)
+cb = open(ciphertext_b_filename).read()
+scb = sanitise(cb)
+```
+
+```python Collapsed="false"
+(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)
+print(word_a, wrap_a, '\n')
+pa = keyword_decipher(ca, word_a, wrap_a)
+print(pa)
+```
+
+```python Collapsed="false"
+open(plaintext_a_filename, 'w').write(pa)
+```
+
+```python Collapsed="false"
+(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)
+print(word_b, wrap_b, '\n')
+pb = keyword_decipher(cb, word_b, wrap_b)
+print(pb)
+```
+
+```python Collapsed="false"
+word_b, score_b = simulated_annealing_break(scb, fitness=Ptrigrams)
+print(word_b, '\n')
+pb = keyword_decipher(cb, word_b)
+print(pb)
+```
+
+```python Collapsed="false"
+keyword_decipher(cb, 'caistor', KeywordWrapAlphabet.from_last)
+```
+
+```python Collapsed="false"
+open(plaintext_b_filename, 'w').write(pb)
+```
+
+```python Collapsed="false"
+
+```
diff --git a/2020/2020-challenge4.ipynb b/2020/2020-challenge4.ipynb
new file mode 100644 (file)
index 0000000..19f01c1
--- /dev/null
@@ -0,0 +1,434 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "from szyfrow.keyword_cipher import *\n",
+    "from szyfrow.column_transposition import *\n",
+    "from szyfrow.support.text_prettify import *"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "challenge_number = 4\n",
+    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
+    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
+    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
+    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "ca = open(ciphertext_a_filename).read()\n",
+    "sca = sanitise(ca)\n",
+    "cb = open(ciphertext_b_filename).read()\n",
+    "scb = sanitise(cb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "akkad KeywordWrapAlphabet.from_largest \n",
+      "\n",
+      "i have drawn a blank in my enqciries aboct uaistor st edmcnd and even harry is getting nowhere with his uontauts in the mod. we both agree that the silenue is very worrying. this is ulearly an area of interest as it presents a urcuial front in any potential invasion so we wocld have expeuted some interest in ocr intelligenue, or at least some pcsh bauk warning cs to keep away from basiu defenue installations like listening posts. the faut that no-one wants to talk aboct the fauilities in the area scggests that it is all very hcsh hcsh. something important is happening there and we probably want to find oct what.\n",
+      "\n",
+      "ocr agents in london kept watuh for the tocring party and reuorded them as arriving at liverpool street. the grocp uonsisted of twenty three uyulists who split cp and stayed with members of loual suoct grocps while their leader was hosted by a member of the loual ortsgrcppe. we reueived reports from k's network that the grocp has been invited to stay with the spalding rotary ulcb in linuoln and we need yoc to investigate any reports yoc uan find aboct that visit. i will uontince to press for information aboct strategiu developments in norwiuh and norfolk.\n",
+      "\n",
+      "the akela initiative has been given approval and i will be setting that cp this week. the intention is to enroll leaders and members of loual suoct grocps, train them in uocnter-intelligenue and cse them to host the spyulist tocring grocps in the hope of getting inside their operation. sinue fctcre uommcniuations may inulcde sensitive operational details of this initiative i intend to inurease seucrity by moving to a blouked keyword uipher.\n",
+      "\n",
+      "the attauhed doucment was interuepted by ocr london agents when the party posted it on arrival at liverpool street. as cscal it was addressed to tirpitzcfer. primary analysis scggests that it does not cse a scbstitction uipher.\n",
+      "\n",
+      "more to follow.\n",
+      "\n",
+      "pearl.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)\n",
+    "print(word_a, wrap_a, '\\n')\n",
+    "pa = keyword_decipher(ca, word_a, wrap_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "akelmnopqrstuvwxyzbcdfghij \n",
+      "\n",
+      "i have drawn a blank in my enquiries about caistor st edmund and even harry is getting nowhere with his contacts in the mod. we both agree that the silence is very worrying. this is clearly an area of interest as it presents a crucial front in any potential invasion so we would have expected some interest in our intelligence, or at least some push back warning us to keep away from basic defence installations like listening posts. the fact that no-one wants to talk about the facilities in the area suggests that it is all very hush hush. something important is happening there and we probably want to find out what.\n",
+      "\n",
+      "our agents in london kept watch for the touring party and recorded them as arriving at liverpool street. the group consisted of twenty three cyclists who split up and stayed with members of local scout groups while their leader was hosted by a member of the local ortsgruppe. we received reports from k's network that the group has been invited to stay with the spalding rotary club in lincoln and we need you to investigate any reports you can find about that visit. i will continue to press for information about strategic developments in norwich and norfolk.\n",
+      "\n",
+      "the akela initiative has been given approval and i will be setting that up this week. the intention is to enroll leaders and members of local scout groups, train them in counter-intelligence and use them to host the spyclist touring groups in the hope of getting inside their operation. since future communications may include sensitive operational details of this initiative i intend to increase security by moving to a blocked keyword cipher.\n",
+      "\n",
+      "the attached document was intercepted by our london agents when the party posted it on arrival at liverpool street. as usual it was addressed to tirpitzufer. primary analysis suggests that it does not use a substitution cipher.\n",
+      "\n",
+      "more to follow.\n",
+      "\n",
+      "pearl.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "word_a, score_a = simulated_annealing_break(sca, fitness=Ptrigrams,\n",
+    "        plain_alphabet=string.ascii_lowercase, cipher_alphabet=keyword_cipher_alphabet_of('akkad', wrap_alphabet=KeywordWrapAlphabet.from_largest))\n",
+    "print(word_a, '\\n')\n",
+    "pa = keyword_decipher(ca, word_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "i have drawn a blank in my enquiries about caistor st edmund and even harry is getting nowhere with his contacts in the mod. we both agree that the silence is very worrying. this is clearly an area of interest as it presents a crucial front in any potential invasion so we would have expected some interest in our intelligence, or at least some push back warning us to keep away from basic defence installations like listening posts. the fact that no-one wants to talk about the facilities in the area suggests that it is all very hush hush. something important is happening there and we probably want to find out what.\n",
+      "\n",
+      "our agents in london kept watch for the touring party and recorded them as arriving at liverpool street. the group consisted of twenty three cyclists who split up and stayed with members of local scout groups while their leader was hosted by a member of the local ortsgruppe. we received reports from k's network that the group has been invited to stay with the spalding rotary club in lincoln and we need you to investigate any reports you can find about that visit. i will continue to press for information about strategic developments in norwich and norfolk.\n",
+      "\n",
+      "the akela initiative has been given approval and i will be setting that up this week. the intention is to enroll leaders and members of local scout groups, train them in counter-intelligence and use them to host the spyclist touring groups in the hope of getting inside their operation. since future communications may include sensitive operational details of this initiative i intend to increase security by moving to a blocked keyword cipher.\n",
+      "\n",
+      "the attached document was intercepted by our london agents when the party posted it on arrival at liverpool street. as usual it was addressed to tirpitzufer. primary analysis suggests that it does not use a substitution cipher.\n",
+      "\n",
+      "more to follow.\n",
+      "\n",
+      "pearl.\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "pa = keyword_decipher(ca, 'akela', wrap_alphabet=KeywordWrapAlphabet.from_largest)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1883"
+      ]
+     },
+     "execution_count": 7,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_a_filename, 'w').write(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "clue_dict = ['alerting', 'altering', 'integral', 'relating', 'triangle', 'angriest', 'gantries', 'granites', 'ingrates', 'rangiest', 'tangiers', \n",
+    "             'dniester', 'inserted', 'nerdiest', 'resident', 'trendies', 'respects', 'scepters', 'sceptres', 'specters', 'spectres', 'restrain', \n",
+    "             'retrains', 'strainer', 'terrains', 'trainers']\n",
+    "clue_trans = [transpositions_of(w) for w in clue_dict]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(1, 2, 3, 5, 0, 4) True False \n",
+      "\n",
+      "REERNLNHNRTAANNBSCROIAUSHOALISICTETSIEAARASTSOSLNOIOOWESEIOGMHISTXDIEGEAGATTADRVSICAYSITREARESOFNCFFWPNSPPTNTAELHYBNRRAMNSMSXOENGPNINFAFOGDLOMENOORHNTNERMTATFTWATFAESOGRYNCSHSENTEDAOTRKIBPPARHCERRTTHNNTGIREITMVHEDCONTCTUWPDOIROENHEGIKIATNCWLNODRSSNTEOGAFREBTAEHOLWHOSSITPTRNCUNLECLOUTDSTHNTSLLHTRTGNDCRERSESALLBEOCOAUEOEOUAEHIDVADSAHETISIVTGLNNESTTPCIWUFRAETIRHIIWFLEREYTEEOKHYRFOTIRERNERTSFIILFCINYTSALGAHHSDIVSLLSUTWSTELNPOOSISOSHAYNEGNLOGTORDTHTRRORRSDISUEOEIALSTKGASPUNBNLUMYIIBSIELHEEAIGIRISSCRCVNATGTYIOIAIUTTEANNNURSCMMHEEAPEOIRIRTESOODTHILWCESTTYSRALHUROOSAAGRRIOEIAHHFSOYTRMATSEAUSNKVVSWTLSNTDONOENFTYMRHTCNETHLDEWWHSPHNSTALNIIEEETTAFTASSFHASRAEOSEPUEOXAOOHHTTTNIEENYAIOYATVIEIISEOLIYGEIEIROTPUTASARUETHONOIPNIHUUTOEHIUNTUWISTNRYNSREAOUNCTEMFEIFGEISNRHOCYORTRLANATASOYHIFTHHHAGMNTNMWOICTPIRAEEAIARNNLDUNYFEHRYURTOONDIONTAOOIEUWLJEOWODMHITGGRHKOPENNIEAYMMANETIRPDRBYACCRPUTOHRSRSIMOBSUMEOWPHTATORENNBHHNTAIHNALIDCOOLWOPUFODIFAEOIFELITHNBEEAEOSTNIDIERILBDOAQTEVGEUEWLUEIDSRBEDEDAETHVBOTISHTTNTMEWOSTFEEDCODTDUMEATLISLOETVOLSHIJGETTASAHEIEBIHFSERHNHREROOUDDTTTTYGNATOHAGWIVISGTACENOIRUHRNAUDAEUTPNHYPETSRCY                                                                                                                                                                                                                                                                                     \n",
+      "DNIMOYNARCIENTATITSUELDTDIDBOPBPSHRAREYLTVROYERSNAGEUTTBFRHTONUIEEFYHRUXGEOEEDHCTETPCTIUTUVAMLRNLTTERRRTONOOHEDUOCSRFAAOTINWENEETSNUISIEASSEURHNOUTRRSRTSTHEEERELSESYTEETIUTIOIAIARMHISEMBIECISSSREMIEOAOLNOIDPLESCYUNATMROETIOIMNUTANSHHHOHTKOUENONOIAUTHRHSNRTATEEPPCFRMRSAGASOSEESE\n"
+     ]
+    }
+   ],
+   "source": [
+    "(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, translist=clue_trans, fitness=Ptrigrams)\n",
+    "print(trans_b, fill_b, empty_b, '\\n')\n",
+    "pb = column_transposition_decipher(cb, trans_b, \n",
+    "    fillcolumnwise=fill_b,\n",
+    "    emptycolumnwise=empty_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 22,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "(1, 2, 4, 0, 3) False False \n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, fitness=Ptrigrams)\n",
+    "print(trans_b, fill_b, empty_b, '\\n')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "dear uncle wilhelm our journey to london was short and charming the trains rattling along the\n",
+      "british tracks through open fields and countryside their roads maybe almost impassable in places but\n",
+      "these iron tracks provide a very usable way to travel across country at speed our hosts in london\n",
+      "have organised for us to stay with members of the british scouting movement though i will spend the\n",
+      "next few days with the orts gruppe exchanging news about the fatherland and their activities herein\n",
+      "the capital city it was difficult to tear ourselves away from the pleasures of norfolk and the city\n",
+      "offers far fewer opportunities for open exploration on the other hand the bustle of the city as in\n",
+      "berlin offers a certain anonymity and it is in some ways relaxing to leave behind the gossip and\n",
+      "inquisitiveness of village life as you suggested we will use our time herein london to support our\n",
+      "brothers and sisters and to reassure them that they have not been forgotten i will pass on the gifts\n",
+      "that you entrusted to me together with your instructions for their use as we did in caistor st\n",
+      "edmund the radio you sent me is remarkable it is able to pickup signals across the spectrum even\n",
+      "from berlin itself though i am enjoying listening to british radio especially the home service they\n",
+      "are building a chain of transmitters across the country which provide information throughout the day\n",
+      "and night something that i think you might want to take into account when planning our own radio\n",
+      "services i am assuming that there are no changes planned for our itinerary but if there are then\n",
+      "perhaps you could forward them to our hosts in spalding with a copy sent post restante to cse yours\n",
+      "sincerely\n"
+     ]
+    }
+   ],
+   "source": [
+    "pb = prettify(column_transposition_decipher(scb, trans_b, \n",
+    "    fillcolumnwise=fill_b,\n",
+    "    emptycolumnwise=empty_b))\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 20,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['fable',\n",
+       " 'gable',\n",
+       " 'nacre',\n",
+       " 'nahum',\n",
+       " 'oakum',\n",
+       " 'odium',\n",
+       " 'padre',\n",
+       " 'pinto',\n",
+       " 'salvo',\n",
+       " 'santo',\n",
+       " 'scour',\n",
+       " 'tabus',\n",
+       " 'tagus',\n",
+       " 'talus',\n",
+       " 'thous',\n",
+       " 'timur',\n",
+       " 'torus',\n",
+       " 'torys',\n",
+       " 'whizs',\n",
+       " 'gabble',\n",
+       " 'kabuki',\n",
+       " 'lactic',\n",
+       " 'ladoga',\n",
+       " 'leftie',\n",
+       " 'madrid',\n",
+       " 'megohm',\n",
+       " 'oberon',\n",
+       " 'raisin',\n",
+       " 'refuel',\n",
+       " 'refuge',\n",
+       " 'salvos',\n",
+       " 'santos',\n",
+       " 'scours',\n",
+       " 'tabbys',\n",
+       " 'tabula',\n",
+       " 'taffys',\n",
+       " 'taguss',\n",
+       " 'taiwan',\n",
+       " 'tallys',\n",
+       " 'tammys',\n",
+       " 'tanyas',\n",
+       " 'telexs',\n",
+       " 'tenure',\n",
+       " 'terrys',\n",
+       " 'tethys',\n",
+       " 'thrush',\n",
+       " 'thrust',\n",
+       " 'timmys',\n",
+       " 'toruss',\n",
+       " 'velezs',\n",
+       " 'vilyui',\n",
+       " 'weepys',\n",
+       " 'whizzs',\n",
+       " 'willys',\n",
+       " 'worrys',\n",
+       " 'lactate',\n",
+       " 'macrame',\n",
+       " 'palazzo',\n",
+       " 'raisins',\n",
+       " 'raritan',\n",
+       " 'refresh',\n",
+       " 'refugee',\n",
+       " 'sabbath',\n",
+       " 'salazar',\n",
+       " 'sinuous',\n",
+       " 'tactual',\n",
+       " 'tarawas',\n",
+       " 'telexes',\n",
+       " 'tethyss',\n",
+       " 'thrushs',\n",
+       " 'thrusts',\n",
+       " 'maharaja',\n",
+       " 'nakayama',\n",
+       " 'ramayana',\n",
+       " 'sabbaths',\n",
+       " 'salazars',\n",
+       " 'semester',\n",
+       " 'sensuous',\n",
+       " 'teletype',\n",
+       " 'tortuous',\n",
+       " 'maharajah',\n",
+       " 'refresher',\n",
+       " 'refreshes',\n",
+       " 'semesters',\n",
+       " 'refreshers',\n",
+       " 'sensuousness',\n",
+       " 'sensuousnesss']"
+      ]
+     },
+     "execution_count": 20,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "transpositions[trans_b]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1685"
+      ]
+     },
+     "execution_count": 21,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "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
+}
diff --git a/2020/2020-challenge4.md b/2020/2020-challenge4.md
new file mode 100644 (file)
index 0000000..032af74
--- /dev/null
@@ -0,0 +1,99 @@
+---
+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 Collapsed="false"
+from szyfrow.keyword_cipher import *
+from szyfrow.column_transposition import *
+from szyfrow.support.text_prettify import *
+```
+
+```python Collapsed="false"
+challenge_number = 4
+plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
+plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
+ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
+ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
+```
+
+```python Collapsed="false"
+ca = open(ciphertext_a_filename).read()
+sca = sanitise(ca)
+cb = open(ciphertext_b_filename).read()
+scb = sanitise(cb)
+```
+
+```python Collapsed="false"
+(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)
+print(word_a, wrap_a, '\n')
+pa = keyword_decipher(ca, word_a, wrap_a)
+print(pa)
+```
+
+```python Collapsed="false"
+word_a, score_a = simulated_annealing_break(sca, fitness=Ptrigrams,
+        plain_alphabet=string.ascii_lowercase, cipher_alphabet=keyword_cipher_alphabet_of('akkad', wrap_alphabet=KeywordWrapAlphabet.from_largest))
+print(word_a, '\n')
+pa = keyword_decipher(ca, word_a)
+print(pa)
+```
+
+```python Collapsed="false"
+pa = keyword_decipher(ca, 'akela', wrap_alphabet=KeywordWrapAlphabet.from_largest)
+print(pa)
+```
+
+```python Collapsed="false"
+open(plaintext_a_filename, 'w').write(pa)
+```
+
+```python Collapsed="false"
+clue_dict = ['alerting', 'altering', 'integral', 'relating', 'triangle', 'angriest', 'gantries', 'granites', 'ingrates', 'rangiest', 'tangiers', 
+             'dniester', 'inserted', 'nerdiest', 'resident', 'trendies', 'respects', 'scepters', 'sceptres', 'specters', 'spectres', 'restrain', 
+             'retrains', 'strainer', 'terrains', 'trainers']
+clue_trans = [transpositions_of(w) for w in clue_dict]
+```
+
+```python Collapsed="false"
+(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, translist=clue_trans, fitness=Ptrigrams)
+print(trans_b, fill_b, empty_b, '\n')
+pb = column_transposition_decipher(cb, trans_b, 
+    fillcolumnwise=fill_b,
+    emptycolumnwise=empty_b)
+print(pb)
+```
+
+```python Collapsed="false"
+(trans_b, fill_b, empty_b), score_b = column_transposition_break(scb, fitness=Ptrigrams)
+print(trans_b, fill_b, empty_b, '\n')
+```
+
+```python Collapsed="false"
+pb = prettify(column_transposition_decipher(scb, trans_b, 
+    fillcolumnwise=fill_b,
+    emptycolumnwise=empty_b))
+print(pb)
+```
+
+```python Collapsed="false"
+transpositions[trans_b]
+```
+
+```python Collapsed="false"
+open(plaintext_b_filename, 'w').write(pb)
+```
+
+```python Collapsed="false"
+
+```
diff --git a/2020/2020-challenge5.ipynb b/2020/2020-challenge5.ipynb
new file mode 100644 (file)
index 0000000..0023d1c
--- /dev/null
@@ -0,0 +1,593 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "from szyfrow.keyword_cipher import *\n",
+    "from szyfrow.column_transposition import *\n",
+    "from szyfrow.support.text_prettify import *"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "challenge_number = 5\n",
+    "plaintext_a_filename = f'plaintext.{challenge_number}a.txt'\n",
+    "plaintext_b_filename = f'plaintext.{challenge_number}b.txt'\n",
+    "ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'\n",
+    "ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [],
+   "source": [
+    "ca = open(ciphertext_a_filename).read()\n",
+    "sca = sanitise(ca)\n",
+    "cb = open(ciphertext_b_filename).read()\n",
+    "scb = sanitise(cb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "aile KeywordWrapAlphabet.from_a \n",
+      "\n",
+      "whike wecic notha vetim etopk adean ytrai necag entsw ithth ekonc onsdo utgro upsth eabek aoper ation cicma naget oredr uitan clrie fseve rakme mlers ofthe kindo knsdo uting assod iatio nanco neoft hemha smace amajo rlrea bthro ughsp ottin gsome thing thato urreg ukara gents hacno tnoti decth ekonc onpar tydon siste coftw entyt hreed ydkis tslut thegr oupar rivin ginki ndokn hacon kytwe ntyme mlers atfir stias sumec hehac misdo untec lutth ephot ograp hinth ekoda kpape raddo mpany ingth eirre porto nthev isitd onfir mecth enuml eriwi kkmab eenqu iries witho urkon conag entst oseei fthey havea nythi ngont heoth erthr eeanc wikkl riefy ouont hatne xttim etheg roupw astra dbeca sthey retur necso uthsp kitup ancvi sitec adhai nofes sexan cbent vikka gesak ongth etham eslut cespi tethe irdon tinui ngint erest inkan cmarb snoth ingol vious inthe irleh aviou rsugg estec anypa rtidu karpk anthe north erngr oupar enows tayin gwith sdout sinda newco nanca bekah asred ruite coneo fthem tospy onthe party ourai rmini stryd ontad tsare indre asing kyaka rmeca loutt hespy dkist sluta resti kknot prepa recto tekku swhat itist hatis worry ingth emthe yarep artid ukark yagit ateca loutt hepre sende atdai stora ncnow atdan ewcon ancth isdon derna louta dtivi tyine astan gkiaa ncess exmab esmew oncer ifiti sdonn edtec witha ircef endef orthe dapit aklut theya reref using totek kanci twikk lehar cforu stohe kpthe mifth eywon ttekk uswha twear esupp osect olepr otedt ingth eatta dhect ekegr amwas dopie clyan abeka agent inspa kcing hissi sterw orbsa tthet ekegr aphyo ffide ancga vehim addes sthem essag ewasc ekive recly oneof thesp ydkis tsanc ondem oreit wasac cress ectow ikhek minti rpitz ufert hespy dkist shave rever tecto asuls titut iondi pherf orthi smess agelu tlkod becit tocis guise theme ssage strud turet hatma ceita kotha rcert odrad bluti amgka cicic ithas asedr etmes sageh iccen inthe cedip herec textw hidhs ugges tstha tthes pydki stmis sioni sdkos ingon itsai msiam notsu rewha tthei nitia ksrcf stanc forlu tiwik kgola dbtot heair minis tryto asbif theyh avean ysugg estio nsiti sakso dkear fromt hedon tents ofthi smess ageth atthe germa nsare getti ngaki ttkes uspid iouss owewi kknee ctost epupo urown sedur ityiw ikkse ncmyn extlr iefin gusin gavig enere diphe rwith beyke ngtht hreem oreto fokko wpear k\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)\n",
+    "print(word_a, wrap_a, '\\n')\n",
+    "pa = keyword_decipher(ca, word_a, wrap_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'while wedid notha vetim etopl acean ytrai nedag entsw ithth elond onsco utgro upsth eakel aoper ation didma naget orecr uitan dbrie fseve ralme mbers ofthe linco lnsco uting assoc iatio nando neoft hemha smade amajo rbrea kthro ughsp ottin gsome thing thato urreg ulara gents hadno tnoti cedth elond onpar tycon siste doftw entyt hreec yclis tsbut thegr oupar rivin ginli ncoln hadon lytwe ntyme mbers atfir stias sumed hehad misco unted butth ephot ograp hinth eloca lpape racco mpany ingth eirre porto nthev isitc onfir medth enumb eriwi llmak eenqu iries witho urlon donag entst oseei fthey havea nythi ngont heoth erthr eeand willb riefy ouont hatne xttim etheg roupw astra ckeda sthey retur nedso uthsp litup andvi sited achai nofes sexan dkent villa gesal ongth etham esbut despi tethe ircon tinui ngint erest inlan dmark snoth ingob vious inthe irbeh aviou rsugg ested anypa rticu larpl anthe north erngr oupar enows tayin gwith scout sinca newdo nanda kelah asrec ruite doneo fthem tospy onthe party ourai rmini stryc ontac tsare incre asing lyala rmeda boutt hespy clist sbuta resti llnot prepa redto tellu swhat itist hatis worry ingth emthe yarep artic ularl yagit ateda boutt hepre sence atcai stora ndnow atcan ewdon andth iscon cerna bouta ctivi tyine astan gliaa ndess exmak esmew onder ifiti sconn ected witha irdef encef orthe capit albut theya reref using totel landi twill behar dforu stohe lpthe mifth eywon ttell uswha twear esupp osedt obepr otect ingth eatta chedt elegr amwas copie dbyan akela agent inspa lding hissi sterw orksa tthet elegr aphyo ffice andga vehim acces sthem essag ewasd elive redby oneof thesp yclis tsand oncem oreit wasad dress edtow ilhel minti rpitz ufert hespy clist shave rever tedto asubs titut ionci pherf orthi smess agebu tbloc kedit todis guise theme ssage struc turet hatma deita lotha rdert ocrac kbuti amgla didid ithas asecr etmes sageh idden inthe decip hered textw hichs ugges tstha tthes pycli stmis sioni sclos ingon itsai msiam notsu rewha tthei nitia lsrdf stand forbu tiwil lgoba cktot heair minis tryto askif theyh avean ysugg estio nsiti salso clear fromt hecon tents ofthi smess ageth atthe germa nsare getti ngali ttles uspic iouss owewi llnee dtost epupo urown secur ityiw illse ndmyn extbr iefin gusin gavig enere ciphe rwith keyle ngtht hreem oreto follo wpear l\\n'"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "keyword_decipher(ca, 'akela', wrap_a)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "akelbcdfghijmnopqrstuvwxyz \n",
+      "\n",
+      "while wedid notha vetim etopl acean ytrai nedag entsw ithth elond onsco utgro upsth eakel aoper ation didma naget orecr uitan dbrie fseve ralme mbers ofthe linco lnsco uting assoc iatio nando neoft hemha smade amajo rbrea kthro ughsp ottin gsome thing thato urreg ulara gents hadno tnoti cedth elond onpar tycon siste doftw entyt hreec yclis tsbut thegr oupar rivin ginli ncoln hadon lytwe ntyme mbers atfir stias sumed hehad misco unted butth ephot ograp hinth eloca lpape racco mpany ingth eirre porto nthev isitc onfir medth enumb eriwi llmak eenqu iries witho urlon donag entst oseei fthey havea nythi ngont heoth erthr eeand willb riefy ouont hatne xttim etheg roupw astra ckeda sthey retur nedso uthsp litup andvi sited achai nofes sexan dkent villa gesal ongth etham esbut despi tethe ircon tinui ngint erest inlan dmark snoth ingob vious inthe irbeh aviou rsugg ested anypa rticu larpl anthe north erngr oupar enows tayin gwith scout sinca newdo nanda kelah asrec ruite doneo fthem tospy onthe party ourai rmini stryc ontac tsare incre asing lyala rmeda boutt hespy clist sbuta resti llnot prepa redto tellu swhat itist hatis worry ingth emthe yarep artic ularl yagit ateda boutt hepre sence atcai stora ndnow atcan ewdon andth iscon cerna bouta ctivi tyine astan gliaa ndess exmak esmew onder ifiti sconn ected witha irdef encef orthe capit albut theya reref using totel landi twill behar dforu stohe lpthe mifth eywon ttell uswha twear esupp osedt obepr otect ingth eatta chedt elegr amwas copie dbyan akela agent inspa lding hissi sterw orksa tthet elegr aphyo ffice andga vehim acces sthem essag ewasd elive redby oneof thesp yclis tsand oncem oreit wasad dress edtow ilhel minti rpitz ufert hespy clist shave rever tedto asubs titut ionci pherf orthi smess agebu tbloc kedit todis guise theme ssage struc turet hatma deita lotha rdert ocrac kbuti amgla didid ithas asecr etmes sageh idden inthe decip hered textw hichs ugges tstha tthes pycli stmis sioni sclos ingon itsai msiam notsu rewha tthei nitia lsrdf stand forbu tiwil lgoba cktot heair minis tryto askif theyh avean ysugg estio nsiti salso clear fromt hecon tents ofthi smess ageth atthe germa nsare getti ngali ttles uspic iouss owewi llnee dtost epupo urown secur ityiw illse ndmyn extbr iefin gusin gavig enere ciphe rwith keyle ngtht hreem oreto follo wpear l\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "word_a, score_a = simulated_annealing_break(sca, fitness=Ptrigrams,\n",
+    "        plain_alphabet=string.ascii_lowercase, cipher_alphabet=keyword_cipher_alphabet_of('akkad', wrap_alphabet=KeywordWrapAlphabet.from_largest))\n",
+    "print(word_a, '\\n')\n",
+    "pa = keyword_decipher(ca, word_a)\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "while we did not have time to place any trained agents with the london scout groups the akela\n",
+      "operation did manage to recruit and brief several members of the lincoln scouting association and\n",
+      "one of them has made a major breakthrough spotting something that our regular agents had not noticed\n",
+      "the london party consisted of twenty three cyclists but the group arriving in lincoln had only\n",
+      "twenty members at first i assumed he had mis counted but the photograph in the local paper\n",
+      "accompanying their report on the visit confirmed the number i will make enquiries with our london\n",
+      "agents to see if they have anything on the other three and will brief you on that next time the\n",
+      "group was tracked as they returned south split up and visited a chain of essex and kent villages\n",
+      "along the thames but despite their continuing interest in landmarks nothing obvious in their\n",
+      "behaviour suggested any particular plan the northern group are now staying with scouts in ca new don\n",
+      "and akela has recruited one of them to spy on the part your air ministry contacts are increasingly\n",
+      "alarmed about the spy c lists but are still not prepared to tell us what it is that is worrying them\n",
+      "they are particularly agitated about the presence at caistor and now at ca new don and this concern\n",
+      "about activity in east anglia and essex makes me wonder if it is connected with air defence for the\n",
+      "capital but they are refusing to tell and it will be hard for us to help them if they wont tell us\n",
+      "what we are supposed to be protecting the attached telegram was copied by an akela agent in spalding\n",
+      "his sister works at the telegraphy office and gave him access the message was delivered by one of\n",
+      "the spy c lists and once more it was addressed to wilhelm in tirpitz ufer the spy c lists have\n",
+      "reverted to a substitution cipher for this message but blocked it to disguise the message structure\n",
+      "that made it alot harder to crack but i am glad i did it has a secret message hidden in the\n",
+      "deciphered text which suggests that the spy c list mission is closing on its aim siam not sure what\n",
+      "the initials rdf stand for but i will go back to the air ministry to ask if they have any\n",
+      "suggestions it is also clear from the contents of this message that the germans are getting a little\n",
+      "suspicious so we will need to step up our own security i will send my next briefing using avi genere\n",
+      "cipher with key length three more to follow pearl\n"
+     ]
+    }
+   ],
+   "source": [
+    "pa = prettify(keyword_decipher(sca, 'akela', wrap_alphabet=KeywordWrapAlphabet.from_a))\n",
+    "print(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "2336"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_a_filename, 'w').write(pa)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "wilhelm KeywordWrapAlphabet.from_last \n",
+      "\n",
+      "dearu nclew ilhel masyo uprom isedw ethor oughl yenjo yedou rvisi ttoyo urcou sinin linco lnand found itmos tinfo rmati vesto ptheb eauti fulca thedr alalm ostju stifi edour visit onits ownan dourh ostss hared withu ssome inter estin gdraw ingso fthet owers youme ntion edsto pthey graci ously allow edmet ocopy thesk etche sande xplai nedmu chabo uthow theto wersa rebui ltand whyst opasu suali wills endyo umyno tesan dsket chesv iaour dearf riend jessi cawho haspr omise dtoen suret heirs afede liver ystop reall yimus tcong ratul ateou rhost sinth eloca lscou tgrou psfor thema rvell ouswa yinwh ichth eyhav eorga nised ourtr avelt hough someo fthes couts haveb eenra therm oreso licit ousth anweh adexp ected askin grath eralo tofqu estio nsabo utour plans stopg enera llyih opeth eywer esati sfied witht heans werst hatwe gaveb utwef eelth atwea reatr iskof overs tayin gourw elcom esowe willr eturn tolon donon tuesd aysto peven thoug hweha veenj oyedo urtim etoge thert hereh asbee nsome debat eamon gtheg roupa boutw herew eshou ldvis itnex tstop there areso manyi ntere sting sites tovis italo ngthe majes ticth amese stuar ysowe haved ecide dtosp litin totwo group sstop ralfw illle adone party onato uroft heken tcoas twhil eiamv erymu chloo kingf orwar dtoex plori ngthe essex marsh essto pdole tmekn owify ouhav eabet terid eabut ihave beent oldth atcan ewdon sfift eenth centu rychu rchaf fords anele vatio nwith awide viewo fthes urrou nding lands inthi sothe rwise rathe rflat lands capea ndist hesit eofan other fasci natin gtowe rwhic hiwil lbece rtain toske tchfo ryous topfi nally ifyou havea nyfur therr eques tsfor speci ficin forma tiont henpe rhaps youco uldle aveam essag eform eatth epost offic ether estop karlm essag eends \n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)\n",
+    "print(word_b, wrap_b, '\\n')\n",
+    "pb = keyword_decipher(cb, word_b, wrap_b)\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "dear uncle wilhelm as you promised we thoroughly enjoyed our visit to your cousin in lincoln and\n",
+      "found it most informative stop the beautiful cathedral almost justified our visit on its own and our\n",
+      "hosts shared with us some interesting drawings of the towers you mentioned stop they graciously\n",
+      "allowed me to copy the sketches and explained much about how the towers are built and why stop as\n",
+      "usual i will send you my notes and sketches via our dear friend jessica who has promised to ensure\n",
+      "their safe delivery stop really i must congratulate our hosts in the local scout groups for the\n",
+      "marvellous way in which they have organised our travel though some of the scouts have been rather\n",
+      "more solicitous than we had expected asking rather alot of questions about our plans stop generally\n",
+      "i hope they were satisfied with the answers that we gave but we feel that we are at risk of\n",
+      "overstaying our welcome so we will return to london on tuesday stop eventhough we have enjoyed our\n",
+      "time together there has been some debate among the group about where we should visit next stop there\n",
+      "are so many interesting sites to visit along the majestic thames estuary so we have decided to split\n",
+      "into two groups stop ralf will lead one party on at our of the kent coast while i am very much\n",
+      "looking forward to exploring the essex marshes stop do let me know if you have a better idea but i\n",
+      "have been told that ca new dons fifteenth century church afford san elevation with a wide view of\n",
+      "the surrounding lands in this otherwise rather flat landscape and is the site of another fascinating\n",
+      "tower which i will be certain to sketch for you stop finally if you have any further requests for\n",
+      "specific information then perhaps you could leave a message for meat the post office there stop karl\n",
+      "message ends\n"
+     ]
+    }
+   ],
+   "source": [
+    "pb = prettify(keyword_decipher(scb, word_b, wrap_b))\n",
+    "print(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 27,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "1782"
+      ]
+     },
+     "execution_count": 27,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(pb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 23,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['the',\n",
+       " 'they',\n",
+       " 'as',\n",
+       " 'really',\n",
+       " 'generally',\n",
+       " 'eventhough',\n",
+       " 'there',\n",
+       " 'ralf',\n",
+       " 'do',\n",
+       " 'finally',\n",
+       " 'karl']"
+      ]
+     },
+     "execution_count": 23,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "pbs = pb.split()\n",
+    "[pbs[i+1] for i, w in enumerate(pbs) if w == 'stop']"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 35,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'duwaypwteovtycilafimistbcajovoioaohswusidottymstgamtctsaemahttabawsauiwsymnasvodfjwhptetsdsrimcohitlsgftmwiwthoottsotshbrmstwhearaoqaopsgihtwswtatwgbwftwaarooowswwrtlotsewheottthbsdatgawwsvnstasmistvatmteswhdtsitgsrwlopoaootkcwiavmlftetemsdlmkiyhabibihbttcndfccasewawvotslitorflaitsoaftwiwbctsfysfiyhafrfsitpyclamfmtpotskme'"
+      ]
+     },
+     "execution_count": 35,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "cat(w[0] for w in pbs)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 26,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[21, 24, 19, 23, 44, 32, 21, 22, 24, 56, 23, 3]"
+      ]
+     },
+     "execution_count": 26,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "[len(s.strip().split()) for s in pb.split('stop')]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 30,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'DeaR uncle wilhelm as you pRomiseD we thoRoughly enjoyeD ouR visit to youR cousin in lincoln anD FounD it most inFoRmative stop the beautiFul catheDRal almost justiFieD ouR visit on its own anD ouR hosts shaReD with us some inteResting DRawings oF the toweRs you mentioneD stop they gRaciously alloweD me to copy the sketches anD explaineD much about how the toweRs aRe built anD why stop as usual i will senD you my notes anD sketches via ouR DeaR FRienD jessica who has pRomiseD to ensuRe theiR saFe DeliveRy stop Really i must congRatulate ouR hosts in the local scout gRoups FoR the maRvellous way in which they have oRganiseD ouR tRavel though some oF the scouts have been RatheR moRe solicitous than we haD expecteD asking RatheR alot oF questions about ouR plans stop geneRally i hope they weRe satisFieD with the answeRs that we gave but we Feel that we aRe at Risk oF oveRstaying ouR welcome so we will RetuRn to lonDon on tuesDay stop eventhough we have enjoyeD ouR time togetheR theRe has been some Debate among the gRoup about wheRe we shoulD visit next stop theRe aRe so many inteResting sites to visit along the majestic thames estuaRy so we have DeciDeD to split into two gRoups stop RalF will leaD one paRty on at ouR oF the kent coast while i am veRy much looking FoRwaRD to exploRing the essex maRshes stop Do let me know iF you have a betteR iDea but i have been tolD that ca new Dons FiFteenth centuRy chuRch aFFoRD san elevation with a wiDe view oF the suRRounDing lanDs in this otheRwise RatheR Flat lanDscape anD is the site oF anotheR Fascinating toweR which i will be ceRtain to sketch FoR you stop Finally iF you have any FuRtheR Requests FoR speciFic inFoRmation then peRhaps you coulD leave a message FoR meat the post oFFice theRe stop kaRl message enDs'"
+      ]
+     },
+     "execution_count": 30,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "tt = ''.maketrans('rdf', 'RDF')\n",
+    "pbcap = wcat(pb.split()).translate(tt)\n",
+    "pbcap"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 33,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "\n",
+      "Dea\n",
+      "R uncle wilhelm as you p\n",
+      "Romise\n",
+      "D we tho\n",
+      "Roughly enjoye\n",
+      "D ou\n",
+      "R visit to you\n",
+      "R cousin in lincoln an\n",
+      "D \n",
+      "Foun\n",
+      "D it most in\n",
+      "Fo\n",
+      "Rmative stop the beauti\n",
+      "Ful cathe\n",
+      "D\n",
+      "Ral almost justi\n",
+      "Fie\n",
+      "D ou\n",
+      "R visit on its own an\n",
+      "D ou\n",
+      "R hosts sha\n",
+      "Re\n",
+      "D with us some inte\n",
+      "Resting \n",
+      "D\n",
+      "Rawings o\n",
+      "F the towe\n",
+      "Rs you mentione\n",
+      "D stop they g\n",
+      "Raciously allowe\n",
+      "D me to copy the sketches an\n",
+      "D explaine\n",
+      "D much about how the towe\n",
+      "Rs a\n",
+      "Re built an\n",
+      "D why stop as usual i will sen\n",
+      "D you my notes an\n",
+      "D sketches via ou\n",
+      "R \n",
+      "Dea\n",
+      "R \n",
+      "F\n",
+      "Rien\n",
+      "D jessica who has p\n",
+      "Romise\n",
+      "D to ensu\n",
+      "Re thei\n",
+      "R sa\n",
+      "Fe \n",
+      "Delive\n",
+      "Ry stop \n",
+      "Really i must cong\n",
+      "Ratulate ou\n",
+      "R hosts in the local scout g\n",
+      "Roups \n",
+      "Fo\n",
+      "R the ma\n",
+      "Rvellous way in which they have o\n",
+      "Rganise\n",
+      "D ou\n",
+      "R t\n",
+      "Ravel though some o\n",
+      "F the scouts have been \n",
+      "Rathe\n",
+      "R mo\n",
+      "Re solicitous than we ha\n",
+      "D expecte\n",
+      "D asking \n",
+      "Rathe\n",
+      "R alot o\n",
+      "F questions about ou\n",
+      "R plans stop gene\n",
+      "Rally i hope they we\n",
+      "Re satis\n",
+      "Fie\n",
+      "D with the answe\n",
+      "Rs that we gave but we \n",
+      "Feel that we a\n",
+      "Re at \n",
+      "Risk o\n",
+      "F ove\n",
+      "Rstaying ou\n",
+      "R welcome so we will \n",
+      "Retu\n",
+      "Rn to lon\n",
+      "Don on tues\n",
+      "Day stop eventhough we have enjoye\n",
+      "D ou\n",
+      "R time togethe\n",
+      "R the\n",
+      "Re has been some \n",
+      "Debate among the g\n",
+      "Roup about whe\n",
+      "Re we shoul\n",
+      "D visit next stop the\n",
+      "Re a\n",
+      "Re so many inte\n",
+      "Resting sites to visit along the majestic thames estua\n",
+      "Ry so we have \n",
+      "Deci\n",
+      "De\n",
+      "D to split into two g\n",
+      "Roups stop \n",
+      "Ral\n",
+      "F will lea\n",
+      "D one pa\n",
+      "Rty on at ou\n",
+      "R o\n",
+      "F the kent coast while i am ve\n",
+      "Ry much looking \n",
+      "Fo\n",
+      "Rwa\n",
+      "R\n",
+      "D to explo\n",
+      "Ring the essex ma\n",
+      "Rshes stop \n",
+      "Do let me know i\n",
+      "F you have a bette\n",
+      "R i\n",
+      "Dea but i have been tol\n",
+      "D that ca new \n",
+      "Dons \n",
+      "Fi\n",
+      "Fteenth centu\n",
+      "Ry chu\n",
+      "Rch a\n",
+      "F\n",
+      "Fo\n",
+      "R\n",
+      "D san elevation with a wi\n",
+      "De view o\n",
+      "F the su\n",
+      "R\n",
+      "Roun\n",
+      "Ding lan\n",
+      "Ds in this othe\n",
+      "Rwise \n",
+      "Rathe\n",
+      "R \n",
+      "Flat lan\n",
+      "Dscape an\n",
+      "D is the site o\n",
+      "F anothe\n",
+      "R \n",
+      "Fascinating towe\n",
+      "R which i will be ce\n",
+      "Rtain to sketch \n",
+      "Fo\n",
+      "R you stop \n",
+      "Finally i\n",
+      "F you have any \n",
+      "Fu\n",
+      "Rthe\n",
+      "R \n",
+      "Requests \n",
+      "Fo\n",
+      "R speci\n",
+      "Fic in\n",
+      "Fo\n",
+      "Rmation then pe\n",
+      "Rhaps you coul\n",
+      "D leave a message \n",
+      "Fo\n",
+      "R meat the post o\n",
+      "F\n",
+      "Fice the\n",
+      "Re stop ka\n",
+      "Rl message en\n",
+      "Ds\n"
+     ]
+    }
+   ],
+   "source": [
+    "pbcap2 = cat(('\\n' + c) if c.isupper() else c for c in pbcap)\n",
+    "print(pbcap2)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {
+    "Collapsed": "false"
+   },
+   "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
+}
diff --git a/2020/2020-challenge5.md b/2020/2020-challenge5.md
new file mode 100644 (file)
index 0000000..55703b7
--- /dev/null
@@ -0,0 +1,107 @@
+---
+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 Collapsed="false"
+from szyfrow.keyword_cipher import *
+from szyfrow.column_transposition import *
+from szyfrow.support.text_prettify import *
+```
+
+```python Collapsed="false"
+challenge_number = 5
+plaintext_a_filename = f'plaintext.{challenge_number}a.txt'
+plaintext_b_filename = f'plaintext.{challenge_number}b.txt'
+ciphertext_a_filename = f'ciphertext.{challenge_number}a.txt'
+ciphertext_b_filename = f'ciphertext.{challenge_number}b.txt'
+```
+
+```python Collapsed="false"
+ca = open(ciphertext_a_filename).read()
+sca = sanitise(ca)
+cb = open(ciphertext_b_filename).read()
+scb = sanitise(cb)
+```
+
+```python Collapsed="false"
+(word_a, wrap_a), score_a = keyword_break_mp(sca, fitness=Ptrigrams)
+print(word_a, wrap_a, '\n')
+pa = keyword_decipher(ca, word_a, wrap_a)
+print(pa)
+```
+
+```python Collapsed="false"
+keyword_decipher(ca, 'akela', wrap_a)
+```
+
+```python Collapsed="false"
+word_a, score_a = simulated_annealing_break(sca, fitness=Ptrigrams,
+        plain_alphabet=string.ascii_lowercase, cipher_alphabet=keyword_cipher_alphabet_of('akkad', wrap_alphabet=KeywordWrapAlphabet.from_largest))
+print(word_a, '\n')
+pa = keyword_decipher(ca, word_a)
+print(pa)
+```
+
+```python Collapsed="false"
+pa = prettify(keyword_decipher(sca, 'akela', wrap_alphabet=KeywordWrapAlphabet.from_a))
+print(pa)
+```
+
+```python Collapsed="false"
+open(plaintext_a_filename, 'w').write(pa)
+```
+
+```python Collapsed="false"
+(word_b, wrap_b), score_b = keyword_break_mp(scb, fitness=Ptrigrams)
+print(word_b, wrap_b, '\n')
+pb = keyword_decipher(cb, word_b, wrap_b)
+print(pb)
+```
+
+```python Collapsed="false"
+pb = prettify(keyword_decipher(scb, word_b, wrap_b))
+print(pb)
+```
+
+```python Collapsed="false"
+open(plaintext_b_filename, 'w').write(pb)
+```
+
+```python Collapsed="false"
+pbs = pb.split()
+[pbs[i+1] for i, w in enumerate(pbs) if w == 'stop']
+```
+
+```python Collapsed="false"
+cat(w[0] for w in pbs)
+```
+
+```python Collapsed="false"
+[len(s.strip().split()) for s in pb.split('stop')]
+```
+
+```python Collapsed="false"
+tt = ''.maketrans('rdf', 'RDF')
+pbcap = wcat(pb.split()).translate(tt)
+pbcap
+```
+
+```python Collapsed="false"
+pbcap2 = cat(('\n' + c) if c.isupper() else c for c in pbcap)
+print(pbcap2)
+```
+
+```python Collapsed="false"
+
+```
diff --git a/2020/ciphertext.5a.txt b/2020/ciphertext.5a.txt
new file mode 100644 (file)
index 0000000..31b021d
--- /dev/null
@@ -0,0 +1 @@
+WFGJB WBLGL NOTFA VBTGM BTOPJ AEBAN YTRAG NBLAD BNTSW GTFTF BJONL ONSEO UTDRO UPSTF BAIBJ AOPBR ATGON LGLMA NADBT ORBER UGTAN LKRGB CSBVB RAJMB MKBRS OCTFB JGNEO JNSEO UTGND ASSOE GATGO NANLO NBOCT FBMFA SMALB AMAHO RKRBA ITFRO UDFSP OTTGN DSOMB TFGND TFATO URRBD UJARA DBNTS FALNO TNOTG EBLTF BJONL ONPAR TYEON SGSTB LOCTW BNTYT FRBBE YEJGS TSKUT TFBDR OUPAR RGVGN DGNJG NEOJN FALON JYTWB NTYMB MKBRS ATCGR STGAS SUMBL FBFAL MGSEO UNTBL KUTTF BPFOT ODRAP FGNTF BJOEA JPAPB RAEEO MPANY GNDTF BGRRB PORTO NTFBV GSGTE ONCGR MBLTF BNUMK BRGWG JJMAI BBNQU GRGBS WGTFO URJON LONAD BNTST OSBBG CTFBY FAVBA NYTFG NDONT FBOTF BRTFR BBANL WGJJK RGBCY OUONT FATNB XTTGM BTFBD ROUPW ASTRA EIBLA STFBY RBTUR NBLSO UTFSP JGTUP ANLVG SGTBL AEFAG NOCBS SBXAN LIBNT VGJJA DBSAJ ONDTF BTFAM BSKUT LBSPG TBTFB GREON TGNUG NDGNT BRBST GNJAN LMARI SNOTF GNDOK VGOUS GNTFB GRKBF AVGOU RSUDD BSTBL ANYPA RTGEU JARPJ ANTFB NORTF BRNDR OUPAR BNOWS TAYGN DWGTF SEOUT SGNEA NBWLO NANLA IBJAF ASRBE RUGTB LONBO CTFBM TOSPY ONTFB PARTY OURAG RMGNG STRYE ONTAE TSARB GNERB ASGND JYAJA RMBLA KOUTT FBSPY EJGST SKUTA RBSTG JJNOT PRBPA RBLTO TBJJU SWFAT GTGST FATGS WORRY GNDTF BMTFB YARBP ARTGE UJARJ YADGT ATBLA KOUTT FBPRB SBNEB ATEAG STORA NLNOW ATEAN BWLON ANLTF GSEON EBRNA KOUTA ETGVG TYGNB ASTAN DJGAA NLBSS BXMAI BSMBW ONLBR GCGTG SEONN BETBL WGTFA GRLBC BNEBC ORTFB EAPGT AJKUT TFBYA RBRBC USGND TOTBJ JANLG TWGJJ KBFAR LCORU STOFB JPTFB MGCTF BYWON TTBJJ USWFA TWBAR BSUPP OSBLT OKBPR OTBET GNDTF BATTA EFBLT BJBDR AMWAS EOPGB LKYAN AIBJA ADBNT GNSPA JLGND FGSSG STBRW ORISA TTFBT BJBDR APFYO CCGEB ANLDA VBFGM AEEBS STFBM BSSAD BWASL BJGVB RBLKY ONBOC TFBSP YEJGS TSANL ONEBM ORBGT WASAL LRBSS BLTOW GJFBJ MGNTG RPGTZ UCBRT FBSPY EJGST SFAVB RBVBR TBLTO ASUKS TGTUT GONEG PFBRC ORTFG SMBSS ADBKU TKJOE IBLGT TOLGS DUGSB TFBMB SSADB STRUE TURBT FATMA LBGTA JOTFA RLBRT OERAE IKUTG AMDJA LGLGL GTFAS ASBER BTMBS SADBF GLLBN GNTFB LBEGP FBRBL TBXTW FGEFS UDDBS TSTFA TTFBS PYEJG STMGS SGONG SEJOS GNDON GTSAG MSGAM NOTSU RBWFA TTFBG NGTGA JSRLC STANL CORKU TGWGJ JDOKA EITOT FBAGR MGNGS TRYTO ASIGC TFBYF AVBAN YSUDD BSTGO NSGTG SAJSO EJBAR CROMT FBEON TBNTS OCTFG SMBSS ADBTF ATTFB DBRMA NSARB DBTTG NDAJG TTJBS USPGE GOUSS OWBWG JJNBB LTOST BPUPO UROWN SBEUR GTYGW GJJSB NLMYN BXTKR GBCGN DUSGN DAVGD BNBRB EGPFB RWGTF IBYJB NDTFT FRBBM ORBTO COJJO WPBAR J
diff --git a/2020/ciphertext.5b.txt b/2020/ciphertext.5b.txt
new file mode 100644 (file)
index 0000000..7581eac
--- /dev/null
@@ -0,0 +1 @@
+HEWZC ULSEF PSOES TWAJV CXZVT PAEHF EBOVZ VCNOS JEUQV JEHVC ZDPAP BBVJV CZLVC APUPU SPULV SUWUH MVCUH PBTVA BPUMV ZTWBP DEABV XBOEI EWCBP MCSLW BOEHZ WSWST VABQC ABPMP EHVCZ DPAPB VUPBA VFUWU HVCZO VABAA OWZEH FPBOC AAVTE PUBEZ EABPU NHZWF PUNAV MBOEB VFEZA JVCTE UBPVU EHABV XBOEJ NZWLP VCASJ WSSVF EHTEB VLVXJ BOEAR EBLOE AWUHE GXSWP UEHTC LOWIV CBOVF BOEBV FEZAW ZEICP SBWUH FOJAB VXWAC ACWSP FPSSA EUHJV CTJUV BEAWU HAREB LOEAD PWVCZ HEWZM ZPEUH QEAAP LWFOV OWAXZ VTPAE HBVEU ACZEB OEPZA WMEHE SPDEZ JABVX ZEWSS JPTCA BLVUN ZWBCS WBEVC ZOVAB APUBO ESVLW SALVC BNZVC XAMVZ BOETW ZDESS VCAFW JPUFO PLOBO EJOWD EVZNW UPAEH VCZBZ WDESB OVCNO AVTEV MBOEA LVCBA OWDEI EEUZW BOEZT VZEAV SPLPB VCABO WUFEO WHEGX ELBEH WARPU NZWBO EZWSV BVMYC EABPV UAWIV CBVCZ XSWUA ABVXN EUEZW SSJPO VXEBO EJFEZ EAWBP AMPEH FPBOB OEWUA FEZAB OWBFE NWDEI CBFEM EESBO WBFEW ZEWBZ PARVM VDEZA BWJPU NVCZF ESLVT EAVFE FPSSZ EBCZU BVSVU HVUVU BCEAH WJABV XEDEU BOVCN OFEOW DEEUQ VJEHV CZBPT EBVNE BOEZB OEZEO WAIEE UAVTE HEIWB EWTVU NBOEN ZVCXW IVCBF OEZEF EAOVC SHDPA PBUEG BABVX BOEZE WZEAV TWUJP UBEZE ABPUN APBEA BVDPA PBWSV UNBOE TWQEA BPLBO WTEAE ABCWZ JAVFE OWDEH ELPHE HBVAX SPBPU BVBFV NZVCX AABVX ZWSMF PSSSE WHVUE XWZBJ VUWBV CZVMB OEREU BLVWA BFOPS EPWTD EZJTC LOSVV RPUNM VZFWZ HBVEG XSVZP UNBOE EAAEG TWZAO EAABV XHVSE BTERU VFPMJ VCOWD EWIEB BEZPH EWICB POWDE IEEUB VSHBO WBLWU EFHVU AMPMB EEUBO LEUBC ZJLOC ZLOWM MVZHA WUESE DWBPV UFPBO WFPHE DPEFV MBOEA CZZVC UHPUN SWUHA PUBOP AVBOE ZFPAE ZWBOE ZMSWB SWUHA LWXEW UHPAB OEAPB EVMWU VBOEZ MWALP UWBPU NBVFE ZFOPL OPFPS SIELE ZBWPU BVARE BLOMV ZJVCA BVXMP UWSSJ PMJVC OWDEW UJMCZ BOEZZ EYCEA BAMVZ AXELP MPLPU MVZTW BPVUB OEUXE ZOWXA JVCLV CSHSE WDEWT EAAWN EMVZT EWBBO EXVAB VMMPL EBOEZ EABVX RWZST EAAWN EEUHA 
diff --git a/2020/plaintext.5a.txt b/2020/plaintext.5a.txt
new file mode 100644 (file)
index 0000000..ff6e2f9
--- /dev/null
@@ -0,0 +1 @@
+while wedid notha vetim etopl acean ytrai nedag entsw ithth elond onsco utgro upsth eakel aoper ation didma naget orecr uitan dbrie fseve ralme mbers ofthe linco lnsco uting assoc iatio nando neoft hemha smade amajo rbrea kthro ughsp ottin gsome thing thato urreg ulara gents hadno tnoti cedth elond onpar tycon siste doftw entyt hreec yclis tsbut thegr oupar rivin ginli ncoln hadon lytwe ntyme mbers atfir stias sumed hehad misco unted butth ephot ograp hinth eloca lpape racco mpany ingth eirre porto nthev isitc onfir medth enumb eriwi llmak eenqu iries witho urlon donag entst oseei fthey havea nythi ngont heoth erthr eeand willb riefy ouont hatne xttim etheg roupw astra ckeda sthey retur nedso uthsp litup andvi sited achai nofes sexan dkent villa gesal ongth etham esbut despi tethe ircon tinui ngint erest inlan dmark snoth ingob vious inthe irbeh aviou rsugg ested anypa rticu larpl anthe north erngr oupar enows tayin gwith scout sinca newdo nanda kelah asrec ruite doneo fthem tospy onthe party ourai rmini stryc ontac tsare incre asing lyala rmeda boutt hespy clist sbuta resti llnot prepa redto tellu swhat itist hatis worry ingth emthe yarep artic ularl yagit ateda boutt hepre sence atcai stora ndnow atcan ewdon andth iscon cerna bouta ctivi tyine astan gliaa ndess exmak esmew onder ifiti sconn ected witha irdef encef orthe capit albut theya reref using totel landi twill behar dforu stohe lpthe mifth eywon ttell uswha twear esupp osedt obepr otect ingth eatta chedt elegr amwas copie dbyan akela agent inspa lding hissi sterw orksa tthet elegr aphyo ffice andga vehim acces sthem essag ewasd elive redby oneof thesp yclis tsand oncem oreit wasad dress edtow ilhel minti rpitz ufert hespy clist shave rever tedto asubs titut ionci pherf orthi smess agebu tbloc kedit todis guise theme ssage struc turet hatma deita lotha rdert ocrac kbuti amgla didid ithas asecr etmes sageh idden inthe decip hered textw hichs ugges tstha tthes pycli stmis sioni sclos ingon itsai msiam notsu rewha tthei nitia lsrdf stand forbu tiwil lgoba cktot heair minis tryto askif theyh avean ysugg estio nsiti salso clear fromt hecon tents ofthi smess ageth atthe germa nsare getti ngali ttles uspic iouss owewi llnee dtost epupo urown secur ityiw illse ndmyn extbr iefin gusin gavig enere ciphe rwith keyle ngtht hreem oreto follo wpear l
diff --git a/2020/plaintext.5b.txt b/2020/plaintext.5b.txt
new file mode 100644 (file)
index 0000000..5ee6388
--- /dev/null
@@ -0,0 +1,19 @@
+dear uncle wilhelm as you promised we thoroughly enjoyed our visit to your cousin in lincoln and
+found it most informative stop the beautiful cathedral almost justified our visit on its own and our
+hosts shared with us some interesting drawings of the towers you mentioned stop they graciously
+allowed me to copy the sketches and explained much about how the towers are built and why stop as
+usual i will send you my notes and sketches via our dear friend jessica who has promised to ensure
+their safe delivery stop really i must congratulate our hosts in the local scout groups for the
+marvellous way in which they have organised our travel though some of the scouts have been rather
+more solicitous than we had expected asking rather alot of questions about our plans stop generally
+i hope they were satisfied with the answers that we gave but we feel that we are at risk of
+overstaying our welcome so we will return to london on tuesday stop eventhough we have enjoyed our
+time together there has been some debate among the group about where we should visit next stop there
+are so many interesting sites to visit along the majestic thames estuary so we have decided to split
+into two groups stop ralf will lead one party on at our of the kent coast while i am very much
+looking forward to exploring the essex marshes stop do let me know if you have a better idea but i
+have been told that ca new dons fifteenth century church afford san elevation with a wide view of
+the surrounding lands in this otherwise rather flat landscape and is the site of another fascinating
+tower which i will be certain to sketch for you stop finally if you have any further requests for
+specific information then perhaps you could leave a message for meat the post office there stop karl
+message ends
\ No newline at end of file