Fixed railfence ciphers, done challenges 2014 4 and 5
[cipher-tools.git] / railfence-experiment-2.ipynb
diff --git a/railfence-experiment-2.ipynb b/railfence-experiment-2.ipynb
new file mode 100644 (file)
index 0000000..be34da0
--- /dev/null
@@ -0,0 +1,725 @@
+{
+ "metadata": {
+  "name": "",
+  "signature": "sha256:285f7a82eaf5cc815e9a686ebce8aa2cfbdecb14f2473c9b5dfe0aedafcd727c"
+ },
+ "nbformat": 3,
+ "nbformat_minor": 0,
+ "worksheets": [
+  {
+   "cells": [
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "from cipher import *\n",
+      "from cipherbreak import *\n",
+      "import math"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 79
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def railfence_encipher(message, height, fillvalue=' '):\n",
+      "    \"\"\"Railfence cipher\n",
+      "\n",
+      "    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 2, fillvalue='!')\n",
+      "    'hlohraateerishsslnpeefetotsigaleccpeselteevsmhatetiiaogicotxfretnrifneihr!'\n",
+      "    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 3, fillvalue='!')\n",
+      "    'horaersslpeeosglcpselteevsmhatetiiaogicotxfretnrifneihr!!lhateihsnefttiaece!'\n",
+      "    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 5, fillvalue='!')\n",
+      "    'hresleogcseeemhetaocofrnrner!!lhateihsnefttiaece!!ltvsatiigitxetifih!!oarspeslp!'\n",
+      "    >>> railfence_encipher('hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers', 10, fillvalue='!')\n",
+      "    'hepisehagitnr!!lernesge!!lmtocerh!!otiletap!!tseaorii!!hassfolc!!evtitffe!!rahsetec!!eixn!'\n",
+      "    \"\"\"\n",
+      "    sections = chunks(message, (height - 1) * 2, fillvalue=fillvalue)\n",
+      "    # Add the top row\n",
+      "    rows = [s[0] for s in sections]\n",
+      "    # process the middle rows of the grid\n",
+      "    for r in range(1, height - 1):\n",
+      "        rows += [s[r] + s[-r] for s in sections]\n",
+      "    # process the bottom row\n",
+      "    rows += [s[height - 1] for s in sections]\n",
+      "    return ''.join(rows)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 2
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "pt = 'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'\n",
+      "height = 6"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 195
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "sections = chunks(pt, (height - 1) * 2, fillvalue='!')\n",
+      "n_sections = len(sections)\n",
+      "# Add the top row\n",
+      "rows = [' '.join([s[0] for s in sections])]\n",
+      "# process the middle rows of the grid\n",
+      "for r in range(1, height - 1):\n",
+      "    # rows += [''.join([s[r:r+1] + s[n_sections-r:n_sections-r+1] for s in sections])]\n",
+      "    rows += [''.join([s[r] + s[-r] for s in sections])]\n",
+      "# process the bottom row\n",
+      "# rows += [' '.join([s[height - 1:height] for s in sections])]\n",
+      "rows += [' '.join([s[height - 1] for s in sections])]\n",
+      "rows"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 196,
+       "text": [
+        "['h a r s e t l e',\n",
+        " 'eevatiacoreifhr!',\n",
+        " 'lraeislefosaeps!',\n",
+        " 'lesheioitftrni!!',\n",
+        " 'ohteshnpetigcc!!',\n",
+        " 't m t g x n e !']"
+       ]
+      }
+     ],
+     "prompt_number": 196
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "sections"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 197,
+       "text": [
+        "['hellothere',\n",
+        " 'avastmehea',\n",
+        " 'rtiesthisi',\n",
+        " 'salongpiec',\n",
+        " 'eoftextfor',\n",
+        " 'testingrai',\n",
+        " 'lfenceciph',\n",
+        " 'ers!!!!!!!']"
+       ]
+      }
+     ],
+     "prompt_number": 197
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "sections = chunks(pt, (height - 1) * 2, fillvalue='')\n",
+      "# Add the top row\n",
+      "rows = [' '.join([s[0] for s in sections])]\n",
+      "# process the middle rows of the grid\n",
+      "for r in range(1, height-1):\n",
+      "    print(r, height*2-r-2, ':', sections[0][r:r+1], sections[0][height*2-r-2:height*2-r-1])\n",
+      "    rows += [''.join([s[r:r+1] + s[height*2-r-2:height*2-r-1] for s in sections])]\n",
+      "    # rows += [''.join([s[r] + s[-r] for s in sections])]\n",
+      "# process the bottom row\n",
+      "rows += [' '.join([s[height - 1:height] for s in sections])]\n",
+      "# rows += [' '.join([s[height - 1] for s in sections])]\n",
+      "rows"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "1 9 : e e\n",
+        "2 8 : l r\n",
+        "3 7 : l e\n",
+        "4 6 : o h\n"
+       ]
+      },
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 198,
+       "text": [
+        "['h a r s e t l e',\n",
+        " 'eevatiacoreifhr',\n",
+        " 'lraeislefosaeps',\n",
+        " 'lesheioitftrni',\n",
+        " 'ohteshnpetigcc',\n",
+        " 't m t g x n e ']"
+       ]
+      }
+     ],
+     "prompt_number": 198
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "sections"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 199,
+       "text": [
+        "['hellothere',\n",
+        " 'avastmehea',\n",
+        " 'rtiesthisi',\n",
+        " 'salongpiec',\n",
+        " 'eoftextfor',\n",
+        " 'testingrai',\n",
+        " 'lfenceciph',\n",
+        " 'ers']"
+       ]
+      }
+     ],
+     "prompt_number": 199
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "ct = ''.join(c for c in ''.join(rows) if c != ' ')\n",
+      "ct"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 200,
+       "text": [
+        "'harsetleeevatiacoreifhrlraeislefosaepslesheioitftrniohteshnpetigcctmtgxne'"
+       ]
+      }
+     ],
+     "prompt_number": 200
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "n_sections = math.ceil(len(pt) / ((height - 1) * 2))\n",
+      "n_sections"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 202,
+       "text": [
+        "8"
+       ]
+      }
+     ],
+     "prompt_number": 202
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "padding_to_add = n_sections * (height - 1) * 2 - len(pt)\n",
+      "padding_to_add"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 203,
+       "text": [
+        "7"
+       ]
+      }
+     ],
+     "prompt_number": 203
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "row_lengths = [n_sections] * (height - 1) * 2\n",
+      "row_lengths"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 204,
+       "text": [
+        "[8, 8, 8, 8, 8, 8, 8, 8, 8, 8]"
+       ]
+      }
+     ],
+     "prompt_number": 204
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "for i in range((height - 1) * 2 - 1, (height - 1) * 2 - (padding_to_add + 1), -1):\n",
+      "    row_lengths[i] -= 1\n",
+      "row_lengths"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 205,
+       "text": [
+        "[8, 8, 8, 7, 7, 7, 7, 7, 7, 7]"
+       ]
+      }
+     ],
+     "prompt_number": 205
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "folded_row_lengths = [row_lengths[0]]\n",
+      "for i in range(1, height-1):\n",
+      "    folded_row_lengths += [row_lengths[i] + row_lengths[-i]]\n",
+      "folded_row_lengths += [row_lengths[height - 1]]\n",
+      "folded_row_lengths"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 206,
+       "text": [
+        "[8, 15, 15, 14, 14, 7]"
+       ]
+      }
+     ],
+     "prompt_number": 206
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "rows = []\n",
+      "row_start = 0\n",
+      "for i in folded_row_lengths:\n",
+      "    rows += [ct[row_start:row_start + i]]\n",
+      "    row_start += i\n",
+      "rows"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 207,
+       "text": [
+        "['harsetle',\n",
+        " 'eevatiacoreifhr',\n",
+        " 'lraeislefosaeps',\n",
+        " 'lesheioitftrni',\n",
+        " 'ohteshnpetigcc',\n",
+        " 'tmtgxne']"
+       ]
+      }
+     ],
+     "prompt_number": 207
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "down_rows = [rows[0]]\n",
+      "up_rows = []\n",
+      "for i in range(1, height-1):\n",
+      "    down_rows += [''.join([c for n, c in enumerate(rows[i]) if n % 2 == 0])]\n",
+      "    up_rows += [''.join([c for n, c in enumerate(rows[i]) if n % 2 == 1])]\n",
+      "down_rows += [rows[-1]]\n",
+      "down_rows, up_rows"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 208,
+       "text": [
+        "(['harsetle', 'evtaoefr', 'lailfses', 'lseottn', 'otsneic', 'tmtgxne'],\n",
+        " ['eaicrih', 'reseoap', 'ehiifri', 'hehptgc'])"
+       ]
+      }
+     ],
+     "prompt_number": 208
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "up_rows.reverse()\n",
+      "down_rows + up_rows"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 164,
+       "text": [
+        "['hresleogcs',\n",
+        " 'eehtoorre',\n",
+        " 'laehnftac',\n",
+        " 'lvaigteii',\n",
+        " 'oarspeslp',\n",
+        " 'tstiixtfh',\n",
+        " 'htisetiee',\n",
+        " 'emeacfnnr']"
+       ]
+      }
+     ],
+     "prompt_number": 164
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "''.join(c for r in zip_longest(*(down_rows + up_rows), fillvalue='') for c in r)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 165,
+       "text": [
+        "'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'"
+       ]
+      }
+     ],
+     "prompt_number": 165
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def rfe(message, height, fillvalue=''):\n",
+      "    sections = chunks(message, (height - 1) * 2, fillvalue=fillvalue)\n",
+      "    n_sections = len(sections)\n",
+      "    # Add the top row\n",
+      "    rows = [''.join([s[0] for s in sections])]\n",
+      "    # process the middle rows of the grid\n",
+      "    for r in range(1, height-1):\n",
+      "        rows += [''.join([s[r:r+1] + s[height*2-r-2:height*2-r-1] for s in sections])]\n",
+      "    # process the bottom row\n",
+      "    rows += [''.join([s[height - 1:height] for s in sections])]\n",
+      "    # rows += [' '.join([s[height - 1] for s in sections])]\n",
+      "    return ''.join(rows)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 171
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "rfe(pt, 5)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 177,
+       "text": [
+        "'hresleogcseeemhetaocofrnrnerlhateihsnefttiaeceltvsatiigitxetifihoarspeslp'"
+       ]
+      }
+     ],
+     "prompt_number": 177
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "rfe(pt, 5) == ct"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 178,
+       "text": [
+        "True"
+       ]
+      }
+     ],
+     "prompt_number": 178
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "def rfd(message, height, fillvalue=''):\n",
+      "    n_sections = math.ceil(len(message) / ((height - 1) * 2))\n",
+      "    padding_to_add = n_sections * (height - 1) * 2 - len(message)\n",
+      "    row_lengths = [n_sections] * (height - 1) * 2\n",
+      "    for i in range((height - 1) * 2 - 1, (height - 1) * 2 - (padding_to_add + 1), -1):\n",
+      "        row_lengths[i] -= 1\n",
+      "    folded_row_lengths = [row_lengths[0]]\n",
+      "    for i in range(1, height-1):\n",
+      "        folded_row_lengths += [row_lengths[i] + row_lengths[-i]]\n",
+      "    folded_row_lengths += [row_lengths[height - 1]]\n",
+      "    rows = []\n",
+      "    row_start = 0\n",
+      "    for i in folded_row_lengths:\n",
+      "        rows += [message[row_start:row_start + i]]\n",
+      "        row_start += i\n",
+      "    down_rows = [rows[0]]\n",
+      "    up_rows = []\n",
+      "    for i in range(1, height-1):\n",
+      "        down_rows += [''.join([c for n, c in enumerate(rows[i]) if n % 2 == 0])]\n",
+      "        up_rows += [''.join([c for n, c in enumerate(rows[i]) if n % 2 == 1])]\n",
+      "    down_rows += [rows[-1]]\n",
+      "    up_rows.reverse()\n",
+      "    return ''.join(c for r in zip_longest(*(down_rows + up_rows), fillvalue='') for c in r)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [],
+     "prompt_number": 220
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "h = 7\n",
+      "print(rfe(pt, h))\n",
+      "rfd(rfe(pt, h), h)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "haspolsevsetgifrifrlatihnettaeelemtiocxernhorersleesgcptehaiaottneihesfic\n"
+       ]
+      },
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 221,
+       "text": [
+        "'hellothereavastmeheartiesthisisalongpieceoftextfortestingrailfenceciphers'"
+       ]
+      }
+     ],
+     "prompt_number": 221
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "for h in range(2, 51):\n",
+      "    assert rfd(rfe(pt, h), h) == pt\n",
+      "    print(h, ':', rfd(rfe(pt, h), h) == pt)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "2 : True\n",
+        "3 : True\n",
+        "4 : True\n",
+        "5 : True\n",
+        "6 : True\n",
+        "7 : True\n",
+        "8 : True\n",
+        "9 : True\n",
+        "10 : True\n",
+        "11 : True\n",
+        "12 : True\n",
+        "13 : True\n",
+        "14 : True\n",
+        "15 : True\n",
+        "16 : True\n",
+        "17 : True\n",
+        "18 : True\n",
+        "19 : True\n",
+        "20 : True\n",
+        "21 : True\n",
+        "22 : True\n",
+        "23 : True\n",
+        "24 : True\n",
+        "25 : True\n",
+        "26 : True\n",
+        "27 : True\n",
+        "28 : True\n",
+        "29 : True\n",
+        "30 : True\n",
+        "31 : True\n",
+        "32 : True\n",
+        "33 : True\n",
+        "34 : True\n",
+        "35 : True\n",
+        "36 : True\n",
+        "37 : True\n",
+        "38 : True\n",
+        "39 : True\n",
+        "40 : True\n",
+        "41 : True\n",
+        "42 : True\n",
+        "43 : True\n",
+        "44 : True\n",
+        "45 : True\n",
+        "46 : True\n",
+        "47 : True\n",
+        "48 : True\n",
+        "49 : True\n",
+        "50 : True\n"
+       ]
+      }
+     ],
+     "prompt_number": 227
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "h"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 224,
+       "text": [
+        "1"
+       ]
+      }
+     ],
+     "prompt_number": 224
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "rfe('hellotherefriends', 4)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 228,
+       "text": [
+        "'hhieterelorfnsled'"
+       ]
+      }
+     ],
+     "prompt_number": 228
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "rfd('hhieterelorfnsled', 4)"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "metadata": {},
+       "output_type": "pyout",
+       "prompt_number": 229,
+       "text": [
+        "'hellotherefriends'"
+       ]
+      }
+     ],
+     "prompt_number": 229
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [
+      "for h in [3, 5, 7]:\n",
+      "    print(rfe(pt, h))"
+     ],
+     "language": "python",
+     "metadata": {},
+     "outputs": [
+      {
+       "output_type": "stream",
+       "stream": "stdout",
+       "text": [
+        "horaersslpeeosglcpselteevsmhatetiiaogicotxfretnrifneihrlhateihsnefttiaece\n",
+        "hresleogcseeemhetaocofrnrnerlhateihsnefttiaeceltvsatiigitxetifihoarspeslp\n",
+        "haspolsevsetgifrifrlatihnettaeelemtiocxernhorersleesgcptehaiaottneihesfic\n"
+       ]
+      }
+     ],
+     "prompt_number": 230
+    },
+    {
+     "cell_type": "code",
+     "collapsed": false,
+     "input": [],
+     "language": "python",
+     "metadata": {},
+     "outputs": []
+    }
+   ],
+   "metadata": {}
+  }
+ ]
+}
\ No newline at end of file