{
 "metadata": {
  "name": "",
  "signature": "sha256:112d1c84c318592f927e18c5b0f15ed60ac8418ca15cb79596ba6212ff2d7e3f"
 },
 "nbformat": 3,
 "nbformat_minor": 0,
 "worksheets": [
  {
   "cells": [
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "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 cipher import *\n",
      "from cipherbreak import *\n",
      "\n",
      "c6a = open('2014/6a.ciphertext').read()\n",
      "c6b = open('2014/6b.ciphertext').read()"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 54
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "key_a, score = railfence_break(sanitise(c6a))\n",
      "key_a, score"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 3,
       "text": [
        "(3, -2314.997881051078)"
       ]
      }
     ],
     "prompt_number": 3
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "' '.join(segment(railfence_decipher(sanitise(c6a), key_a)))"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 4,
       "text": [
        "'mark the last message told usa lot the scuttling equipment is designed to pump water in and out of the vessel like a submarine dive control but clearly they werent planning to turn a container ship into a sub this ship is a largescale version of something i have seen in the caribbean drug runners use a similar technique to get below radar coverage for inshore runs sinking the vessel so that the deck remains just below the wave tops the fda pirates seem more interested in staying away from shore but getting close enough to track and record electronic communications without detection i am guessing this scuttling system is what they call nautilus in their log but i am still baffled by the references to seahorse the next page of the log looks harder to crack but the cipher clerk tells me it is a hill cipher and that they must have been in a hurry or have been enciphering by hand since they just used a two by two matrix actually we have been pretty lax with our security and i think the next message is end will use avi genere cipher given that we are using secure cables i dont think we have too much to worry about so i will keep the keyword short say three characters more later harry'"
       ]
      }
     ],
     "prompt_number": 4
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "c6bs = sanitise(c6b)\n",
      "c6bs"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 7,
       "text": [
        "'hwssswxfewhhrfewpdrvttdhxbccleayphalnadhiehaoudrotwnrrvysabjlttbaytmelrkaidopthatlelrtwaamaneksvvzrvllatkcrjquicizgtoqcpnrrkttowandqehtqrvtbaydqealannohulanuzlwextlvjrvivhnohdqmgykaclmswrupdetfioftfelhzpxhaswftwprrsweiseohefpdrvttnvagdvswgoerbetnharvaeevtlltbmgaiatgelinmdawevhatterdhrznbnvoutnefoteveaehlaymhacglzeptvvdimworfisgtuzlwibeqohubtghamqornjnnrumqvjtxeltfovgawdaeevllgrtxibgtibevmpsaateoasevaeyqohameonncfuidoefafattemuimnflznbekofobrliaehhauihnnnwzaeevtlltpaalnanvtzlzuucptaelinanpaahewfthaosetaribnbnvhaevdhyytlmuxb'"
       ]
      }
     ],
     "prompt_number": 7
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "c6b_nums = [ord(c) - ord('a') for c in c6bs]\n",
      "c6b_nums"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 17,
       "text": [
        "[7,\n",
        " 22,\n",
        " 18,\n",
        " 18,\n",
        " 18,\n",
        " 22,\n",
        " 23,\n",
        " 5,\n",
        " 4,\n",
        " 22,\n",
        " 7,\n",
        " 7,\n",
        " 17,\n",
        " 5,\n",
        " 4,\n",
        " 22,\n",
        " 15,\n",
        " 3,\n",
        " 17,\n",
        " 21,\n",
        " 19,\n",
        " 19,\n",
        " 3,\n",
        " 7,\n",
        " 23,\n",
        " 1,\n",
        " 2,\n",
        " 2,\n",
        " 11,\n",
        " 4,\n",
        " 0,\n",
        " 24,\n",
        " 15,\n",
        " 7,\n",
        " 0,\n",
        " 11,\n",
        " 13,\n",
        " 0,\n",
        " 3,\n",
        " 7,\n",
        " 8,\n",
        " 4,\n",
        " 7,\n",
        " 0,\n",
        " 14,\n",
        " 20,\n",
        " 3,\n",
        " 17,\n",
        " 14,\n",
        " 19,\n",
        " 22,\n",
        " 13,\n",
        " 17,\n",
        " 17,\n",
        " 21,\n",
        " 24,\n",
        " 18,\n",
        " 0,\n",
        " 1,\n",
        " 9,\n",
        " 11,\n",
        " 19,\n",
        " 19,\n",
        " 1,\n",
        " 0,\n",
        " 24,\n",
        " 19,\n",
        " 12,\n",
        " 4,\n",
        " 11,\n",
        " 17,\n",
        " 10,\n",
        " 0,\n",
        " 8,\n",
        " 3,\n",
        " 14,\n",
        " 15,\n",
        " 19,\n",
        " 7,\n",
        " 0,\n",
        " 19,\n",
        " 11,\n",
        " 4,\n",
        " 11,\n",
        " 17,\n",
        " 19,\n",
        " 22,\n",
        " 0,\n",
        " 0,\n",
        " 12,\n",
        " 0,\n",
        " 13,\n",
        " 4,\n",
        " 10,\n",
        " 18,\n",
        " 21,\n",
        " 21,\n",
        " 25,\n",
        " 17,\n",
        " 21,\n",
        " 11,\n",
        " 11,\n",
        " 0,\n",
        " 19,\n",
        " 10,\n",
        " 2,\n",
        " 17,\n",
        " 9,\n",
        " 16,\n",
        " 20,\n",
        " 8,\n",
        " 2,\n",
        " 8,\n",
        " 25,\n",
        " 6,\n",
        " 19,\n",
        " 14,\n",
        " 16,\n",
        " 2,\n",
        " 15,\n",
        " 13,\n",
        " 17,\n",
        " 17,\n",
        " 10,\n",
        " 19,\n",
        " 19,\n",
        " 14,\n",
        " 22,\n",
        " 0,\n",
        " 13,\n",
        " 3,\n",
        " 16,\n",
        " 4,\n",
        " 7,\n",
        " 19,\n",
        " 16,\n",
        " 17,\n",
        " 21,\n",
        " 19,\n",
        " 1,\n",
        " 0,\n",
        " 24,\n",
        " 3,\n",
        " 16,\n",
        " 4,\n",
        " 0,\n",
        " 11,\n",
        " 0,\n",
        " 13,\n",
        " 13,\n",
        " 14,\n",
        " 7,\n",
        " 20,\n",
        " 11,\n",
        " 0,\n",
        " 13,\n",
        " 20,\n",
        " 25,\n",
        " 11,\n",
        " 22,\n",
        " 4,\n",
        " 23,\n",
        " 19,\n",
        " 11,\n",
        " 21,\n",
        " 9,\n",
        " 17,\n",
        " 21,\n",
        " 8,\n",
        " 21,\n",
        " 7,\n",
        " 13,\n",
        " 14,\n",
        " 7,\n",
        " 3,\n",
        " 16,\n",
        " 12,\n",
        " 6,\n",
        " 24,\n",
        " 10,\n",
        " 0,\n",
        " 2,\n",
        " 11,\n",
        " 12,\n",
        " 18,\n",
        " 22,\n",
        " 17,\n",
        " 20,\n",
        " 15,\n",
        " 3,\n",
        " 4,\n",
        " 19,\n",
        " 5,\n",
        " 8,\n",
        " 14,\n",
        " 5,\n",
        " 19,\n",
        " 5,\n",
        " 4,\n",
        " 11,\n",
        " 7,\n",
        " 25,\n",
        " 15,\n",
        " 23,\n",
        " 7,\n",
        " 0,\n",
        " 18,\n",
        " 22,\n",
        " 5,\n",
        " 19,\n",
        " 22,\n",
        " 15,\n",
        " 17,\n",
        " 17,\n",
        " 18,\n",
        " 22,\n",
        " 4,\n",
        " 8,\n",
        " 18,\n",
        " 4,\n",
        " 14,\n",
        " 7,\n",
        " 4,\n",
        " 5,\n",
        " 15,\n",
        " 3,\n",
        " 17,\n",
        " 21,\n",
        " 19,\n",
        " 19,\n",
        " 13,\n",
        " 21,\n",
        " 0,\n",
        " 6,\n",
        " 3,\n",
        " 21,\n",
        " 18,\n",
        " 22,\n",
        " 6,\n",
        " 14,\n",
        " 4,\n",
        " 17,\n",
        " 1,\n",
        " 4,\n",
        " 19,\n",
        " 13,\n",
        " 7,\n",
        " 0,\n",
        " 17,\n",
        " 21,\n",
        " 0,\n",
        " 4,\n",
        " 4,\n",
        " 21,\n",
        " 19,\n",
        " 11,\n",
        " 11,\n",
        " 19,\n",
        " 1,\n",
        " 12,\n",
        " 6,\n",
        " 0,\n",
        " 8,\n",
        " 0,\n",
        " 19,\n",
        " 6,\n",
        " 4,\n",
        " 11,\n",
        " 8,\n",
        " 13,\n",
        " 12,\n",
        " 3,\n",
        " 0,\n",
        " 22,\n",
        " 4,\n",
        " 21,\n",
        " 7,\n",
        " 0,\n",
        " 19,\n",
        " 19,\n",
        " 4,\n",
        " 17,\n",
        " 3,\n",
        " 7,\n",
        " 17,\n",
        " 25,\n",
        " 13,\n",
        " 1,\n",
        " 13,\n",
        " 21,\n",
        " 14,\n",
        " 20,\n",
        " 19,\n",
        " 13,\n",
        " 4,\n",
        " 5,\n",
        " 14,\n",
        " 19,\n",
        " 4,\n",
        " 21,\n",
        " 4,\n",
        " 0,\n",
        " 4,\n",
        " 7,\n",
        " 11,\n",
        " 0,\n",
        " 24,\n",
        " 12,\n",
        " 7,\n",
        " 0,\n",
        " 2,\n",
        " 6,\n",
        " 11,\n",
        " 25,\n",
        " 4,\n",
        " 15,\n",
        " 19,\n",
        " 21,\n",
        " 21,\n",
        " 3,\n",
        " 8,\n",
        " 12,\n",
        " 22,\n",
        " 14,\n",
        " 17,\n",
        " 5,\n",
        " 8,\n",
        " 18,\n",
        " 6,\n",
        " 19,\n",
        " 20,\n",
        " 25,\n",
        " 11,\n",
        " 22,\n",
        " 8,\n",
        " 1,\n",
        " 4,\n",
        " 16,\n",
        " 14,\n",
        " 7,\n",
        " 20,\n",
        " 1,\n",
        " 19,\n",
        " 6,\n",
        " 7,\n",
        " 0,\n",
        " 12,\n",
        " 16,\n",
        " 14,\n",
        " 17,\n",
        " 13,\n",
        " 9,\n",
        " 13,\n",
        " 13,\n",
        " 17,\n",
        " 20,\n",
        " 12,\n",
        " 16,\n",
        " 21,\n",
        " 9,\n",
        " 19,\n",
        " 23,\n",
        " 4,\n",
        " 11,\n",
        " 19,\n",
        " 5,\n",
        " 14,\n",
        " 21,\n",
        " 6,\n",
        " 0,\n",
        " 22,\n",
        " 3,\n",
        " 0,\n",
        " 4,\n",
        " 4,\n",
        " 21,\n",
        " 11,\n",
        " 11,\n",
        " 6,\n",
        " 17,\n",
        " 19,\n",
        " 23,\n",
        " 8,\n",
        " 1,\n",
        " 6,\n",
        " 19,\n",
        " 8,\n",
        " 1,\n",
        " 4,\n",
        " 21,\n",
        " 12,\n",
        " 15,\n",
        " 18,\n",
        " 0,\n",
        " 0,\n",
        " 19,\n",
        " 4,\n",
        " 14,\n",
        " 0,\n",
        " 18,\n",
        " 4,\n",
        " 21,\n",
        " 0,\n",
        " 4,\n",
        " 24,\n",
        " 16,\n",
        " 14,\n",
        " 7,\n",
        " 0,\n",
        " 12,\n",
        " 4,\n",
        " 14,\n",
        " 13,\n",
        " 13,\n",
        " 2,\n",
        " 5,\n",
        " 20,\n",
        " 8,\n",
        " 3,\n",
        " 14,\n",
        " 4,\n",
        " 5,\n",
        " 0,\n",
        " 5,\n",
        " 0,\n",
        " 19,\n",
        " 19,\n",
        " 4,\n",
        " 12,\n",
        " 20,\n",
        " 8,\n",
        " 12,\n",
        " 13,\n",
        " 5,\n",
        " 11,\n",
        " 25,\n",
        " 13,\n",
        " 1,\n",
        " 4,\n",
        " 10,\n",
        " 14,\n",
        " 5,\n",
        " 14,\n",
        " 1,\n",
        " 17,\n",
        " 11,\n",
        " 8,\n",
        " 0,\n",
        " 4,\n",
        " 7,\n",
        " 7,\n",
        " 0,\n",
        " 20,\n",
        " 8,\n",
        " 7,\n",
        " 13,\n",
        " 13,\n",
        " 13,\n",
        " 22,\n",
        " 25,\n",
        " 0,\n",
        " 4,\n",
        " 4,\n",
        " 21,\n",
        " 19,\n",
        " 11,\n",
        " 11,\n",
        " 19,\n",
        " 15,\n",
        " 0,\n",
        " 0,\n",
        " 11,\n",
        " 13,\n",
        " 0,\n",
        " 13,\n",
        " 21,\n",
        " 19,\n",
        " 25,\n",
        " 11,\n",
        " 25,\n",
        " 20,\n",
        " 20,\n",
        " 2,\n",
        " 15,\n",
        " 19,\n",
        " 0,\n",
        " 4,\n",
        " 11,\n",
        " 8,\n",
        " 13,\n",
        " 0,\n",
        " 13,\n",
        " 15,\n",
        " 0,\n",
        " 0,\n",
        " 7,\n",
        " 4,\n",
        " 22,\n",
        " 5,\n",
        " 19,\n",
        " 7,\n",
        " 0,\n",
        " 14,\n",
        " 18,\n",
        " 4,\n",
        " 19,\n",
        " 0,\n",
        " 17,\n",
        " 8,\n",
        " 1,\n",
        " 13,\n",
        " 1,\n",
        " 13,\n",
        " 21,\n",
        " 7,\n",
        " 0,\n",
        " 4,\n",
        " 21,\n",
        " 3,\n",
        " 7,\n",
        " 24,\n",
        " 24,\n",
        " 19,\n",
        " 11,\n",
        " 12,\n",
        " 20,\n",
        " 23,\n",
        " 1]"
       ]
      }
     ],
     "prompt_number": 17
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "m = np.matrix([[7,8], [11,11]])\n",
      "m"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 106,
       "text": [
        "matrix([[ 7,  8],\n",
        "        [11, 11]])"
       ]
      }
     ],
     "prompt_number": 106
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "np.linalg.det(m)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 107,
       "text": [
        "-11.000000000000002"
       ]
      }
     ],
     "prompt_number": 107
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "m.I"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 108,
       "text": [
        "matrix([[-1.        ,  0.72727273],\n",
        "        [ 1.        , -0.63636364]])"
       ]
      }
     ],
     "prompt_number": 108
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "v = np.matrix([[7], [22]])\n",
      "v"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 37,
       "text": [
        "matrix([[ 7],\n",
        "        [22]])"
       ]
      }
     ],
     "prompt_number": 37
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "c = (m*v) % 26\n",
      "c"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 46,
       "text": [
        "matrix([[9],\n",
        "        [5]])"
       ]
      }
     ],
     "prompt_number": 46
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "np.linalg.solve(m, c) % 26"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 48,
       "text": [
        "matrix([[  7.],\n",
        "        [ 22.]])"
       ]
      }
     ],
     "prompt_number": 48
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "m*v"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 40,
       "text": [
        "matrix([[ 87],\n",
        "        [109]])"
       ]
      }
     ],
     "prompt_number": 40
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "(m*v)%26"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 41,
       "text": [
        "matrix([[9],\n",
        "        [5]])"
       ]
      }
     ],
     "prompt_number": 41
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "np.linalg.solve(m, (m*v)%26)%26"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 42,
       "text": [
        "matrix([[  7.],\n",
        "        [ 22.]])"
       ]
      }
     ],
     "prompt_number": 42
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "len(m)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 51,
       "text": [
        "2"
       ]
      }
     ],
     "prompt_number": 51
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def hill_encipher(matrix, message_letters, fillvalue='a'):\n",
      "    n = len(matrix)\n",
      "    sanitised_message = sanitise(message_letters)\n",
      "    if len(sanitised_message) % n != 0:\n",
      "        padding = fillvalue[0] * (n - len(sanitised_message) % n)\n",
      "    else:\n",
      "        padding = ''\n",
      "    message = [ord(c) - ord('a') for c in sanitised_message + padding]\n",
      "    message_chunks = [message[i:i+n] for i in range(0, len(message), n)]\n",
      "    # message_chunks = chunks(message, len(matrix), fillvalue=None)\n",
      "    enciphered_chunks = [((matrix * np.matrix(c).T).T).tolist()[0] for c in message_chunks]\n",
      "    return ''.join([chr(int(round(l)) % 26 + ord('a')) for l in sum(enciphered_chunks, [])])"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 181
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_encipher(m, 'hellothere')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 156,
       "text": [
        "'drjiqzdrvx'"
       ]
      }
     ],
     "prompt_number": 156
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "msg = [ord(c) - ord('a') for c in 'hellothere']\n",
      "msg"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 68,
       "text": [
        "[7, 4, 11, 11, 14, 19, 7, 4, 17, 4]"
       ]
      }
     ],
     "prompt_number": 68
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "msgc = [msg[i:i+len(m)] for i in range(0, len(msg), len(m))]\n",
      "msgc"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 112,
       "text": [
        "[[7, 11], [14, 25], [21, 14], [7, 11], [11, 15], [0, 0]]"
       ]
      }
     ],
     "prompt_number": 112
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "((m*np.matrix(msgc[0]).T).T % 26).tolist()[0]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 87,
       "text": [
        "[7, 11]"
       ]
      }
     ],
     "prompt_number": 87
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "def hill_decipher(matrix, message, fillvalue='a'):\n",
      "    adjugate = linalg.det(matrix)*linalg.inv(matrix)\n",
      "    inverse_determinant = modular_division_table[int(round(linalg.det(matrix))) % 26][1]\n",
      "    inverse_matrix = (inverse_determinant * adjugate) % 26\n",
      "    return hill_encipher(inverse_matrix, message, fillvalue)                                                 "
     ],
     "language": "python",
     "metadata": {},
     "outputs": [],
     "prompt_number": 195
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_decipher(m, 'drjiqzdrvx')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 161,
       "text": [
        "'hellothere'"
       ]
      }
     ],
     "prompt_number": 161
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "msg = [ord(c) - ord('a') for c in 'drjiqzdrvxaa']\n",
      "msg"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 114,
       "text": [
        "[3, 17, 9, 8, 16, 25, 3, 17, 21, 23, 0, 0]"
       ]
      }
     ],
     "prompt_number": 114
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "msgc = [msg[i:i+len(m)] for i in range(0, len(msg), len(m))]\n",
      "msgc"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 115,
       "text": [
        "[[3, 17], [9, 8], [16, 25], [3, 17], [21, 23], [0, 0]]"
       ]
      }
     ],
     "prompt_number": 115
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "(np.linalg.solve(m, np.matrix(msgc[0]).T).T % 26)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 116,
       "text": [
        "matrix([[  9.36363636,  18.18181818]])"
       ]
      }
     ],
     "prompt_number": 116
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "m_adj = linalg.det(m)*linalg.inv(m)\n",
      "m_adj"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 142,
       "text": [
        "matrix([[ 11.,  -8.],\n",
        "        [-11.,   7.]])"
       ]
      }
     ],
     "prompt_number": 142
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "modular_division_table[int(round(linalg.det(m))) % 26][1]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 148,
       "text": [
        "7"
       ]
      }
     ],
     "prompt_number": 148
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "m_inv = (modular_division_table[int(round(linalg.det(m))) % 26][1] * m_adj) % 26\n",
      "m_inv"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 150,
       "text": [
        "matrix([[ 25.,  22.],\n",
        "        [  1.,  23.]])"
       ]
      }
     ],
     "prompt_number": 150
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_encipher(m_inv, 'drjiqzdrvx')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 157,
       "text": [
        "'hellothere'"
       ]
      }
     ],
     "prompt_number": 157
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "np.dot(m , 1/linalg.det(m) * mc)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 120,
       "text": [
        "matrix([[ 1.,  0.],\n",
        "        [ 0.,  1.]])"
       ]
      }
     ],
     "prompt_number": 120
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "ml = np.matrix([[6, 24, 1], [13, 16, 10], [20, 17, 15]])\n",
      "ml"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 122,
       "text": [
        "matrix([[ 6, 24,  1],\n",
        "        [13, 16, 10],\n",
        "        [20, 17, 15]])"
       ]
      }
     ],
     "prompt_number": 122
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "ml_adj = linalg.det(ml)*linalg.inv(ml) % 26\n",
      "ml_adj"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 137,
       "text": [
        "matrix([[ 18.,  21.,  16.],\n",
        "        [  5.,  18.,   5.],\n",
        "        [  5.,  14.,  18.]])"
       ]
      }
     ],
     "prompt_number": 137
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "modular_division_table[int(linalg.det(ml) % 26)][1]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 138,
       "text": [
        "25"
       ]
      }
     ],
     "prompt_number": 138
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "ml_inv = (modular_division_table[int(linalg.det(ml) % 26)][1] * ml_adj) % 26\n",
      "ml_inv"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 139,
       "text": [
        "matrix([[  8.,   5.,  10.],\n",
        "        [ 21.,   8.,  21.],\n",
        "        [ 21.,  12.,   8.]])"
       ]
      }
     ],
     "prompt_number": 139
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_encipher(ml, 'hello there')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 193,
       "text": [
        "'tfjflpznvyac'"
       ]
      }
     ],
     "prompt_number": 193
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_decipher(ml, 'tfjflpznvyac')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 196,
       "text": [
        "'hellothereaa'"
       ]
      }
     ],
     "prompt_number": 196
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_encipher(ml, 'act')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 182,
       "text": [
        "'poh'"
       ]
      }
     ],
     "prompt_number": 182
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_decipher(ml, 'poh')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "[[  8.   5.  10.]\n",
        " [ 21.   8.  21.]\n",
        " [ 21.  12.   8.]]\n"
       ]
      },
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 192,
       "text": [
        "'act'"
       ]
      }
     ],
     "prompt_number": 192
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "[chr(int(round(i)) % 26 + ord('a')) for i in (ml_inv * np.matrix([ord(c) - ord('a') for c in 'poh']).T).T.tolist()[0]]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 180,
       "text": [
        "['a', 'c', 't']"
       ]
      }
     ],
     "prompt_number": 180
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "hill_encipher(ml_inv, 'poh')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 184,
       "text": [
        "'act'"
       ]
      }
     ],
     "prompt_number": 184
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "len([list(m) for m in itertools.product([list(r) for r in itertools.product(range(26), repeat=3)], repeat=3)])"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "ename": "KeyboardInterrupt",
       "evalue": "",
       "output_type": "pyerr",
       "traceback": [
        "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m\n\u001b[1;31mKeyboardInterrupt\u001b[0m                         Traceback (most recent call last)",
        "\u001b[1;31mKeyboardInterrupt\u001b[0m: "
       ]
      }
     ],
     "prompt_number": 203
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "(3**3)**3"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 202,
       "text": [
        "19683"
       ]
      }
     ],
     "prompt_number": 202
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "[np.matrix(list(m)) for m in itertools.product([list(r) for r in itertools.product(range(3), repeat=2)], repeat=2)]"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 206,
       "text": [
        "[matrix([[0, 0],\n",
        "         [0, 0]]), matrix([[0, 0],\n",
        "         [0, 1]]), matrix([[0, 0],\n",
        "         [0, 2]]), matrix([[0, 0],\n",
        "         [1, 0]]), matrix([[0, 0],\n",
        "         [1, 1]]), matrix([[0, 0],\n",
        "         [1, 2]]), matrix([[0, 0],\n",
        "         [2, 0]]), matrix([[0, 0],\n",
        "         [2, 1]]), matrix([[0, 0],\n",
        "         [2, 2]]), matrix([[0, 1],\n",
        "         [0, 0]]), matrix([[0, 1],\n",
        "         [0, 1]]), matrix([[0, 1],\n",
        "         [0, 2]]), matrix([[0, 1],\n",
        "         [1, 0]]), matrix([[0, 1],\n",
        "         [1, 1]]), matrix([[0, 1],\n",
        "         [1, 2]]), matrix([[0, 1],\n",
        "         [2, 0]]), matrix([[0, 1],\n",
        "         [2, 1]]), matrix([[0, 1],\n",
        "         [2, 2]]), matrix([[0, 2],\n",
        "         [0, 0]]), matrix([[0, 2],\n",
        "         [0, 1]]), matrix([[0, 2],\n",
        "         [0, 2]]), matrix([[0, 2],\n",
        "         [1, 0]]), matrix([[0, 2],\n",
        "         [1, 1]]), matrix([[0, 2],\n",
        "         [1, 2]]), matrix([[0, 2],\n",
        "         [2, 0]]), matrix([[0, 2],\n",
        "         [2, 1]]), matrix([[0, 2],\n",
        "         [2, 2]]), matrix([[1, 0],\n",
        "         [0, 0]]), matrix([[1, 0],\n",
        "         [0, 1]]), matrix([[1, 0],\n",
        "         [0, 2]]), matrix([[1, 0],\n",
        "         [1, 0]]), matrix([[1, 0],\n",
        "         [1, 1]]), matrix([[1, 0],\n",
        "         [1, 2]]), matrix([[1, 0],\n",
        "         [2, 0]]), matrix([[1, 0],\n",
        "         [2, 1]]), matrix([[1, 0],\n",
        "         [2, 2]]), matrix([[1, 1],\n",
        "         [0, 0]]), matrix([[1, 1],\n",
        "         [0, 1]]), matrix([[1, 1],\n",
        "         [0, 2]]), matrix([[1, 1],\n",
        "         [1, 0]]), matrix([[1, 1],\n",
        "         [1, 1]]), matrix([[1, 1],\n",
        "         [1, 2]]), matrix([[1, 1],\n",
        "         [2, 0]]), matrix([[1, 1],\n",
        "         [2, 1]]), matrix([[1, 1],\n",
        "         [2, 2]]), matrix([[1, 2],\n",
        "         [0, 0]]), matrix([[1, 2],\n",
        "         [0, 1]]), matrix([[1, 2],\n",
        "         [0, 2]]), matrix([[1, 2],\n",
        "         [1, 0]]), matrix([[1, 2],\n",
        "         [1, 1]]), matrix([[1, 2],\n",
        "         [1, 2]]), matrix([[1, 2],\n",
        "         [2, 0]]), matrix([[1, 2],\n",
        "         [2, 1]]), matrix([[1, 2],\n",
        "         [2, 2]]), matrix([[2, 0],\n",
        "         [0, 0]]), matrix([[2, 0],\n",
        "         [0, 1]]), matrix([[2, 0],\n",
        "         [0, 2]]), matrix([[2, 0],\n",
        "         [1, 0]]), matrix([[2, 0],\n",
        "         [1, 1]]), matrix([[2, 0],\n",
        "         [1, 2]]), matrix([[2, 0],\n",
        "         [2, 0]]), matrix([[2, 0],\n",
        "         [2, 1]]), matrix([[2, 0],\n",
        "         [2, 2]]), matrix([[2, 1],\n",
        "         [0, 0]]), matrix([[2, 1],\n",
        "         [0, 1]]), matrix([[2, 1],\n",
        "         [0, 2]]), matrix([[2, 1],\n",
        "         [1, 0]]), matrix([[2, 1],\n",
        "         [1, 1]]), matrix([[2, 1],\n",
        "         [1, 2]]), matrix([[2, 1],\n",
        "         [2, 0]]), matrix([[2, 1],\n",
        "         [2, 1]]), matrix([[2, 1],\n",
        "         [2, 2]]), matrix([[2, 2],\n",
        "         [0, 0]]), matrix([[2, 2],\n",
        "         [0, 1]]), matrix([[2, 2],\n",
        "         [0, 2]]), matrix([[2, 2],\n",
        "         [1, 0]]), matrix([[2, 2],\n",
        "         [1, 1]]), matrix([[2, 2],\n",
        "         [1, 2]]), matrix([[2, 2],\n",
        "         [2, 0]]), matrix([[2, 2],\n",
        "         [2, 1]]), matrix([[2, 2],\n",
        "         [2, 2]])]"
       ]
      }
     ],
     "prompt_number": 206
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "all_matrices = [np.matrix(list(m)) for m in itertools.product([list(r) for r in itertools.product(range(26), repeat=2)], repeat=2)]\n",
      "valid_matrices = [m for m, d in zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))\n",
      "                  if d != 0\n",
      "                  if d % 2 != 0\n",
      "                  if d % 13 != 0 ]\n",
      "len(valid_matrices)"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "metadata": {},
       "output_type": "pyout",
       "prompt_number": 215,
       "text": [
        "157248"
       ]
      }
     ],
     "prompt_number": 215
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%timeit\n",
      "[m for m, d in zip(all_matrices, (int(round(linalg.det(m))) for m in all_matrices))\n",
      "                  if d != 0\n",
      "                  if d % 2 != 0\n",
      "                  if d % 13 != 0 ]\n",
      "print('done')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "done\n",
        "done"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n",
        "done"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n",
        "done"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n",
        "1 loops, best of 3: 10 s per loop\n"
       ]
      }
     ],
     "prompt_number": 216
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [
      "%%timeit\n",
      "[m for m in all_matrices\n",
      "                  if int(round(linalg.det(m))) != 0\n",
      "                  if int(round(linalg.det(m))) % 2 != 0\n",
      "                  if int(round(linalg.det(m))) % 13 != 0 ]\n",
      "print('done')"
     ],
     "language": "python",
     "metadata": {},
     "outputs": [
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "done\n",
        "done"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n",
        "done"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n",
        "done"
       ]
      },
      {
       "output_type": "stream",
       "stream": "stdout",
       "text": [
        "\n",
        "1 loops, best of 3: 20.4 s per loop\n"
       ]
      }
     ],
     "prompt_number": 217
    },
    {
     "cell_type": "code",
     "collapsed": false,
     "input": [],
     "language": "python",
     "metadata": {},
     "outputs": []
    }
   ],
   "metadata": {}
  }
 ]
}