Done challenge 9
[cipher-tools.git] / 2019 / 2019-challenge9b.ipynb
diff --git a/2019/2019-challenge9b.ipynb b/2019/2019-challenge9b.ipynb
new file mode 100644 (file)
index 0000000..10a3894
--- /dev/null
@@ -0,0 +1,710 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "import os,sys,inspect\n",
+    "currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))\n",
+    "parentdir = os.path.dirname(currentdir)\n",
+    "sys.path.insert(0,parentdir) "
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from cipher.caesar import *\n",
+    "from cipher.affine import *\n",
+    "from cipher.keyword_cipher import *\n",
+    "from cipher.column_transposition import *\n",
+    "from cipher.vigenere import *\n",
+    "from support.text_prettify import *\n",
+    "from support.utilities import *\n",
+    "from support.plot_frequency_histogram import *\n",
+    "import re\n",
+    "import itertools"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "challenge_number = 9\n",
+    "plaintext_a_filename = f'{challenge_number}a.plaintext'\n",
+    "plaintext_b_filename = f'{challenge_number}b.plaintext'\n",
+    "ciphertext_a_filename = f'{challenge_number}a.ciphertext'\n",
+    "ciphertext_b_filename = f'{challenge_number}b.ciphertext'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "ca = open(ciphertext_a_filename).read()\n",
+    "cb = open(ciphertext_b_filename).read()\n",
+    "\n",
+    "rwa = wcat(cat(reversed(w)) for w in ca.split())\n",
+    "ra = cat(reversed(ca))\n",
+    "sca = sanitise(ca)\n",
+    "rsca = cat(reversed(sca))\n",
+    "pca = letters(ca)\n",
+    "pta = depunctuate(ca)\n",
+    "\n",
+    "scb = cat(l for l in cb if l in \"012\")\n",
+    "gcb = cb.split()\n",
+    "rscb = cat(reversed(scb))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# open(plaintext_b_filename, 'w').write(lcat(tpack(segment(pa))))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "18480"
+      ]
+     },
+     "execution_count": 6,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "len(scb)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Solution"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 45,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def unquad(quadlet):\n",
+    "    ds = [int(c) for c in quadlet]\n",
+    "    return ds[0] * 12 + ds[1] * 6 + ds[2] * 2 + ds[3]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['1110',\n",
+       " '1020',\n",
+       " '1110',\n",
+       " '0011',\n",
+       " '1021',\n",
+       " '0020',\n",
+       " '0011',\n",
+       " '1110',\n",
+       " '1011',\n",
+       " '0011']"
+      ]
+     },
+     "execution_count": 48,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "quads = [q for ch in chunks(scb, 28) for q in every_nth(ch, 7)]\n",
+    "quads[:10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 57,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'uqudredupdatfvsunvdqijeqdrrfaqhdnghqghrcfsbhgwnaqgmghqugeqngpdatfvsadccnehqghgweqcfufvnemhqghfvsdrhb'"
+      ]
+     },
+     "execution_count": 57,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "qcb = cat(unpos(unquad(q)) for q in quads)\n",
+    "qcb[:100]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/usr/local/lib/python3.6/dist-packages/matplotlib/figure.py:445: UserWarning: Matplotlib is currently using module://ipykernel.pylab.backend_inline, which is a non-GUI backend, so cannot show the figure.\n",
+      "  % get_backend())\n"
+     ]
+    },
+    {
+     "data": {
+      "image/png": "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\n",
+      "text/plain": [
+       "<Figure size 432x288 with 1 Axes>"
+      ]
+     },
+     "metadata": {
+      "needs_background": "light"
+     },
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "fc = collections.Counter(scb)\n",
+    "plot_frequency_histogram(fc, sort_key=fc.get)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "runs = [(k, len(list(v))) for k, v in itertools.groupby(scb)]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[(1, 5338),\n",
+       " (2, 2442),\n",
+       " (3, 1143),\n",
+       " (4, 522),\n",
+       " (5, 253),\n",
+       " (6, 110),\n",
+       " (7, 63),\n",
+       " (8, 29),\n",
+       " (9, 11),\n",
+       " (10, 3),\n",
+       " (14, 1)]"
+      ]
+     },
+     "execution_count": 9,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "collections.Counter(p[1] for p in runs).most_common()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def untri(triplet):\n",
+    "    ds = [int(c) for c in triplet]\n",
+    "    return ds[0] * 9 + ds[1] * 3 + ds[2]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def unpos_t(n):\n",
+    "    if n == 26:\n",
+    "        return '+'\n",
+    "    else:\n",
+    "        return unpos(n + 1)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 21,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "tb = cat(unpos(untri(t)) for t in chunks(scb, 3))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[]"
+      ]
+     },
+     "execution_count": 16,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "[c for c in tb if c == '+']"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 36,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['1110100101000012112210001101',\n",
+       " '1100101100010111100210110111',\n",
+       " '1111010110100101011210011100',\n",
+       " '0010110100000012212221001111',\n",
+       " '0100100001001102010000011101',\n",
+       " '1001001011000120021200011010',\n",
+       " '0001101011100000020021100100',\n",
+       " '0100110101101100002100001000',\n",
+       " '0110100000100022001100010110',\n",
+       " '1011000101100002100111110010']"
+      ]
+     },
+     "execution_count": 36,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "chunks(scb, 28)[:10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 46,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[['1110', '1020', '1110', '0011', '1021', '0020', '0011'],\n",
+       " ['1110', '1011', '0011', '0000', '1101', '0021', '1111'],\n",
+       " ['1100', '1110', '1001', '1111', '0011', '1020', '0110'],\n",
+       " ['0111', '0020', '1020', '0011', '1021', '1021', '0021'],\n",
+       " ['0000', '1020', '0101', '0011', '1001', '0100', '0101'],\n",
+       " ['1020', '0100', '0101', '1021', '0010', '0021', '1100'],\n",
+       " ['0001', '0101', '0100', '1120', '1001', '0000', '1020'],\n",
+       " ['0100', '1000', '0100', '0101', '1020', '1110', '0100'],\n",
+       " ['0020', '1020', '1001', '0100', '1011', '0011', '0000'],\n",
+       " ['1101', '0021', '1111', '1100', '0000', '0011', '0010']]"
+      ]
+     },
+     "execution_count": 46,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "[every_nth(ch, 7) for ch in chunks(scb, 28)][:10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 31,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['1110010001',\n",
+       " '1110100110',\n",
+       " '1011000011',\n",
+       " '0010011001',\n",
+       " '1101101110',\n",
+       " '0011000100',\n",
+       " '0100011000',\n",
+       " '1111000101',\n",
+       " '0010011000',\n",
+       " '1000111101',\n",
+       " '0010001111',\n",
+       " '0100000000',\n",
+       " '0000100100',\n",
+       " '0110110100',\n",
+       " '1101020020',\n",
+       " '2112200022',\n",
+       " '1102000001',\n",
+       " '1011122000',\n",
+       " '2012010210',\n",
+       " '2222020111',\n",
+       " '1112002001',\n",
+       " '0001001001',\n",
+       " '0100001001',\n",
+       " '0110110011',\n",
+       " '1011110100',\n",
+       " '1111101010',\n",
+       " '0101010011',\n",
+       " '1101100000']"
+      ]
+     },
+     "execution_count": 31,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "[c[:10] for c in every_nth(scb, 28)]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 37,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[15, 18, 19, 47, 75, 99, 100, 102, 103, 104]"
+      ]
+     },
+     "execution_count": 37,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "[n for n, c in enumerate(scb) if c == '2'][:10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 40,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "[[15, 18, 19],\n",
+       " [19],\n",
+       " [19],\n",
+       " [15, 16, 18, 19, 20],\n",
+       " [15],\n",
+       " [14, 17, 19],\n",
+       " [17, 20],\n",
+       " [18],\n",
+       " [14, 15],\n",
+       " [15]]"
+      ]
+     },
+     "execution_count": 40,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "pos2s = [[n for n, c in enumerate(ch) if c == '2'] for ch in chunks(scb, 28)]\n",
+    "pos2s[:10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 44,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "(14, 20)"
+      ]
+     },
+     "execution_count": 44,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "min(min(s) for s in pos2s if s), max(max(s) for s in pos2s if s)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 45,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "def unquad(quadlet):\n",
+    "    ds = [int(c) for c in quadlet]\n",
+    "    return ds[0] * 12 + ds[1] * 6 + ds[2] * 2 + ds[3]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 48,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "['1110',\n",
+       " '1020',\n",
+       " '1110',\n",
+       " '0011',\n",
+       " '1021',\n",
+       " '0020',\n",
+       " '0011',\n",
+       " '1110',\n",
+       " '1011',\n",
+       " '0011']"
+      ]
+     },
+     "execution_count": 48,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "quads = [q for ch in chunks(scb, 28) for q in every_nth(ch, 7)]\n",
+    "quads[:10]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 58,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'uqudredupdatfvsunvdqijeqdrrfaqhdnghqghrcfsbhgwnaqgmghqugeqngpdatfvsadccnehqghgweqcfufvnemhqghfvsdrhb'"
+      ]
+     },
+     "execution_count": 58,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "qcb = cat(unpos(unquad(q)) for q in quads)\n",
+    "qcb[:100]"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 51,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "('noapqrsbfytcuvdwxeghijklmz', -15275.52585516763)"
+      ]
+     },
+     "execution_count": 51,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "kb, scoreb = simulated_annealing_break(qcb, fitness=Ptrigrams)\n",
+    "kb, scoreb"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 52,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "'memofromdockingmanoeuvreofficetoastestflightspacesystemsreasdockingcollartestspreliminarytestingofthedockingcollarsystemhasrevealedapotentiallyseriousflawinthedesignwhichmustbeaddressedbeforethesystemcanbecertifiedtheissueconcernstheemergencyreleasesystembackgroundthedockingsystemperformsthefollowingfunctionsimpactenergyabsorptionmechanicalconnectionspacecraftalignmentandretractionspacecrafthardmechanicalconnectionanddockinginterfacesealingspacecraftundockingandseparationinordertoachievethesefunctionsthedockingsystemconsistsofthreeprinciplepartsthebaseastructuralringandthelatchingringthedockingsystembaseisthemainstructuralmembertowhichthedockingsystemassembliesareattachedthestructuralringcarriesthebodylatcheswhichprovideahardpressuretightconnectionbetweenthetwospacecrafttogetherwiththecapturelatcheswhichoperateduringthedockingmanoeuvretheseperformthedockingfunctiontheyconsistofeightactiveandeightpassivehookswithanelectricaldriveinstalledononeofthelatchesandclosedloopcablesconnectingthemeachactivehookhasacamoperatedmechanismwhichperformsitsopeningandtighteningcorrespondinghooksofthepassivedockingsystemarecapturedbyactivehookseachpassivehookhasastackofpreloadedbellvillespringsprovidingadefiniteforceforthedockinginterfacepreloadingthedockinginterfacesealwillprovidepressureintegrityofthedockinginterfacesthisconsistsoftwoconcentricrubberringsealsoneachsystemandamanholecoverisusedtoclosethetransfertunnelofthespacecrafthatchlockingandunlockingismanuallyperformedbythecrewitissealedbyamechanismwhichhasafurthereighteccentriclatchesthesebeingconnectedwitheachotherbymeansofclosedcableconnectionthedockingsystemisequippedwithalarmandmetersystemwhichprovidetelemetrytotheshipsandtogroundcontrolinstandardoperationalmodeundockingisperformedbyreleaseoftheactivespacecraftcapturelatchesandthenbyopeningthestructurelatchhooksifnecessaryundockingcanbeperformedbythepassivespacecraftbyreleasingthebodymountedlatchesandopeningthestructurelatchpassivehooksspacecraftseparationisperformedbyspringthrusterssymmetricallylocatedonthestructuralringsofbothsystemsafterthelatchesreleasetheprincipledifferencebetweentherussianandusdockingsystemdesignscanbeseenintheguideringsystemunliketherussianelectromechanicaldockingsystemapolloisequippedwithanelectricdrivewhichusescableconnectionstotriggerthelatchesanotheressentialdifferenceistherussianemergencyreleasesystemersabackupprovidedbypyroboltsattachedtoeachpassiveandactivehookwhichoperatesinpassivemodeandprovidespracticallyinstantaneousundockingintheeventofasystemmalfunctionoraccidentonboardoneorbothofthedockedspacecraftsituationsinwhichtheersmightbeinitiatedincludeiuncontrolledfireorexplosiononboardoneofthespacecraftduringdockedoperationsiifailureofthedockingcontrolsystempreventingstandardreleaseoperationiiiattitudecontrolfailureoforunplannedfiringononeorbothspacecraftimposinghighstressesonthedockingmechanismwhiletheersprovidesaneffectivebackupforemergencysituationssimulationsandtestsonthehuntsvilledockingtestbedshowthattheeffectivenessofthepyrotechnicboltsisacriticalissuetoomuchexplosivecouldcausecriticaldamagetothepressuresealsaroundthehatchwhiletoolittlecanleavethespacecraftattachedwithadamagedmechanismtheerswasdesignedforoperationonussrmissionsandisthereforetunedtothestructuralconstraintsonthesovietplatformsincethelatchesareelectromagneticonthatspacecrafttheyarelesspronetodamageundervibrationalforcesthemotorandcablemechanismusedontheapolloplatformismorevulnerabletoshockandundercertaintestconditionshasbeenshowntofailfollowingthetriggeringoftheersonthesovietendofthedockingmechanismshockwaveswillnotofcoursepropagatethroughthevacuumofspacebuttheforcescanbetransmittedthroughthetunneltotheapollolatchesandiftheboltsfireasymmetricallythisplacesatorsionloadingonthemechanismwhichcanunseatthedrivecablesinfiveoftheseventestswherethisphenomenonwasobservedtheengineerswereabletoreseatthecablesbyrepeatedlyoperatingthemechanismbutintheremainingtwocasesthemechanismwasbeyondrepairwithoutmanualinterventionunfortunatelyinthesetwocasesthesafetyinterlockalsopreventedthehatchfrombeingopenedwhichcouldmakeitdifficultfortheastronautstocarryoutaspacewalktoexecutetherequiredrepairinthiscaseitwouldnormallybepossiblefortheastronautstomanuallyoperatethemanholelatchesbydisassemblingandsubsequentlyassemblingthehatchcoverhoweverifthelatchingmechanismshavebeensufficientlydamagedbythepyroboltsthismightproveariskyoptionanditisevenpossiblethatthecoverlatcheswouldfailtoretractmanuallywehaveaskedqueensteamtotakealookatthisandsheassuresmethattheycansortitoutshehasworkedonmostoftheapollomissiondesignteamssoiamprettyconfidentthatshecanmakesureeverythingisokforthisone'"
+      ]
+     },
+     "execution_count": 52,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "pb = keyword_decipher(qcb, kb, KeywordWrapAlphabet.from_last)\n",
+    "pb"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 53,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "memo from docking manoeuvre office to as test flight space systems re as docking collar tests\n",
+      "preliminary testing of the docking collar system has revealed a potentially serious flaw in the\n",
+      "design which must be addressed before the system can be certified the issue concerns the emergency\n",
+      "release system background the docking system performs the following functions impact energy\n",
+      "absorption mechanical connection spacecraft alignment and retraction spacecraft hard mechanical\n",
+      "connection and docking interface sealing spacecraft undocking and separation in order to achieve\n",
+      "these functions the docking system consists of three principle parts the base a structural ring and\n",
+      "the latching ring the docking system base is the main structural member to which the docking system\n",
+      "assemblies are attached the structural ring carries the body latches which provide a hard pressure\n",
+      "tight connection between the two spacecraft together with the capture latches which operate during\n",
+      "the docking manoeuvre these perform the docking function they consist of eight active and eight\n",
+      "passive hooks with an electrical drive installed on one of the latches and closed loop cables\n",
+      "connecting them each active hook has a cam operated mechanism which performs its opening and\n",
+      "tightening corresponding hooks of the passive docking system are captured by active hooks each\n",
+      "passive hook has a stack of preloaded bellville springs providing a definite force for the docking\n",
+      "interface preloading the docking interface seal will provide pressure integrity of the docking\n",
+      "interfaces this consists of two concentric rubber ring seals on each system and a manhole cover is\n",
+      "used to close the transfer tunnel of the spacecraft hatch locking and unlocking is manually\n",
+      "performed by the crew it is sealed by a mechanism which has a further eight eccentric latches these\n",
+      "being connected with each other by means of closed cable connection the docking system is equipped\n",
+      "with alarm and meter system which provide telemetry to the ships and to ground control in standard\n",
+      "operational mode undocking is performed by release of the active spacecraft capture latches and then\n",
+      "by opening the structure latch hooks if necessary undocking can be performed by the passive\n",
+      "spacecraft by releasing the body mounted latches and opening the structure latch passive hooks\n",
+      "spacecraft separation is performed by spring thrusters symmetrically located on the structural rings\n",
+      "of both systems after the latches release the principle difference between the russian and us\n",
+      "docking system designs can be seen in the guide ring system unlike the russian electromechanical\n",
+      "docking system apollo is equipped with an electric drive which uses cable connections to trigger the\n",
+      "latches another essential difference is the russian emergency release system ers a backup provided\n",
+      "by pyro bolts attached to each passive and active hook which operates in passive mode and provides\n",
+      "practically instantaneous undocking in the event of a system malfunction or accident onboard one or\n",
+      "both of the docked spacecraft situations in which the ers might be initiated include i uncontrolled\n",
+      "fire or explosion onboard one of the spacecraft during docked operations ii failure of the docking\n",
+      "control system preventing standard release operation iii attitude control failure of or unplanned\n",
+      "firing on one or both spacecraft imposing high stresses on the docking mechanism while the ers\n",
+      "provides an effective backup for emergency situations simulations and tests on the huntsville\n",
+      "docking testbed show that the effectiveness of the pyrotechnic bolts is a critical issue too much\n",
+      "explosive could cause critical damage to the pressure seals around the hatch while too little can\n",
+      "leave the spacecraft attached with a damaged mechanism the ers was designed for operation on ussr\n",
+      "missions and is therefore tuned to the structural constraints on the soviet platform since the\n",
+      "latches are electromagnetic on that spacecraft they are less prone to damage under vibrational\n",
+      "forces the motor and cable mechanism used on the apollo platform is more vulnerable to shock and\n",
+      "under certain test conditions has been shown to fail following the triggering of the erson the\n",
+      "soviet end of the docking mechanism shockwaves will not of course propagate through the vacuum of\n",
+      "space but the forces can be transmitted through the tunnel to the apollo latches and if the bolts\n",
+      "fire asymmetrically this places a torsion loading on the mechanism which can unseat the drive cables\n",
+      "in five of the seven tests where this phenomenon was observed the engineers were able to reseat the\n",
+      "cables by repeatedly operating the mechanism but in the remaining two cases the mechanism was beyond\n",
+      "repair without manual intervention unfortunately in these two cases the safety interlock also\n",
+      "prevented the hatch from being opened which could make it difficult for the astronauts to carryout a\n",
+      "spacewalk to execute the required repair in this case it would normally be possible for the\n",
+      "astronauts to manually operate the manhole latches by disassembling and subsequently assembling the\n",
+      "hatch cover however if the latching mechanisms have been sufficiently damaged by the pyro bolts this\n",
+      "might prove a risky option and it is even possible that the cover latches would fail to retract\n",
+      "manually we have asked queens team to take a look at this and she assures me that they can sort it\n",
+      "out she has worked on most of the apollo mission design teams so i am pretty confident that she can\n",
+      "make sure everything is ok for this one\n"
+     ]
+    }
+   ],
+   "source": [
+    "print(lcat(tpack(segment(pb))))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 55,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "text/plain": [
+       "5494"
+      ]
+     },
+     "execution_count": 55,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "open(plaintext_b_filename, 'w').write(lcat(tpack(segment(pb))))"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [],
+   "source": []
+  }
+ ],
+ "metadata": {
+  "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.6.9"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 4
+}