{
 "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": {}
  }
 ]
}