{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "import collections\n",
    "import string\n",
    "import numpy as np\n",
    "from numpy import matrix\n",
    "from numpy import linalg\n",
    "%matplotlib inline\n",
    "\n",
    "from multiprocessing import Pool\n",
    "\n",
    "\n",
    "from cipher import *\n",
    "from cipherbreak import *\n",
    "\n",
    "c7b = open('2016/7b.ciphertext').read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 108,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "c7bs = sanitise(c7b)\n",
    "c7br = cat(reversed(c7bs))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def bifid_grid(keyword, wrap_alphabet, letter_mapping):\n",
    "    cipher_alphabet = keyword_cipher_alphabet_of(keyword, wrap_alphabet)\n",
    "    if letter_mapping is None:\n",
    "        letter_mapping = {'j': 'i'}\n",
    "    translation = ''.maketrans(letter_mapping)\n",
    "    cipher_alphabet = cat(collections.OrderedDict.fromkeys(cipher_alphabet.translate(translation)))\n",
    "    f_grid = {k: ((i // 5) + 1, (i % 5) + 1) \n",
    "              for i, k in enumerate(cipher_alphabet)}\n",
    "    r_grid = {((i // 5) + 1, (i % 5) + 1): k \n",
    "              for i, k in enumerate(cipher_alphabet)}\n",
    "    return translation, f_grid, r_grid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 156,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pprint"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 157,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "({106: 'i'},\n",
      " {'a': (1, 4),\n",
      "  'b': (2, 1),\n",
      "  'c': (2, 2),\n",
      "  'd': (2, 3),\n",
      "  'e': (2, 4),\n",
      "  'f': (2, 5),\n",
      "  'g': (1, 2),\n",
      "  'h': (3, 1),\n",
      "  'i': (1, 1),\n",
      "  'k': (3, 2),\n",
      "  'l': (3, 3),\n",
      "  'm': (3, 4),\n",
      "  'n': (1, 5),\n",
      "  'o': (3, 5),\n",
      "  'p': (4, 1),\n",
      "  'q': (4, 2),\n",
      "  'r': (4, 3),\n",
      "  's': (4, 4),\n",
      "  't': (4, 5),\n",
      "  'u': (1, 3),\n",
      "  'v': (5, 1),\n",
      "  'w': (5, 2),\n",
      "  'x': (5, 3),\n",
      "  'y': (5, 4),\n",
      "  'z': (5, 5)},\n",
      " {(1, 1): 'i',\n",
      "  (1, 2): 'g',\n",
      "  (1, 3): 'u',\n",
      "  (1, 4): 'a',\n",
      "  (1, 5): 'n',\n",
      "  (2, 1): 'b',\n",
      "  (2, 2): 'c',\n",
      "  (2, 3): 'd',\n",
      "  (2, 4): 'e',\n",
      "  (2, 5): 'f',\n",
      "  (3, 1): 'h',\n",
      "  (3, 2): 'k',\n",
      "  (3, 3): 'l',\n",
      "  (3, 4): 'm',\n",
      "  (3, 5): 'o',\n",
      "  (4, 1): 'p',\n",
      "  (4, 2): 'q',\n",
      "  (4, 3): 'r',\n",
      "  (4, 4): 's',\n",
      "  (4, 5): 't',\n",
      "  (5, 1): 'v',\n",
      "  (5, 2): 'w',\n",
      "  (5, 3): 'x',\n",
      "  (5, 4): 'y',\n",
      "  (5, 5): 'z'})\n"
     ]
    }
   ],
   "source": [
    "pprint.pprint(bifid_grid('iguana', KeywordWrapAlphabet.from_a, None))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 158,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "({106: 'i'},\n",
      " {'a': (1, 2),\n",
      "  'b': (1, 3),\n",
      "  'c': (1, 4),\n",
      "  'd': (1, 5),\n",
      "  'e': (2, 1),\n",
      "  'f': (2, 2),\n",
      "  'g': (2, 3),\n",
      "  'h': (2, 4),\n",
      "  'i': (2, 5),\n",
      "  'k': (3, 1),\n",
      "  'l': (3, 2),\n",
      "  'm': (3, 3),\n",
      "  'n': (3, 4),\n",
      "  'o': (3, 5),\n",
      "  'p': (4, 1),\n",
      "  'q': (4, 2),\n",
      "  'r': (4, 3),\n",
      "  's': (4, 4),\n",
      "  't': (4, 5),\n",
      "  'u': (5, 1),\n",
      "  'v': (5, 2),\n",
      "  'w': (5, 3),\n",
      "  'x': (5, 4),\n",
      "  'y': (5, 5),\n",
      "  'z': (1, 1)},\n",
      " {(1, 1): 'z',\n",
      "  (1, 2): 'a',\n",
      "  (1, 3): 'b',\n",
      "  (1, 4): 'c',\n",
      "  (1, 5): 'd',\n",
      "  (2, 1): 'e',\n",
      "  (2, 2): 'f',\n",
      "  (2, 3): 'g',\n",
      "  (2, 4): 'h',\n",
      "  (2, 5): 'i',\n",
      "  (3, 1): 'k',\n",
      "  (3, 2): 'l',\n",
      "  (3, 3): 'm',\n",
      "  (3, 4): 'n',\n",
      "  (3, 5): 'o',\n",
      "  (4, 1): 'p',\n",
      "  (4, 2): 'q',\n",
      "  (4, 3): 'r',\n",
      "  (4, 4): 's',\n",
      "  (4, 5): 't',\n",
      "  (5, 1): 'u',\n",
      "  (5, 2): 'v',\n",
      "  (5, 3): 'w',\n",
      "  (5, 4): 'x',\n",
      "  (5, 5): 'y'})\n"
     ]
    }
   ],
   "source": [
    "pprint.pprint(bifid_grid('z', KeywordWrapAlphabet.from_a, None))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "({113: 'p'},\n",
      " {'a': (1, 4),\n",
      "  'b': (2, 1),\n",
      "  'c': (2, 2),\n",
      "  'd': (2, 3),\n",
      "  'e': (2, 4),\n",
      "  'f': (2, 5),\n",
      "  'g': (1, 2),\n",
      "  'h': (3, 1),\n",
      "  'i': (1, 1),\n",
      "  'j': (3, 2),\n",
      "  'k': (3, 3),\n",
      "  'l': (3, 4),\n",
      "  'm': (3, 5),\n",
      "  'n': (1, 5),\n",
      "  'o': (4, 1),\n",
      "  'p': (4, 2),\n",
      "  'r': (4, 3),\n",
      "  's': (4, 4),\n",
      "  't': (4, 5),\n",
      "  'u': (1, 3),\n",
      "  'v': (5, 1),\n",
      "  'w': (5, 2),\n",
      "  'x': (5, 3),\n",
      "  'y': (5, 4),\n",
      "  'z': (5, 5)},\n",
      " {(1, 1): 'i',\n",
      "  (1, 2): 'g',\n",
      "  (1, 3): 'u',\n",
      "  (1, 4): 'a',\n",
      "  (1, 5): 'n',\n",
      "  (2, 1): 'b',\n",
      "  (2, 2): 'c',\n",
      "  (2, 3): 'd',\n",
      "  (2, 4): 'e',\n",
      "  (2, 5): 'f',\n",
      "  (3, 1): 'h',\n",
      "  (3, 2): 'j',\n",
      "  (3, 3): 'k',\n",
      "  (3, 4): 'l',\n",
      "  (3, 5): 'm',\n",
      "  (4, 1): 'o',\n",
      "  (4, 2): 'p',\n",
      "  (4, 3): 'r',\n",
      "  (4, 4): 's',\n",
      "  (4, 5): 't',\n",
      "  (5, 1): 'v',\n",
      "  (5, 2): 'w',\n",
      "  (5, 3): 'x',\n",
      "  (5, 4): 'y',\n",
      "  (5, 5): 'z'})\n"
     ]
    }
   ],
   "source": [
    "pprint.pprint(bifid_grid('iguana', KeywordWrapAlphabet.from_a, {'q': 'p'}))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# def bifid_decipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a, \n",
    "#                    letter_mapping=None, period=None):\n",
    "#     translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)\n",
    "    \n",
    "#     t_message = message.translate(translation)\n",
    "#     pairs0 = [f_grid[l] for l in t_message]\n",
    "#     items = sum([list(p) for p in pairs0], [])\n",
    "#     gap = len(message)\n",
    "#     pairs1 = [(items[i//2], items[i//2+gap]) for i in range(0, len(items), 2)]\n",
    "#     return cat(r_grid[p] for p in pairs1)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 162,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def bifid_encipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a, \n",
    "                   letter_mapping=None, period=None, fillvalue=None):\n",
    "    translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)\n",
    "    \n",
    "    t_message = message.translate(translation)\n",
    "    pairs0 = [f_grid[l] for l in sanitise(t_message)]\n",
    "    if period:\n",
    "        chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]\n",
    "        if len(chunked_pairs[-1]) < period and fillvalue:\n",
    "            chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))\n",
    "    else:\n",
    "        chunked_pairs = [pairs0]\n",
    "    \n",
    "    pairs1 = []\n",
    "    for c in chunked_pairs:\n",
    "        items = sum(list(list(i) for i in zip(*c)), [])\n",
    "        p = [(items[i], items[i+1]) for i in range(0, len(items), 2)]\n",
    "        pairs1 += p\n",
    "    \n",
    "    return cat(r_grid[p] for p in pairs1)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 163,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'nkklawamdkoedysipdesltirsnoesqlvvaloderbhel'"
      ]
     },
     "execution_count": 163,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_encipher('this is a test message for the keyword decipherment', 'elephant', wrap_alphabet=KeywordWrapAlphabet.from_last)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "ot, ofg, org = bifid_grid('iguana', KeywordWrapAlphabet.from_a, None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 1),\n",
       " (1, 5),\n",
       " (2, 3),\n",
       " (1, 1),\n",
       " (1, 4),\n",
       " (2, 2),\n",
       " (1, 3),\n",
       " (4, 3),\n",
       " (4, 3),\n",
       " (5, 4)]"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "op0 = [ofg[l] for l in \"indiacurry\"]\n",
    "op0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[[(1, 1), (1, 5), (2, 3), (1, 1)],\n",
       " [(1, 4), (2, 2), (1, 3), (4, 3)],\n",
       " [(4, 3), (5, 4), (1, 4), (1, 4)]]"
      ]
     },
     "execution_count": 86,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "ocp = chunks(op0, 4, fillvalue=[[ofg['a']]])\n",
    "acc = []\n",
    "ocp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 1),\n",
       " (2, 1),\n",
       " (1, 5),\n",
       " (3, 1),\n",
       " (1, 2),\n",
       " (1, 4),\n",
       " (4, 2),\n",
       " (3, 3),\n",
       " (4, 5),\n",
       " (1, 1),\n",
       " (3, 4),\n",
       " (4, 4)]"
      ]
     },
     "execution_count": 87,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "acc=[]\n",
    "for c in ocp:\n",
    "    items = sum(list(list(i) for i in zip(*c)), [])\n",
    "    p = [(items[i], items[i+1]) for i in range(0, len(items), 2)]\n",
    "    acc += p\n",
    "acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ibnhgaqltims'"
      ]
     },
     "execution_count": 88,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cat(org[p] for p in acc)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 164,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "def bifid_decipher(message, keyword, wrap_alphabet=KeywordWrapAlphabet.from_a, \n",
    "                   letter_mapping=None, period=None, fillvalue=None):\n",
    "    translation, f_grid, r_grid = bifid_grid(keyword, wrap_alphabet, letter_mapping)\n",
    "    \n",
    "    t_message = message.translate(translation)\n",
    "    pairs0 = [f_grid[l] for l in sanitise(t_message)]\n",
    "    if period:\n",
    "        chunked_pairs = [pairs0[i:i+period] for i in range(0, len(pairs0), period)]\n",
    "        if len(chunked_pairs[-1]) < period and fillvalue:\n",
    "            chunked_pairs[-1] += [f_grid[fillvalue]] * (period - len(chunked_pairs[-1]))\n",
    "    else:\n",
    "        chunked_pairs = [pairs0]\n",
    "        \n",
    "    pairs1 = []\n",
    "    for c in chunked_pairs:\n",
    "        items = [j for i in c for j in i]\n",
    "        gap = len(c)\n",
    "        p = [(items[i], items[i+gap]) for i in range(gap)]\n",
    "        pairs1 += p\n",
    "\n",
    "    return cat(r_grid[p] for p in pairs1)    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "({106: 'i'},\n",
       " {'a': (1, 4),\n",
       "  'b': (2, 1),\n",
       "  'c': (2, 2),\n",
       "  'd': (2, 3),\n",
       "  'e': (2, 4),\n",
       "  'f': (2, 5),\n",
       "  'g': (1, 2),\n",
       "  'h': (3, 1),\n",
       "  'i': (1, 1),\n",
       "  'k': (3, 2),\n",
       "  'l': (3, 3),\n",
       "  'm': (3, 4),\n",
       "  'n': (1, 5),\n",
       "  'o': (3, 5),\n",
       "  'p': (4, 1),\n",
       "  'q': (4, 2),\n",
       "  'r': (4, 3),\n",
       "  's': (4, 4),\n",
       "  't': (4, 5),\n",
       "  'u': (1, 3),\n",
       "  'v': (5, 1),\n",
       "  'w': (5, 2),\n",
       "  'x': (5, 3),\n",
       "  'y': (5, 4),\n",
       "  'z': (5, 5)},\n",
       " {(1, 1): 'i',\n",
       "  (1, 2): 'g',\n",
       "  (1, 3): 'u',\n",
       "  (1, 4): 'a',\n",
       "  (1, 5): 'n',\n",
       "  (2, 1): 'b',\n",
       "  (2, 2): 'c',\n",
       "  (2, 3): 'd',\n",
       "  (2, 4): 'e',\n",
       "  (2, 5): 'f',\n",
       "  (3, 1): 'h',\n",
       "  (3, 2): 'k',\n",
       "  (3, 3): 'l',\n",
       "  (3, 4): 'm',\n",
       "  (3, 5): 'o',\n",
       "  (4, 1): 'p',\n",
       "  (4, 2): 'q',\n",
       "  (4, 3): 'r',\n",
       "  (4, 4): 's',\n",
       "  (4, 5): 't',\n",
       "  (5, 1): 'v',\n",
       "  (5, 2): 'w',\n",
       "  (5, 3): 'x',\n",
       "  (5, 4): 'y',\n",
       "  (5, 5): 'z'})"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_grid('iguana', KeywordWrapAlphabet.from_a, None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 139,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ibidonhprm'"
      ]
     },
     "execution_count": 139,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_encipher(\"indiajelly\", 'iguana')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 140,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'indiaielly'"
      ]
     },
     "execution_count": 140,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_decipher('ibidonhprm', 'iguana')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 137,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ibnhgaqltm'"
      ]
     },
     "execution_count": 137,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_encipher(\"indiacurry\", 'iguana', period=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 138,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'indiacurry'"
      ]
     },
     "execution_count": 138,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_decipher(\"ibnhgaqltm\", 'iguana', period=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ibnhgaqltzml'"
      ]
     },
     "execution_count": 144,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_encipher(\"indiacurry\", 'iguana', period=4, fillvalue='x')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 146,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'indiacurryxx'"
      ]
     },
     "execution_count": 146,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_decipher(\"ibnhgaqltzml\", 'iguana', period=4)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 101,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "p0 = [(1, 1), (2, 1), (1, 5), (3, 1)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {
    "collapsed": false,
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 1, 2, 1, 1, 5, 3, 1]"
      ]
     },
     "execution_count": 103,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t0 = [j for i in p0 for j in i]\n",
    "t0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(1, 1), (1, 5), (2, 3), (1, 1)]"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "[(t0[i], t0[i+4]) for i in range(4)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 130,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'martinwehavemadeadreadfulmistakeandihavebeentooslowtoadmitthattomyselfihavehadavisitfromthewomanfromthesyndicateandiconfrontedheraboutthesourceofthetemplatessheconfirmedmyworstfearsandnowiwanttocrawlawayanddiewhathavewedoneoursoftwarehasledtosomuchsufferingwhenitwasdesignedtodotheoppositeiaskedherhowthecabinetofficecouldpossiblyhaveauthorisedthisandshelaughedandexplainedthatthesyndicatenolongerworkedforthebritishgovernmentcallitprivateenterpriseshesaidwehavealwaysbeengoodatthatmyhorrormusthavebeenwrittenallovermyfaceshedidntseemsurprisedatmyreactionbutequallyshedidnttakeitwellandcivilitywasabandonediaskedherhowitcouldbelegalletalonemoraltodowhattheyproposedandheranswerwasthatitwasnecessaryisaidwewouldnthelpthemandshesaiditwasnecessarythatwedidisaidiwouldntbeabletofacemyfamilyandfriendsifwecooperatedandshesaidiwouldnthavetoworryaboutthatforlongonewayoranotherthepdssyndicateweregoingtomakesurewebothdisappearedlookingbackicanseethatfromthestartthiswholethinghasactedtodrawusintoitscentreandnowiamattheeventhorizonalmostunabletoescapeitspullbutithinkwehaveonelastchanceiamsureshewillbevisitingyouaswellshethinkswehavenochoicebutithinkachoiceisallwehavewhateveryoudoholdoutforbettertermsshehastobelievethatyouareonsideandmotivatedbygreedsothatshewontworryaboutanyqualmsyoumighthaveconvinceherthatyouwillconvincemetocooperatetellherthatyouthinkyoushouldworkfromthecollectiveinosloandthatyouwantpaymentviathebankinswitzerlandigottheimpressionthatmoneyisnotaproblemwithmoneyinaswissbankandtheexpertiseandconnectivityaffordedbythecollectiveithinkwehaveachancetoescapeandtotrytostopthemperhapswewillsurvivethisperhapswecanbringthemdown'"
      ]
     },
     "execution_count": 130,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_decipher(c7bs, 'ligo', KeywordWrapAlphabet.from_a, period=4, fillvalue=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 147,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'martin we have made a dreadful mistake and i have been too slow to admit that to myself i have had a visit from the woman from the syndicate and i confronted her about the source of the templates she confirmed my worst fears and now i want to crawl away and die what have we done our software has led to so much suffering when it was designed to do the opposite i asked her how the cabinet office could possibly have authorised this and she laughed and explained that the syndicate no longer worked for the british government call it private enterprises he said we have always been good at that my horror must have been written all over myfaces he didnt seem surprised at my reaction but equally she didnt take it well and civility was abandoned i asked her how it could be legal let alone moral to do what they proposed and her answer was that it was necessary i said we wouldnt help them and she said it was necessary that we did i said i wouldnt be able to face my family and friends if we cooperated and she said i wouldnt have to worry about that for long one way or another the pds syndicate were going to make sure we both disappeared looking back i can see that from the start this whole thing has acted to draw us into its centre and now i am at the event horizon almost unable to escape its pull but i think we have one last chance i am sure she will be visiting you as well she thinks we have no choice but i think a choice is all we have whatever you do hold out for better terms she has to believe that you are on side and motivated by greed so that she wont worry about any qualms you might have convince her that you will convince me to cooperate tell her that you think you should work from the collective in oslo and that you want payment via the bank in switzerland i got the impression that money is not a problem with money in a swiss bank and the expertise and connectivity afforded by the collective i think we have a chance to escape and to try to stop them perhaps we will survive this perhaps we can bring them down'"
      ]
     },
     "execution_count": 147,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "wcat(segment(bifid_decipher(c7bs, 'ligo', KeywordWrapAlphabet.from_a, period=4)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "p0 = [(2, 1), (3, 3), (3, 3), (5, 1), (1, 4)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[2, 1, 3, 3, 3, 3, 5, 1, 1, 4]"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items = sum([list(p) for p in p0], [])\n",
    "items"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[(2, 3), (1, 5), (3, 1), (3, 1), (3, 4)]"
      ]
     },
     "execution_count": 55,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gap=5\n",
    "[(items[i//2], items[i//2+gap]) for i in range(0, len(items), 2)]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 91,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "c7bs = sanitise(c7b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def bifid_break_mp(message, wordlist=keywords, fitness=Pletters,\n",
    "                     number_of_solutions=1, chunksize=500):\n",
    "    \"\"\"Breaks a keyword substitution cipher using a dictionary and\n",
    "    frequency analysis\n",
    "\n",
    "    >>> keyword_break_mp(keyword_encipher('this is a test message for the ' \\\n",
    "          'keyword decipherment', 'elephant', KeywordWrapAlphabet.from_last), \\\n",
    "          wordlist=['cat', 'elephant', 'kangaroo']) # doctest: +ELLIPSIS\n",
    "    (('elephant', <KeywordWrapAlphabet.from_last: 2>), -52.834575011...)\n",
    "    >>> keyword_break_mp(keyword_encipher('this is a test message for the ' \\\n",
    "          'keyword decipherment', 'elephant', KeywordWrapAlphabet.from_last), \\\n",
    "          wordlist=['cat', 'elephant', 'kangaroo'], \\\n",
    "          number_of_solutions=2) # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE\n",
    "    [(('elephant', <KeywordWrapAlphabet.from_last: 2>), -52.834575011...), \n",
    "    (('elephant', <KeywordWrapAlphabet.from_largest: 3>), -52.834575011...)]\n",
    "    \"\"\"\n",
    "    with Pool() as pool:\n",
    "        helper_args = [(message, word, wrap, fitness)\n",
    "                       for word in wordlist\n",
    "                       for wrap in KeywordWrapAlphabet]\n",
    "        # Gotcha: the helper function here needs to be defined at the top level\n",
    "        #   (limitation of Pool.starmap)\n",
    "        breaks = pool.starmap(bifid_break_worker, helper_args, chunksize)\n",
    "        if number_of_solutions == 1:\n",
    "            return max(breaks, key=lambda k: k[1])\n",
    "        else:\n",
    "            return sorted(breaks, key=lambda k: k[1], reverse=True)[:number_of_solutions]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 116,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def bifid_break_worker(message, keyword, wrap_alphabet, fitness):\n",
    "    plaintext = bifid_decipher(message, keyword, wrap_alphabet)\n",
    "    fit = fitness(plaintext)\n",
    "    logger.debug('Keyword break attempt using key {0} (wrap={1}) gives fit of '\n",
    "                 '{2} and decrypt starting: {3}'.format(keyword, \n",
    "                     wrap_alphabet, fit, sanitise(plaintext)[:50]))\n",
    "    return (keyword, wrap_alphabet), fit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'enamokkneogiyegrkcuzbgsydkoqoswiwvtgbolrkfuzbgsyskdqusgnttqetuonyegyfkbsteqeycgbudbvqadcepgqrsbbeaeoqilrqcsosfcdyrbztiuirvqrtcmesbkudboeytksofknyegrambmctvxeogttfggemokopiqwinutqhdtoftsgsathnemlteprmrqbstdolsaklrueucsvncyhgqqcsfqlutsdxzthnfuvotauhnyegosloeogwrrqclelbonknefqkrkofvoqhxttvrimhyttvyqosrlegqtbeyroeuegbtnqkeecgqepblclvutouaehtoekceqgpeobwaohndxlstmvnvalttupquvoieruortugrhfsyqosnsqcesrvhtcrarvqnshkudbistnbwuootauhtqefiolctxqoqhdsmrneettrtberyybtnqblqxgrtrveqyfoboxwaehwlplqrcbiowhirimheyotqcciorhitvdaqkdurimhtheslelwxuooneagedooqlfibrlfhesrpxtgrrbkarhrxqobtogwaehwrimheyotlviqpesoyfkbsteqoviiynstnvhltfgarqostqdfotktpfhlrnadyegrtencsrtltknqffyqsnietwrixhogeqgsooihkiuhtwtonotknenquarhtnerycgicadbschhthlbeurbzpmqkqbsoebweprtepkhtsqhrslbrrefycoisnkumuedqrseqtshftqvftvkntlgbyqbyqosyotbucvtetvqoawhtgniucoadpiqomkeysgcyroeuegbefwimtedcpqcyogakzhbnepcztbqoviiotcnguiocdaipkqbkebwyqosepuqsrecnfsvedoipoqkmyegsqdsaogktgniurofkwfldeoupsqerncsfevoyqosxcoueswnfoqkspkbnyrheuqxotktarhasoiofnqhtokluoqivslbqhbcveqberoaboskskcsfslctsgkapbqftvuiilvcsbkaqlbrrubwtgtnkdboskylzlqqyetqekleuebrsyspnbrcfqspstdntrndsichescznbprqealulhteroctydoocwanhtprnocothnypoqysosniltodcsfyvvolwaehwdpiqoskedwonrtentycobwanelolftbnneksonwlhrsqcqqcqrsopeckrcountigqtldycoisnkuotktanhetwklvshfspkboxkqaolkmyegdqossdcorqoszoowaohabmityghiurocczicttqkifbboekyorhehedkxrobesooztmbqnsbtsqcnkgqnxcorruhokkaergezpctbpdnntqqshcqaehrfyvenwqtttbgsrcfvqasarhfksbkufvvawlacteqtfnvctvhspkqwyocnrtormzdnckouekbomkttarlptmroyketcbrusoeqystofbqoskctenquekbkybgtfrbktbxsqesswgeysggrqfsswgeedoovxaiqvdabaginnrptyqoqesomudleoylstoqtodcoawhkybgeukqdgogzxeiexrinpchoawheewgepth'"
      ]
     },
     "execution_count": 107,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c7bs = sanitise(c7b)\n",
    "c7br = cat(reversed(c7bs))\n",
    "c7br"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 148,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(('ligo', <KeywordWrapAlphabet.from_a: 1>), -2505.924490942904)"
      ]
     },
     "execution_count": 148,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_break_mp(c7bs, wordlist=['gravity', 'ligo'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 102,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'ksotagstmczesqstldwfasoehepicltaryruvgstiwbtylwzlanehrdmthhlqzeohpsdytllgdxfcetbiislqetoukobnterkoyonsetkodhtymxuefpdtnhnsulwnnurhiotctcrwhprbssrdblxanlrxadxgxatetsegdoeuhawberbaswolpqkrkpfcxufohcyefaeabqtkbrykbdonghsbaodvongcfdvngmeslhetnytkocenotirklsatenkdeeyoentbryuoleqoefcuxpqbsirotbogkvtqbrqgyoqamkninrfottolgmynbsekmeouwueklcpqrekyylvronsntcotrrctdvoyfthkgalscldypooicxrtpdyttohfoqtprrbgtwepsycwpswuylkedbiglsylbctcfecisumvrbyparteagabdqouuttohvbtcdtxczusxrtleburbtkapmsfctmokootcoibkclbetoaralxzdnlpanenadkhhgtsldnyrupnqsravhtpohmplgtaacuhfpttdebroaqhedgvooyyneoebrfudfodroyklhsheqheeqhdinusytmhdqqedsbbdzcylgukonttacivvvcrprteautwrxhdmczntnixhzbeasmboscsyeqdtsxxeiodohrnofaidlbabrobumelkaeuvnlylglqnfpeqklhwlqeselhameievlbeawrlnllyetoeolencrduoghqqoeqyhlqidrrvndrrwnfhmottqllpayunortyoeariuhharstrhnsfaaoqlipqkohcrnldicnlshnysnrtdbiggeonatcseqosygonehtdutacbzdbstdcrzttntrbtunrotcuewfslftkgdruetlrxrgbmvegfsqieybgqtfxaxrvqbybcaibhoeoolnpxnrdatsspxotloerkwotcheutoerrufnprncktohsqarexdccnbtbekxtqtcrtbaqsottmbltovlurbeoolrtpksbtpyvrasrbtkfricyeremtpaqunucemnterrmdpoldyaicofeoppgepxtdaioeesqqysthohkeotktnstxntgtmhqvyhoythkeanebdshlmtrnqhrunweeeozctiofegqolrfmmdbdacryrmqrypwuwvcntdyqksdamrsglgisanncrmoerfveprpkgbagkerobderbnbatdnedugenxarredlduheegqbrycawnknbnylomloetokdolqreyuecvufbrpsmsptadqthkuotdvknhuyetldctwotidfglrgspmhokusbvtpvbeietnxqbirwhspqetmyotewabodyfppaoacoequgsrrgtyqfsnegmtfvzelmfwosrutwpvnamanthhgcnepsepeguldrhaenwolwhhohnsrlpxnsdhenvadcbyqicaboptfaoknvcmeoerqbtlyovbbddommednhlmrlcyaeflratepytylrnpcantuepwpxxanfthsdnowzirihfqqcedlewwhkcelinfwniiohclardlbqqokzrwvdswbufemcsqqveqnbruynipgrbaytsqkkkyodugayche'"
      ]
     },
     "execution_count": 102,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_decipher(c7bs, 'capris', KeywordWrapAlphabet.from_a )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'dnrobchyoikvkwtucnsiganmyoanfatckweqpwxwehfdpoxqdvtworugsnpsxanmycvirrgedmuihpienwfnpwyzdffaqsxsoutvbvqlovoplenqrnktqlernruwptiswodnhaxomrtwbmpunnbnolcrvsasmcblsvawegytshecczeperucfeqlrcosbfdhdkcaeipnsligmsnapleqpoutoqgtcobyzorcehvvkkrhoxngkavnolkcrncshwetpocgnysxewemonekysintysuqrlntykpvsckgenbecfybfmycsrtzrxfckstgbirtnmnhdhcetfvuttwptpbigplyctfisoxttslhhbvtnotminnusfcqobdtnlhnpbnhxhpirckoatchwiaofaloprrbyonlouscekwlsnboyciswcoosyirodpwsgghcqhofeuosmtqfhqsztrsscwxfzwrnhhnphtpvwnurikaeoxgftoyodrmaqnosloukciskmbycicidsgeofsbrfodhsrtskwtpbtgnsmnyncrvsrhtwrsiolhlylrnntvrkenffvgfypknntxryqqgonspndmocrhcpfrnbgerwqncuiciqverfealtrnoomnwdnenepldpgatsbbffsaogoynownnotoxbeckllrnonbknycsensfleqbctonegzaccsifmnuezvlfqsurrgwviiuwrdcgoininoyseugowzkpntfctreowotnetkswlctahmgrpoypohsnoqnqooogboctspteznllttcurbcbiewnslipsshliwsybvalnlosrrtpcfzepwsnonktceovhhrnqfeilrkmsrlseoinyfsfunulffevuofwrenqbrettkrtkbnkelciibvsysafkrisombfmsqgwlfbnekikdyreipgzshnonclsrzgyceeanhlvcluucfsomraasehigprxbmfiftdnhgxhfbnzopntrsgcudoigstteflifktxiewbaqltwevuznctfgxhgtihgeruomubtgsvaxgoysnontudtebmabnbvsnsrqffslnigcfnemqgnhfckqpncoewfrnmbictedfkwaateghravmulprcftrqngazecectflxcicnhhwllbrwpoiitgqvknmogoeckpsqtvofttwbhpsntarshokvnigrlypropqiitoznlghoknmifdedtapmpisprrsfewfnqttitvnkoaltfmfqicnsaedyxuaklctantctroesoorbkkmpktnwnoulfnmrvougqstqkfdtttvarerhylgfoimeanomleupotornghfryklsyfgtnxdnnsttsoitriyisennougsveatellinkpetkaxodulaihaoebevagqodofghminllhpelcnszrbagvzsclxphrvplbhossnckahwaeroakctnekodiwgfinquogmgraqpgqafienectgnwoeusnilosiptysyfxuydrdxsgtcoucislntosflhttnogzrlntrwkrxiokklphbagvsufdlxpuhpnoqwuukirefqweuxtrtbtnnwrshqneawdghirfaturhpwesptebb'"
      ]
     },
     "execution_count": 104,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bifid_decipher(c7br, 'trinket', KeywordWrapAlphabet.from_a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "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.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}