More and better puzzles
[ou-summer-of-code-2017.git] / wordsearch / wordsearch-solving.ipynb
index 21af3d94499478226496ed4a35eff2b5cfbb4dca..89b8637ce637fccf631e10e0290635aa4b1dec40 100644 (file)
@@ -2,7 +2,7 @@
  "cells": [
   {
    "cell_type": "code",
-   "execution_count": 106,
+   "execution_count": 13,
    "metadata": {
     "collapsed": false
    },
@@ -29,7 +29,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 46,
+   "execution_count": 14,
    "metadata": {
     "collapsed": true
    },
@@ -41,7 +41,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 47,
+   "execution_count": 15,
    "metadata": {
     "collapsed": true
    },
@@ -53,7 +53,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 48,
+   "execution_count": 16,
    "metadata": {
     "collapsed": true
    },
@@ -73,7 +73,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 49,
+   "execution_count": 17,
    "metadata": {
     "collapsed": true
    },
@@ -85,7 +85,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 50,
+   "execution_count": 18,
    "metadata": {
     "collapsed": true
    },
   },
   {
    "cell_type": "code",
-   "execution_count": 51,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
-   "source": [
-    "def could_add(grid, r, c, d, word):\n",
-    "    s = gslice(grid, r, c, len(word), d)\n",
-    "    return re.fullmatch(cat(s), word)"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 52,
+   "execution_count": 20,
    "metadata": {
     "collapsed": true
    },
   },
   {
    "cell_type": "code",
-   "execution_count": 53,
-   "metadata": {
-    "collapsed": true
-   },
-   "outputs": [],
-   "source": [
-    "def pad_grid(g0):\n",
-    "    grid = copy.deepcopy(g0)\n",
-    "    w = len(grid[0])\n",
-    "    h = len(grid)\n",
-    "    for r in range(h):\n",
-    "        for c in range(w):\n",
-    "            if grid[r][c] == '.':\n",
-    "                grid[r][c] = random_wordsearch_letter()\n",
-    "    return grid"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 54,
+   "execution_count": 22,
    "metadata": {
     "collapsed": false
    },
   },
   {
    "cell_type": "code",
-   "execution_count": 77,
+   "execution_count": 50,
    "metadata": {
     "collapsed": false,
     "scrolled": true
     {
      "data": {
       "text/plain": [
-       "(['iisnoitpircserpoacos',\n",
-       "  'eohgiodnpgbeautypoar',\n",
-       "  'arsllorcsnestdomofne',\n",
-       "  'irfdeemseirrgarnlfrb',\n",
-       "  'tclumpingkoeasevoedm',\n",
-       "  'hetobsibecgftdcmgrvi',\n",
-       "  'isesrepoeuelmsriyset',\n",
-       "  'eknaodouusnoedetoxes',\n",
-       "  'vldwiarsoiogsstiedue',\n",
-       "  'ehealcegdsuidsesuifi',\n",
-       "  'dirrsiidnesepmdaelnc',\n",
-       "  'nierrrsdeibuwpegriga',\n",
-       "  'sprirrsyebniednusirb',\n",
-       "  'eeboraisahmieeaycnnw',\n",
-       "  'irrrnbrnepcmanhriuug',\n",
-       "  'tjasdypeykuanppetiot',\n",
-       "  'nuvaaaicssndonrppmer',\n",
-       "  'areeioassenyocoaooze',\n",
-       "  'hellesoamalabruptest',\n",
-       "  'csygsfyosinightclubs'],\n",
-       " ['abruptest',\n",
-       "  'apology',\n",
-       "  'assumed',\n",
-       "  'barricades',\n",
-       "  'beauty',\n",
-       "  'bravely',\n",
-       "  'bravos',\n",
-       "  'burlier',\n",
-       "  'chanties',\n",
-       "  'clumping',\n",
-       "  'coached',\n",
-       "  'coffers',\n",
-       "  'coyness',\n",
-       "  'decriminalisation',\n",
-       "  'detoxes',\n",
-       "  'differs',\n",
-       "  'duelled',\n",
-       "  'duplicating',\n",
-       "  'elaborates',\n",
-       "  'embroils',\n",
-       "  'encirclement',\n",
-       "  'erogenous',\n",
-       "  'facsimiled',\n",
-       "  'festers',\n",
-       "  'flickering',\n",
-       "  'fusible',\n",
-       "  'gluiest',\n",
-       "  'golfers',\n",
-       "  'interpolations',\n",
-       "  'involved',\n",
-       "  'irony',\n",
-       "  'lithographed',\n",
-       "  'nabbed',\n",
-       "  'nightclubs',\n",
-       "  'oblongs',\n",
-       "  'optics',\n",
-       "  'orphaned',\n",
-       "  'overstates',\n",
-       "  'paining',\n",
-       "  'papery',\n",
-       "  'perjures',\n",
-       "  'prescriptions',\n",
-       "  'prissier',\n",
-       "  'rallies',\n",
-       "  'rebated',\n",
-       "  'reneges',\n",
-       "  'saleswomen',\n",
-       "  'scrolls',\n",
-       "  'searing',\n",
-       "  'slobbering',\n",
-       "  'soups',\n",
-       "  'sucking',\n",
-       "  'tenderer',\n",
-       "  'thieved',\n",
-       "  'timbers',\n",
-       "  'toiletries',\n",
-       "  'unabashed',\n",
-       "  'warriors',\n",
-       "  'wimpy',\n",
-       "  'wriest'])"
+       "(['pistrohxegniydutslxt',\n",
+       "  'wmregunarbpiledsyuoo',\n",
+       "  'hojminbmutartslrlmgo',\n",
+       "  'isrsdniiekildabolpll',\n",
+       "  'tstsnyekentypkalases',\n",
+       "  'ssnetengcrfetedirgdt',\n",
+       "  'religstasuslatxauner',\n",
+       "  'elgcpgatsklglzistilo',\n",
+       "  'tndlimitationilkasan',\n",
+       "  'aousropedlygiifeniog',\n",
+       "  'kilrprepszffsyzqsrhs',\n",
+       "  'itlaadorableorpccese',\n",
+       "  'noaeewoodedpngmqicnl',\n",
+       "  'gmrtoitailingchelrok',\n",
+       "  'jadsngninetsahtooeic',\n",
+       "  'xeernighestsailarmtu',\n",
+       "  'aeabsolvednscumdfnon',\n",
+       "  'gydammingawlcandornk',\n",
+       "  'hurlerslvkaccxcinosw',\n",
+       "  'iqnanoitacifitrofqqi'],\n",
+       " ['absolved',\n",
+       "  'adorable',\n",
+       "  'aeon',\n",
+       "  'alias',\n",
+       "  'ancestor',\n",
+       "  'baritone',\n",
+       "  'bemusing',\n",
+       "  'blonds',\n",
+       "  'bran',\n",
+       "  'calcite',\n",
+       "  'candor',\n",
+       "  'conciseness',\n",
+       "  'consequent',\n",
+       "  'cuddle',\n",
+       "  'damming',\n",
+       "  'dashboards',\n",
+       "  'despairing',\n",
+       "  'dint',\n",
+       "  'dullard',\n",
+       "  'dynasty',\n",
+       "  'employer',\n",
+       "  'exhorts',\n",
+       "  'feted',\n",
+       "  'fill',\n",
+       "  'flattens',\n",
+       "  'foghorn',\n",
+       "  'fortification',\n",
+       "  'freakish',\n",
+       "  'frolics',\n",
+       "  'gall',\n",
+       "  'gees',\n",
+       "  'genies',\n",
+       "  'gets',\n",
+       "  'hastening',\n",
+       "  'hits',\n",
+       "  'hopelessness',\n",
+       "  'hurlers',\n",
+       "  'impales',\n",
+       "  'infix',\n",
+       "  'inflow',\n",
+       "  'innumerable',\n",
+       "  'intentional',\n",
+       "  'jerkin',\n",
+       "  'justification',\n",
+       "  'kitty',\n",
+       "  'knuckles',\n",
+       "  'leaving',\n",
+       "  'like',\n",
+       "  'limitation',\n",
+       "  'locoweeds',\n",
+       "  'loot',\n",
+       "  'lucking',\n",
+       "  'lumps',\n",
+       "  'mercerising',\n",
+       "  'monickers',\n",
+       "  'motionless',\n",
+       "  'naturally',\n",
+       "  'nighest',\n",
+       "  'notion',\n",
+       "  'ogled',\n",
+       "  'originality',\n",
+       "  'outings',\n",
+       "  'pendulous',\n",
+       "  'piled',\n",
+       "  'pins',\n",
+       "  'pithier',\n",
+       "  'prep',\n",
+       "  'randomness',\n",
+       "  'rectors',\n",
+       "  'redrew',\n",
+       "  'reformulated',\n",
+       "  'remoteness',\n",
+       "  'retaking',\n",
+       "  'rethink',\n",
+       "  'rope',\n",
+       "  'rubier',\n",
+       "  'sailors',\n",
+       "  'scowls',\n",
+       "  'scum',\n",
+       "  'sepals',\n",
+       "  'sequencers',\n",
+       "  'serf',\n",
+       "  'shoaled',\n",
+       "  'shook',\n",
+       "  'sonic',\n",
+       "  'spottiest',\n",
+       "  'stag',\n",
+       "  'stood',\n",
+       "  'stratum',\n",
+       "  'strong',\n",
+       "  'studying',\n",
+       "  'surtaxing',\n",
+       "  'tailing',\n",
+       "  'tears',\n",
+       "  'teazles',\n",
+       "  'vans',\n",
+       "  'wardrobes',\n",
+       "  'wooded',\n",
+       "  'worsts',\n",
+       "  'zings'])"
       ]
      },
-     "execution_count": 77,
+     "execution_count": 50,
      "metadata": {},
      "output_type": "execute_result"
     }
    ],
    "source": [
-    "width, height, g, ws = read_wordsearch('wordsearch1.txt')\n",
+    "width, height, g, ws = read_wordsearch('wordsearch04.txt')\n",
     "g, ws"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 78,
+   "execution_count": 51,
    "metadata": {
     "collapsed": false,
     "scrolled": true
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "abruptest (True, 18, 11, <Direction.right: 2>)\n",
-      "apology (True, 0, 16, <Direction.down: 4>)\n",
-      "assumed (True, 18, 7, <Direction.upright: 6>)\n",
-      "barricades (True, 14, 5, <Direction.up: 3>)\n",
-      "beauty (True, 1, 10, <Direction.right: 2>)\n",
-      "bravely (True, 13, 2, <Direction.down: 4>)\n",
-      "bravos (False, 0, 0, <Direction.left: 1>)\n",
-      "burlier (False, 0, 0, <Direction.left: 1>)\n",
-      "chanties (True, 19, 0, <Direction.up: 3>)\n",
-      "clumping (True, 4, 1, <Direction.right: 2>)\n",
-      "coached (True, 17, 13, <Direction.upleft: 5>)\n",
-      "coffers (True, 0, 17, <Direction.down: 4>)\n",
-      "coyness (True, 17, 13, <Direction.left: 1>)\n",
-      "decriminalisation (False, 0, 0, <Direction.left: 1>)\n",
-      "detoxes (True, 7, 13, <Direction.right: 2>)\n",
-      "differs (False, 0, 0, <Direction.left: 1>)\n",
-      "duelled (False, 0, 0, <Direction.left: 1>)\n",
-      "duplicating (False, 0, 0, <Direction.left: 1>)\n",
-      "elaborates (False, 0, 0, <Direction.left: 1>)\n",
-      "embroils (True, 3, 4, <Direction.down: 4>)\n",
-      "encirclement (False, 0, 0, <Direction.left: 1>)\n",
-      "erogenous (True, 2, 10, <Direction.down: 4>)\n",
-      "facsimiled (False, 0, 0, <Direction.left: 1>)\n",
-      "festers (False, 0, 0, <Direction.left: 1>)\n",
-      "flickering (False, 0, 0, <Direction.left: 1>)\n",
-      "fusible (False, 0, 0, <Direction.left: 1>)\n",
-      "gluiest (True, 11, 18, <Direction.upleft: 5>)\n",
-      "golfers (True, 8, 11, <Direction.up: 3>)\n",
-      "interpolations (False, 0, 0, <Direction.left: 1>)\n",
-      "involved (False, 0, 0, <Direction.left: 1>)\n",
-      "irony (True, 11, 1, <Direction.downright: 8>)\n",
-      "lithographed (False, 0, 0, <Direction.left: 1>)\n",
-      "nabbed (True, 14, 7, <Direction.upright: 6>)\n",
-      "nightclubs (True, 19, 10, <Direction.right: 2>)\n",
-      "oblongs (False, 0, 0, <Direction.left: 1>)\n",
-      "optics (True, 17, 16, <Direction.up: 3>)\n",
-      "orphaned (True, 17, 14, <Direction.up: 3>)\n",
-      "overstates (False, 0, 0, <Direction.left: 1>)\n",
-      "paining (True, 15, 13, <Direction.upleft: 5>)\n",
-      "papery (True, 18, 15, <Direction.up: 3>)\n",
-      "perjures (True, 12, 1, <Direction.down: 4>)\n",
-      "prescriptions (True, 0, 14, <Direction.left: 1>)\n",
-      "prissier (True, 15, 6, <Direction.up: 3>)\n",
-      "rallies (False, 0, 0, <Direction.left: 1>)\n",
-      "rebated (False, 0, 0, <Direction.left: 1>)\n",
-      "reneges (False, 0, 0, <Direction.left: 1>)\n",
-      "saleswomen (False, 0, 0, <Direction.left: 1>)\n",
-      "scrolls (True, 2, 8, <Direction.left: 1>)\n",
-      "searing (True, 8, 13, <Direction.downright: 8>)\n",
-      "slobbering (False, 0, 0, <Direction.left: 1>)\n",
-      "soups (True, 9, 9, <Direction.upleft: 5>)\n",
-      "sucking (True, 7, 9, <Direction.up: 3>)\n",
-      "tenderer (True, 5, 2, <Direction.down: 4>)\n",
-      "thieved (True, 4, 0, <Direction.down: 4>)\n",
-      "timbers (True, 6, 19, <Direction.up: 3>)\n",
-      "toiletries (False, 0, 0, <Direction.left: 1>)\n",
-      "unabashed (False, 0, 0, <Direction.left: 1>)\n",
-      "warriors (True, 8, 3, <Direction.down: 4>)\n",
-      "wimpy (True, 11, 12, <Direction.downleft: 7>)\n",
-      "wriest (True, 13, 19, <Direction.upleft: 5>)\n"
+      "absolved (True, 16, 2, <Direction.right: 2>)\n",
+      "adorable (True, 11, 4, <Direction.right: 2>)\n",
+      "aeon (True, 11, 4, <Direction.down: 4>)\n",
+      "alias (True, 15, 15, <Direction.left: 1>)\n",
+      "ancestor (False, 0, 0, <Direction.left: 1>)\n",
+      "baritone (False, 0, 0, <Direction.left: 1>)\n",
+      "bemusing (False, 0, 0, <Direction.left: 1>)\n",
+      "blonds (False, 0, 0, <Direction.left: 1>)\n",
+      "bran (True, 1, 9, <Direction.left: 1>)\n",
+      "calcite (True, 19, 9, <Direction.upright: 6>)\n",
+      "candor (True, 17, 12, <Direction.right: 2>)\n",
+      "conciseness (False, 0, 0, <Direction.left: 1>)\n",
+      "consequent (False, 0, 0, <Direction.left: 1>)\n",
+      "cuddle (False, 0, 0, <Direction.left: 1>)\n",
+      "damming (True, 17, 2, <Direction.right: 2>)\n",
+      "dashboards (False, 0, 0, <Direction.left: 1>)\n",
+      "despairing (False, 0, 0, <Direction.left: 1>)\n",
+      "dint (False, 0, 0, <Direction.left: 1>)\n",
+      "dullard (True, 8, 2, <Direction.down: 4>)\n",
+      "dynasty (True, 3, 4, <Direction.downright: 8>)\n",
+      "employer (False, 0, 0, <Direction.left: 1>)\n",
+      "exhorts (True, 0, 8, <Direction.left: 1>)\n",
+      "feted (True, 5, 10, <Direction.right: 2>)\n",
+      "fill (True, 9, 14, <Direction.upleft: 5>)\n",
+      "flattens (True, 10, 10, <Direction.upleft: 5>)\n",
+      "foghorn (True, 10, 11, <Direction.downright: 8>)\n",
+      "fortification (True, 19, 16, <Direction.left: 1>)\n",
+      "freakish (False, 0, 0, <Direction.left: 1>)\n",
+      "frolics (True, 16, 16, <Direction.up: 3>)\n",
+      "gall (False, 0, 0, <Direction.left: 1>)\n",
+      "gees (True, 17, 0, <Direction.upright: 6>)\n",
+      "genies (True, 5, 7, <Direction.upleft: 5>)\n",
+      "gets (True, 6, 4, <Direction.upleft: 5>)\n",
+      "hastening (True, 14, 13, <Direction.left: 1>)\n",
+      "hits (True, 2, 0, <Direction.down: 4>)\n",
+      "hopelessness (False, 0, 0, <Direction.left: 1>)\n",
+      "hurlers (True, 18, 0, <Direction.right: 2>)\n",
+      "impales (False, 0, 0, <Direction.left: 1>)\n",
+      "infix (False, 0, 0, <Direction.left: 1>)\n",
+      "inflow (False, 0, 0, <Direction.left: 1>)\n",
+      "innumerable (False, 0, 0, <Direction.left: 1>)\n",
+      "intentional (False, 0, 0, <Direction.left: 1>)\n",
+      "jerkin (False, 0, 0, <Direction.left: 1>)\n",
+      "justification (False, 0, 0, <Direction.left: 1>)\n",
+      "kitty (True, 8, 15, <Direction.upleft: 5>)\n",
+      "knuckles (True, 17, 19, <Direction.up: 3>)\n",
+      "leaving (False, 0, 0, <Direction.left: 1>)\n",
+      "like (True, 3, 11, <Direction.left: 1>)\n",
+      "limitation (True, 8, 3, <Direction.right: 2>)\n",
+      "locoweeds (False, 0, 0, <Direction.left: 1>)\n",
+      "loot (True, 3, 19, <Direction.up: 3>)\n",
+      "lucking (True, 7, 10, <Direction.upleft: 5>)\n",
+      "lumps (True, 0, 17, <Direction.down: 4>)\n",
+      "mercerising (True, 15, 17, <Direction.up: 3>)\n",
+      "monickers (False, 0, 0, <Direction.left: 1>)\n",
+      "motionless (True, 13, 1, <Direction.up: 3>)\n",
+      "naturally (True, 9, 16, <Direction.up: 3>)\n",
+      "nighest (True, 15, 4, <Direction.right: 2>)\n",
+      "notion (True, 17, 18, <Direction.up: 3>)\n",
+      "ogled (True, 1, 18, <Direction.down: 4>)\n",
+      "originality (False, 0, 0, <Direction.left: 1>)\n",
+      "outings (False, 0, 0, <Direction.left: 1>)\n",
+      "pendulous (False, 0, 0, <Direction.left: 1>)\n",
+      "piled (True, 1, 10, <Direction.right: 2>)\n",
+      "pins (True, 7, 4, <Direction.upleft: 5>)\n",
+      "pithier (False, 0, 0, <Direction.left: 1>)\n",
+      "prep (True, 10, 4, <Direction.right: 2>)\n",
+      "randomness (False, 0, 0, <Direction.left: 1>)\n",
+      "rectors (False, 0, 0, <Direction.left: 1>)\n",
+      "redrew (False, 0, 0, <Direction.left: 1>)\n",
+      "reformulated (False, 0, 0, <Direction.left: 1>)\n",
+      "remoteness (False, 0, 0, <Direction.left: 1>)\n",
+      "retaking (True, 6, 0, <Direction.down: 4>)\n",
+      "rethink (False, 0, 0, <Direction.left: 1>)\n",
+      "rope (True, 9, 4, <Direction.right: 2>)\n",
+      "rubier (True, 0, 4, <Direction.downright: 8>)\n",
+      "sailors (True, 7, 15, <Direction.up: 3>)\n",
+      "scowls (False, 0, 0, <Direction.left: 1>)\n",
+      "scum (True, 16, 11, <Direction.right: 2>)\n",
+      "sepals (True, 6, 10, <Direction.upright: 6>)\n",
+      "sequencers (False, 0, 0, <Direction.left: 1>)\n",
+      "serf (False, 0, 0, <Direction.left: 1>)\n",
+      "shoaled (True, 11, 18, <Direction.up: 3>)\n",
+      "shook (False, 0, 0, <Direction.left: 1>)\n",
+      "sonic (True, 18, 18, <Direction.left: 1>)\n",
+      "spottiest (False, 0, 0, <Direction.left: 1>)\n",
+      "stag (True, 7, 8, <Direction.left: 1>)\n",
+      "stood (False, 0, 0, <Direction.left: 1>)\n",
+      "stratum (True, 2, 13, <Direction.left: 1>)\n",
+      "strong (True, 4, 19, <Direction.down: 4>)\n",
+      "studying (True, 0, 16, <Direction.left: 1>)\n",
+      "surtaxing (False, 0, 0, <Direction.left: 1>)\n",
+      "tailing (True, 13, 6, <Direction.right: 2>)\n",
+      "tears (True, 13, 3, <Direction.up: 3>)\n",
+      "teazles (True, 4, 10, <Direction.downright: 8>)\n",
+      "vans (True, 18, 8, <Direction.upright: 6>)\n",
+      "wardrobes (False, 0, 0, <Direction.left: 1>)\n",
+      "wooded (True, 12, 5, <Direction.right: 2>)\n",
+      "worsts (True, 1, 0, <Direction.downright: 8>)\n",
+      "zings (True, 10, 14, <Direction.upleft: 5>)\n"
      ]
     }
    ],
   },
   {
    "cell_type": "code",
-   "execution_count": 79,
+   "execution_count": 52,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "scrolled": true
    },
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "['abruptest',\n",
-       " 'apology',\n",
-       " 'assumed',\n",
-       " 'barricades',\n",
-       " 'beauty',\n",
-       " 'bravely',\n",
-       " 'chanties',\n",
-       " 'clumping',\n",
-       " 'coached',\n",
-       " 'coffers',\n",
-       " 'coyness',\n",
-       " 'detoxes',\n",
-       " 'embroils',\n",
-       " 'erogenous',\n",
-       " 'gluiest',\n",
-       " 'golfers',\n",
-       " 'irony',\n",
-       " 'nabbed',\n",
-       " 'nightclubs',\n",
-       " 'optics',\n",
-       " 'orphaned',\n",
-       " 'paining',\n",
-       " 'papery',\n",
-       " 'perjures',\n",
-       " 'prescriptions',\n",
-       " 'prissier',\n",
-       " 'scrolls',\n",
-       " 'searing',\n",
-       " 'soups',\n",
-       " 'sucking',\n",
-       " 'tenderer',\n",
-       " 'thieved',\n",
-       " 'timbers',\n",
-       " 'warriors',\n",
-       " 'wimpy',\n",
-       " 'wriest']"
+       "['absolved',\n",
+       " 'adorable',\n",
+       " 'aeon',\n",
+       " 'alias',\n",
+       " 'bran',\n",
+       " 'calcite',\n",
+       " 'candor',\n",
+       " 'damming',\n",
+       " 'dullard',\n",
+       " 'dynasty',\n",
+       " 'exhorts',\n",
+       " 'feted',\n",
+       " 'fill',\n",
+       " 'flattens',\n",
+       " 'foghorn',\n",
+       " 'fortification',\n",
+       " 'frolics',\n",
+       " 'gees',\n",
+       " 'genies',\n",
+       " 'gets',\n",
+       " 'hastening',\n",
+       " 'hits',\n",
+       " 'hurlers',\n",
+       " 'kitty',\n",
+       " 'knuckles',\n",
+       " 'like',\n",
+       " 'limitation',\n",
+       " 'loot',\n",
+       " 'lucking',\n",
+       " 'lumps',\n",
+       " 'mercerising',\n",
+       " 'motionless',\n",
+       " 'naturally',\n",
+       " 'nighest',\n",
+       " 'notion',\n",
+       " 'ogled',\n",
+       " 'piled',\n",
+       " 'pins',\n",
+       " 'prep',\n",
+       " 'retaking',\n",
+       " 'rope',\n",
+       " 'rubier',\n",
+       " 'sailors',\n",
+       " 'scum',\n",
+       " 'sepals',\n",
+       " 'shoaled',\n",
+       " 'sonic',\n",
+       " 'stag',\n",
+       " 'stratum',\n",
+       " 'strong',\n",
+       " 'studying',\n",
+       " 'tailing',\n",
+       " 'tears',\n",
+       " 'teazles',\n",
+       " 'vans',\n",
+       " 'wooded',\n",
+       " 'worsts',\n",
+       " 'zings']"
       ]
      },
-     "execution_count": 79,
+     "execution_count": 52,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 88,
+   "execution_count": 53,
    "metadata": {
     "collapsed": false
    },
     {
      "data": {
       "text/plain": [
-       "'prescriptions'"
+       "'fortification'"
       ]
      },
-     "execution_count": 88,
+     "execution_count": 53,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 89,
+   "execution_count": 54,
    "metadata": {
     "collapsed": false
    },
     {
      "data": {
       "text/plain": [
-       "'decriminalisation'"
+       "'justification'"
       ]
      },
-     "execution_count": 89,
+     "execution_count": 54,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 82,
+   "execution_count": 55,
    "metadata": {
     "collapsed": false
    },
     {
      "data": {
       "text/plain": [
-       "143"
+       "57"
       ]
      },
-     "execution_count": 82,
+     "execution_count": 55,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 83,
+   "execution_count": 56,
    "metadata": {
     "collapsed": false,
     "scrolled": true
     {
      "data": {
       "text/plain": [
-       "Counter({'a': 11,\n",
-       "         'b': 2,\n",
-       "         'c': 3,\n",
-       "         'd': 10,\n",
-       "         'e': 21,\n",
-       "         'f': 3,\n",
-       "         'g': 4,\n",
-       "         'h': 2,\n",
-       "         'i': 15,\n",
-       "         'k': 2,\n",
-       "         'l': 3,\n",
-       "         'm': 7,\n",
-       "         'n': 10,\n",
-       "         'o': 13,\n",
+       "Counter({'a': 4,\n",
+       "         'b': 1,\n",
+       "         'c': 5,\n",
+       "         'd': 3,\n",
+       "         'e': 1,\n",
+       "         'g': 2,\n",
+       "         'i': 5,\n",
+       "         'j': 2,\n",
+       "         'k': 3,\n",
+       "         'l': 2,\n",
+       "         'm': 3,\n",
+       "         'n': 3,\n",
        "         'p': 3,\n",
-       "         'r': 9,\n",
-       "         's': 12,\n",
-       "         't': 2,\n",
-       "         'u': 6,\n",
-       "         'v': 2,\n",
+       "         'q': 5,\n",
+       "         'r': 3,\n",
+       "         's': 3,\n",
+       "         'w': 2,\n",
+       "         'x': 4,\n",
        "         'y': 2,\n",
        "         'z': 1})"
       ]
      },
-     "execution_count": 83,
+     "execution_count": 56,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 84,
+   "execution_count": 57,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "scrolled": true
    },
    "outputs": [
     {
      "data": {
       "text/plain": [
-       "['bravos',\n",
-       " 'burlier',\n",
-       " 'decriminalisation',\n",
-       " 'differs',\n",
-       " 'duelled',\n",
-       " 'duplicating',\n",
-       " 'elaborates',\n",
-       " 'encirclement',\n",
-       " 'facsimiled',\n",
-       " 'festers',\n",
-       " 'flickering',\n",
-       " 'fusible',\n",
-       " 'interpolations',\n",
-       " 'involved',\n",
-       " 'lithographed',\n",
-       " 'oblongs',\n",
-       " 'overstates',\n",
-       " 'rallies',\n",
-       " 'rebated',\n",
-       " 'reneges',\n",
-       " 'saleswomen',\n",
-       " 'slobbering',\n",
-       " 'toiletries',\n",
-       " 'unabashed']"
+       "['ancestor',\n",
+       " 'baritone',\n",
+       " 'bemusing',\n",
+       " 'blonds',\n",
+       " 'conciseness',\n",
+       " 'consequent',\n",
+       " 'cuddle',\n",
+       " 'dashboards',\n",
+       " 'despairing',\n",
+       " 'dint',\n",
+       " 'employer',\n",
+       " 'freakish',\n",
+       " 'gall',\n",
+       " 'hopelessness',\n",
+       " 'impales',\n",
+       " 'infix',\n",
+       " 'inflow',\n",
+       " 'innumerable',\n",
+       " 'intentional',\n",
+       " 'jerkin',\n",
+       " 'justification',\n",
+       " 'leaving',\n",
+       " 'locoweeds',\n",
+       " 'monickers',\n",
+       " 'originality',\n",
+       " 'outings',\n",
+       " 'pendulous',\n",
+       " 'pithier',\n",
+       " 'randomness',\n",
+       " 'rectors',\n",
+       " 'redrew',\n",
+       " 'reformulated',\n",
+       " 'remoteness',\n",
+       " 'rethink',\n",
+       " 'scowls',\n",
+       " 'sequencers',\n",
+       " 'serf',\n",
+       " 'shook',\n",
+       " 'spottiest',\n",
+       " 'stood',\n",
+       " 'surtaxing',\n",
+       " 'wardrobes']"
       ]
      },
-     "execution_count": 84,
+     "execution_count": 57,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 85,
+   "execution_count": 59,
    "metadata": {
-    "collapsed": false
+    "collapsed": false,
+    "scrolled": true
    },
    "outputs": [
     {
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "*bravos Counter({'v': 1, 'b': 1, 'a': 1, 's': 1, 'o': 1, 'r': 1})\n",
-      "*burlier Counter({'r': 2, 'b': 1, 'u': 1, 'l': 1, 'i': 1, 'e': 1})\n",
-      "*decriminalisation Counter({'i': 4, 'n': 2, 'a': 2, 's': 1, 'l': 1, 'd': 1, 'e': 1, 'r': 1, 't': 1, 'm': 1, 'o': 1, 'c': 1})\n",
-      "*differs Counter({'f': 2, 's': 1, 'i': 1, 'd': 1, 'e': 1, 'r': 1})\n",
-      "*duelled Counter({'d': 2, 'e': 2, 'l': 2, 'u': 1})\n",
-      "*duplicating Counter({'i': 2, 'g': 1, 'n': 1, 'a': 1, 'l': 1, 'd': 1, 't': 1, 'p': 1, 'u': 1, 'c': 1})\n",
-      "*elaborates Counter({'a': 2, 'e': 2, 'b': 1, 's': 1, 'l': 1, 'o': 1, 'r': 1, 't': 1})\n",
-      "*encirclement Counter({'e': 3, 'n': 2, 'c': 2, 'm': 1, 't': 1, 'l': 1, 'i': 1, 'r': 1})\n",
-      "*facsimiled Counter({'i': 2, 's': 1, 'm': 1, 'a': 1, 'f': 1, 'l': 1, 'd': 1, 'e': 1, 'c': 1})\n",
-      "*festers Counter({'s': 2, 'e': 2, 'f': 1, 'r': 1, 't': 1})\n",
-      "*flickering Counter({'i': 2, 'g': 1, 'n': 1, 'f': 1, 'l': 1, 'e': 1, 'k': 1, 'r': 1, 'c': 1})\n",
-      "*fusible Counter({'s': 1, 'e': 1, 'f': 1, 'b': 1, 'i': 1, 'l': 1, 'u': 1})\n",
-      "*interpolations Counter({'n': 2, 'i': 2, 'o': 2, 't': 2, 's': 1, 'a': 1, 'l': 1, 'e': 1, 'p': 1, 'r': 1})\n",
-      "*involved Counter({'v': 2, 'n': 1, 'l': 1, 'i': 1, 'o': 1, 'e': 1, 'd': 1})\n",
-      "*lithographed Counter({'h': 2, 'g': 1, 'a': 1, 'r': 1, 'l': 1, 'i': 1, 'o': 1, 'e': 1, 'p': 1, 'd': 1, 't': 1})\n",
-      "*oblongs Counter({'o': 2, 'b': 1, 'g': 1, 'n': 1, 'l': 1, 's': 1})\n",
-      "*overstates Counter({'s': 2, 'e': 2, 't': 2, 'v': 1, 'a': 1, 'o': 1, 'r': 1})\n",
-      "*rallies Counter({'l': 2, 's': 1, 'a': 1, 'i': 1, 'e': 1, 'r': 1})\n",
-      "*rebated Counter({'e': 2, 'b': 1, 'a': 1, 'd': 1, 'r': 1, 't': 1})\n",
-      "*reneges Counter({'e': 3, 's': 1, 'g': 1, 'n': 1, 'r': 1})\n",
-      "saleswomen Counter({'s': 2, 'e': 2, 'm': 1, 'n': 1, 'a': 1, 'l': 1, 'o': 1, 'w': 1})\n",
-      "*slobbering Counter({'b': 2, 's': 1, 'g': 1, 'n': 1, 'i': 1, 'o': 1, 'e': 1, 'l': 1, 'r': 1})\n",
-      "*toiletries Counter({'i': 2, 'e': 2, 't': 2, 's': 1, 'l': 1, 'o': 1, 'r': 1})\n",
-      "*unabashed Counter({'a': 2, 'b': 1, 'n': 1, 'h': 1, 's': 1, 'd': 1, 'e': 1, 'u': 1})\n"
+      "ancestor Counter({'c': 1, 'a': 1, 's': 1, 't': 1, 'n': 1, 'r': 1, 'o': 1, 'e': 1})\n",
+      "baritone Counter({'a': 1, 'i': 1, 'r': 1, 't': 1, 'b': 1, 'n': 1, 'o': 1, 'e': 1})\n",
+      "bemusing Counter({'g': 1, 'u': 1, 'i': 1, 's': 1, 'n': 1, 'm': 1, 'b': 1, 'e': 1})\n",
+      "blonds Counter({'s': 1, 'd': 1, 'n': 1, 'b': 1, 'o': 1, 'l': 1})\n",
+      "conciseness Counter({'s': 3, 'c': 2, 'n': 2, 'e': 2, 'i': 1, 'o': 1})\n",
+      "consequent Counter({'n': 2, 'e': 2, 'u': 1, 'c': 1, 's': 1, 't': 1, 'q': 1, 'o': 1})\n",
+      "cuddle Counter({'d': 2, 'u': 1, 'e': 1, 'c': 1, 'l': 1})\n",
+      "dashboards Counter({'a': 2, 's': 2, 'd': 2, 'o': 1, 'r': 1, 'b': 1, 'h': 1})\n",
+      "*despairing Counter({'i': 2, 'g': 1, 'a': 1, 's': 1, 'r': 1, 'd': 1, 'n': 1, 'p': 1, 'e': 1})\n",
+      "dint Counter({'d': 1, 'n': 1, 'i': 1, 't': 1})\n",
+      "employer Counter({'e': 2, 'y': 1, 'r': 1, 'm': 1, 'p': 1, 'o': 1, 'l': 1})\n",
+      "freakish Counter({'k': 1, 'a': 1, 'i': 1, 'r': 1, 'f': 1, 's': 1, 'h': 1, 'e': 1})\n",
+      "*gall Counter({'l': 2, 'g': 1, 'a': 1})\n",
+      "hopelessness Counter({'s': 4, 'e': 3, 'h': 1, 'n': 1, 'p': 1, 'o': 1, 'l': 1})\n",
+      "*impales Counter({'s': 1, 'a': 1, 'i': 1, 'm': 1, 'e': 1, 'p': 1, 'l': 1})\n",
+      "infix Counter({'i': 2, 'f': 1, 'n': 1, 'x': 1})\n",
+      "inflow Counter({'i': 1, 'w': 1, 'f': 1, 'n': 1, 'o': 1, 'l': 1})\n",
+      "innumerable Counter({'n': 2, 'e': 2, 'u': 1, 'l': 1, 'a': 1, 'i': 1, 'r': 1, 'm': 1, 'b': 1})\n",
+      "intentional Counter({'n': 3, 'i': 2, 't': 2, 'a': 1, 'l': 1, 'o': 1, 'e': 1})\n",
+      "*jerkin Counter({'k': 1, 'i': 1, 'r': 1, 'n': 1, 'j': 1, 'e': 1})\n",
+      "justification Counter({'i': 3, 't': 2, 'u': 1, 'c': 1, 's': 1, 'n': 1, 'f': 1, 'j': 1, 'o': 1, 'a': 1})\n",
+      "leaving Counter({'g': 1, 'l': 1, 'a': 1, 'i': 1, 'n': 1, 'v': 1, 'e': 1})\n",
+      "locoweeds Counter({'o': 2, 'e': 2, 'c': 1, 's': 1, 'd': 1, 'w': 1, 'l': 1})\n",
+      "monickers Counter({'k': 1, 'c': 1, 's': 1, 'i': 1, 'r': 1, 'n': 1, 'm': 1, 'o': 1, 'e': 1})\n",
+      "originality Counter({'i': 3, 'g': 1, 'a': 1, 'r': 1, 't': 1, 'n': 1, 'y': 1, 'o': 1, 'l': 1})\n",
+      "outings Counter({'g': 1, 'u': 1, 's': 1, 'i': 1, 't': 1, 'n': 1, 'o': 1})\n",
+      "pendulous Counter({'u': 2, 's': 1, 'd': 1, 'n': 1, 'l': 1, 'p': 1, 'o': 1, 'e': 1})\n",
+      "pithier Counter({'i': 2, 'r': 1, 't': 1, 'p': 1, 'h': 1, 'e': 1})\n",
+      "randomness Counter({'s': 2, 'n': 2, 'a': 1, 'r': 1, 'd': 1, 'm': 1, 'o': 1, 'e': 1})\n",
+      "rectors Counter({'r': 2, 'c': 1, 's': 1, 't': 1, 'o': 1, 'e': 1})\n",
+      "redrew Counter({'e': 2, 'r': 2, 'd': 1, 'w': 1})\n",
+      "reformulated Counter({'r': 2, 'e': 2, 'u': 1, 'a': 1, 'f': 1, 't': 1, 'm': 1, 'l': 1, 'd': 1, 'o': 1})\n",
+      "remoteness Counter({'e': 3, 's': 2, 'r': 1, 't': 1, 'm': 1, 'n': 1, 'o': 1})\n",
+      "rethink Counter({'k': 1, 'i': 1, 'r': 1, 't': 1, 'n': 1, 'h': 1, 'e': 1})\n",
+      "scowls Counter({'s': 2, 'w': 1, 'c': 1, 'o': 1, 'l': 1})\n",
+      "sequencers Counter({'e': 3, 's': 2, 'u': 1, 'c': 1, 'r': 1, 'n': 1, 'q': 1})\n",
+      "serf Counter({'f': 1, 'r': 1, 's': 1, 'e': 1})\n",
+      "shook Counter({'o': 2, 'k': 1, 'h': 1, 's': 1})\n",
+      "spottiest Counter({'t': 3, 's': 2, 'i': 1, 'p': 1, 'o': 1, 'e': 1})\n",
+      "stood Counter({'o': 2, 'd': 1, 't': 1, 's': 1})\n",
+      "surtaxing Counter({'i': 1, 'u': 1, 'x': 1, 'g': 1, 'a': 1, 's': 1, 'r': 1, 't': 1, 'n': 1})\n",
+      "wardrobes Counter({'r': 2, 'a': 1, 's': 1, 'd': 1, 'w': 1, 'b': 1, 'o': 1, 'e': 1})\n"
      ]
     }
    ],
     "makeable_words = []\n",
     "for w in unused_words:\n",
     "    unused_word_count = collections.Counter(w)\n",
-    "    if all(l in unused_letter_count and unused_word_count[l] <= unused_letter_count[l] for l in unused_word_count):\n",
+    "    if all(unused_word_count[l] <= unused_letter_count[l] for l in unused_word_count):\n",
     "        makeable_words += [w]\n",
     "        print('*', end='')\n",
     "    print(w, unused_word_count)"
   },
   {
    "cell_type": "code",
-   "execution_count": 86,
+   "execution_count": 48,
    "metadata": {
     "collapsed": false
    },
     {
      "data": {
       "text/plain": [
-       "17"
+       "10"
       ]
      },
-     "execution_count": 86,
+     "execution_count": 48,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 90,
+   "execution_count": 49,
    "metadata": {
     "collapsed": false
    },
     {
      "data": {
       "text/plain": [
-       "'decriminalisation'"
+       "'despairing'"
       ]
      },
-     "execution_count": 90,
+     "execution_count": 49,
      "metadata": {},
      "output_type": "execute_result"
     }
   },
   {
    "cell_type": "code",
-   "execution_count": 103,
+   "execution_count": 74,
    "metadata": {
     "collapsed": false
    },
    "outputs": [],
    "source": [
-    "def do_wordsearch_tasks(fn):\n",
+    "def do_wordsearch_tasks(fn, show_anyway=False):\n",
     "    width, height, grid, words = read_wordsearch(fn)\n",
+    "    used_words = [w for w in words if present(grid, w)[0]]\n",
     "    unused_words = [w for w in words if not present(grid, w)[0]]\n",
     "    lwp = sorted([w for w in words if present(grid, w)[0]], key=len)[-1]\n",
+    "    lwps = [w for w in used_words if len(w) == len(lwp)]\n",
     "    lwa = sorted(unused_words, key=len)[-1]\n",
+    "    lwas = [w for w in unused_words if len(w) == len(lwa)]\n",
     "    g0 = empty_grid(width, height)\n",
     "    for w in words:\n",
     "        p, r, c, d = present(grid, w)\n",
     "    makeable_words = []\n",
     "    for w in unused_words:\n",
     "        unused_word_count = collections.Counter(w)\n",
-    "        if all(l in unused_letter_count and unused_word_count[l] <= unused_letter_count[l] for l in unused_word_count):\n",
+    "        if all(unused_word_count[l] <= unused_letter_count[l] for l in unused_word_count):\n",
     "            makeable_words += [w]\n",
     "    lwm = sorted(makeable_words, key=len)[-1]\n",
-    "    print('\\n{}'.format(fn))\n",
-    "    print('Longest word present: {}, {} letters'.format(lwp, len(lwp)))\n",
-    "    print('Longest word absent: {}, {} letters'.format(lwa, len(lwa)))\n",
-    "    print('{} unused letters'.format(len([c for c in cat(cat(l) for l in g0) if c == '.'])))\n",
-    "    print('Longest makeable word: {}, {}'.format(lwm, len(lwm)))"
+    "    lwms = [w for w in makeable_words if len(w) == len(lwm)]\n",
+    "    if show_anyway or len(set((len(lwp),len(lwa),len(lwm)))) == 3:\n",
+    "        print('\\n{}'.format(fn))\n",
+    "        print('{} words present'.format(len(words) - len(unused_words)))\n",
+    "        print('Longest word present: {}, {} letters ({})'.format(lwp, len(lwp), lwps))\n",
+    "        print('Longest word absent: {}, {} letters ({})'.format(lwa, len(lwa), lwas))\n",
+    "        print('{} unused letters'.format(len([c for c in cat(cat(l) for l in g0) if c == '.'])))\n",
+    "        print('Longest makeable word: {}, {} ({})'.format(lwm, len(lwm), lwms))"
    ]
   },
   {
    "cell_type": "code",
-   "execution_count": 112,
+   "execution_count": 75,
    "metadata": {
     "collapsed": false
    },
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "\n",
-      "wordsearch00.txt\n",
-      "Longest word present: yellowing, 9 letters\n",
-      "Longest word absent: sequined, 8 letters\n",
-      "147 unused letters\n",
-      "Longest makeable word: pettiest, 8\n",
-      "\n",
-      "wordsearch01.txt\n",
-      "Longest word present: soubriquets, 11 letters\n",
-      "Longest word absent: swallowing, 10 letters\n",
-      "124 unused letters\n",
-      "Longest makeable word: extradited, 10\n",
-      "\n",
-      "wordsearch02.txt\n",
-      "Longest word present: unattended, 10 letters\n",
-      "Longest word absent: runabouts, 9 letters\n",
-      "120 unused letters\n",
-      "Longest makeable word: runabouts, 9\n",
-      "\n",
-      "wordsearch03.txt\n",
-      "Longest word present: indemnifications, 16 letters\n",
-      "Longest word absent: propagandised, 13 letters\n",
-      "129 unused letters\n",
-      "Longest makeable word: propagandised, 13\n",
       "\n",
       "wordsearch04.txt\n",
-      "Longest word present: ostentatiously, 14 letters\n",
-      "Longest word absent: oleomargarine, 13 letters\n",
-      "128 unused letters\n",
-      "Longest makeable word: oleomargarine, 13\n",
-      "\n",
-      "wordsearch05.txt\n",
-      "Longest word present: straightjacketing, 17 letters\n",
-      "Longest word absent: grandiloquence, 14 letters\n",
-      "115 unused letters\n",
-      "Longest makeable word: multivitamins, 13\n",
-      "\n",
-      "wordsearch06.txt\n",
-      "Longest word present: inflorescence, 13 letters\n",
-      "Longest word absent: extinguished, 12 letters\n",
-      "159 unused letters\n",
-      "Longest makeable word: convocations, 12\n",
-      "\n",
-      "wordsearch07.txt\n",
-      "Longest word present: hypothesising, 13 letters\n",
-      "Longest word absent: nonrenewable, 12 letters\n",
-      "127 unused letters\n",
-      "Longest makeable word: nonrenewable, 12\n",
+      "58 words present\n",
+      "Longest word present: fortification, 13 letters (['fortification'])\n",
+      "Longest word absent: justification, 13 letters (['justification'])\n",
+      "57 unused letters\n",
+      "Longest makeable word: despairing, 10 (['despairing'])\n"
+     ]
+    }
+   ],
+   "source": [
+    "do_wordsearch_tasks('wordsearch04.txt', show_anyway=True)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 70,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
       "\n",
       "wordsearch08.txt\n",
-      "Longest word present: misrepresents, 13 letters\n",
-      "Longest word absent: predominates, 12 letters\n",
-      "125 unused letters\n",
-      "Longest makeable word: predominates, 12\n",
-      "\n",
-      "wordsearch09.txt\n",
-      "Longest word present: counterattacks, 14 letters\n",
-      "Longest word absent: overstepping, 12 letters\n",
-      "125 unused letters\n",
-      "Longest makeable word: constituents, 12\n",
-      "\n",
-      "wordsearch10.txt\n",
-      "Longest word present: cheerlessness, 13 letters\n",
-      "Longest word absent: gregariously, 12 letters\n",
-      "142 unused letters\n",
-      "Longest makeable word: gregariously, 12\n",
-      "\n",
-      "wordsearch11.txt\n",
-      "Longest word present: petitioners, 11 letters\n",
-      "Longest word absent: overdosing, 10 letters\n",
-      "137 unused letters\n",
-      "Longest makeable word: needlessly, 10\n",
-      "\n",
-      "wordsearch12.txt\n",
-      "Longest word present: propagandises, 13 letters\n",
-      "Longest word absent: fluorescent, 11 letters\n",
-      "130 unused letters\n",
-      "Longest makeable word: fluorescent, 11\n",
+      "62 words present\n",
+      "Longest word present: compassionately, 15 letters (['compassionately'])\n",
+      "Longest word absent: retrospectives, 14 letters (['retrospectives'])\n",
+      "65 unused letters\n",
+      "Longest makeable word: vacationing, 11 (['vacationing'])\n"
+     ]
+    }
+   ],
+   "source": [
+    "do_wordsearch_tasks('wordsearch08.txt')"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 76,
+   "metadata": {
+    "collapsed": false,
+    "scrolled": true
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
       "\n",
-      "wordsearch13.txt\n",
-      "Longest word present: preregisters, 12 letters\n",
-      "Longest word absent: undergrowth, 11 letters\n",
-      "113 unused letters\n",
-      "Longest makeable word: undergrowth, 11\n",
+      "wordsearch08.txt\n",
+      "62 words present\n",
+      "Longest word present: compassionately, 15 letters (['compassionately'])\n",
+      "Longest word absent: retrospectives, 14 letters (['retrospectives'])\n",
+      "65 unused letters\n",
+      "Longest makeable word: vacationing, 11 (['vacationing'])\n",
       "\n",
-      "wordsearch14.txt\n",
-      "Longest word present: dispossessing, 13 letters\n",
-      "Longest word absent: sweatshirts, 11 letters\n",
-      "116 unused letters\n",
-      "Longest makeable word: sweatshirts, 11\n",
+      "wordsearch17.txt\n",
+      "58 words present\n",
+      "Longest word present: complementing, 13 letters (['complementing'])\n",
+      "Longest word absent: upholstering, 12 letters (['domestically', 'upholstering'])\n",
+      "56 unused letters\n",
+      "Longest makeable word: plunderer, 9 (['plunderer'])\n",
       "\n",
-      "wordsearch15.txt\n",
-      "Longest word present: retrenching, 11 letters\n",
-      "Longest word absent: quadruples, 10 letters\n",
-      "119 unused letters\n",
-      "Longest makeable word: cavillings, 10\n",
+      "wordsearch32.txt\n",
+      "60 words present\n",
+      "Longest word present: reciprocating, 13 letters (['reciprocating'])\n",
+      "Longest word absent: parenthesise, 12 letters (['collectibles', 'frontrunners', 'parenthesise'])\n",
+      "65 unused letters\n",
+      "Longest makeable word: sultanas, 8 (['sultanas'])\n",
       "\n",
-      "wordsearch16.txt\n",
-      "Longest word present: cantankerously, 14 letters\n",
-      "Longest word absent: amorphousness, 13 letters\n",
-      "101 unused letters\n",
-      "Longest makeable word: amorphousness, 13\n",
+      "wordsearch52.txt\n",
+      "51 words present\n",
+      "Longest word present: prefabricated, 13 letters (['prefabricated'])\n",
+      "Longest word absent: catastrophic, 12 letters (['capitalistic', 'catastrophic'])\n",
+      "86 unused letters\n",
+      "Longest makeable word: unimpressed, 11 (['bloodstream', 'brainstorms', 'reassembles', 'rhapsodises', 'synergistic', 'unimpressed'])\n",
       "\n",
-      "wordsearch17.txt\n",
-      "Longest word present: appreciating, 12 letters\n",
-      "Longest word absent: unreasoning, 11 letters\n",
-      "114 unused letters\n",
-      "Longest makeable word: unreasoning, 11\n",
+      "wordsearch62.txt\n",
+      "58 words present\n",
+      "Longest word present: diametrically, 13 letters (['diametrically'])\n",
+      "Longest word absent: streetlights, 12 letters (['harmonically', 'skyrocketing', 'streetlights'])\n",
+      "59 unused letters\n",
+      "Longest makeable word: tabernacle, 10 (['falterings', 'tabernacle'])\n",
       "\n",
-      "wordsearch18.txt\n",
-      "Longest word present: rehabilitates, 13 letters\n",
-      "Longest word absent: interlarding, 12 letters\n",
-      "135 unused letters\n",
-      "Longest makeable word: interlarding, 12\n",
+      "wordsearch76.txt\n",
+      "60 words present\n",
+      "Longest word present: bloodthirstier, 14 letters (['bloodthirstier'])\n",
+      "Longest word absent: incriminating, 13 letters (['incriminating'])\n",
+      "59 unused letters\n",
+      "Longest makeable word: stubbornly, 10 (['leafletted', 'stubbornly'])\n",
       "\n",
-      "wordsearch19.txt\n",
-      "Longest word present: predetermines, 13 letters\n",
-      "Longest word absent: prosperously, 12 letters\n",
-      "127 unused letters\n",
-      "Longest makeable word: kneecapping, 11\n"
+      "wordsearch94.txt\n",
+      "59 words present\n",
+      "Longest word present: unforgettable, 13 letters (['unforgettable'])\n",
+      "Longest word absent: accommodated, 12 letters (['accommodated'])\n",
+      "69 unused letters\n",
+      "Longest makeable word: respectably, 11 (['predictions', 'respectably'])\n"
      ]
     }
    ],
     "        do_wordsearch_tasks(fn)"
    ]
   },
+  {
+   "cell_type": "code",
+   "execution_count": 38,
+   "metadata": {
+    "collapsed": false
+   },
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "absolved (True, 16, 2, <Direction.right: 2>)\n",
+      "adorable (True, 11, 4, <Direction.right: 2>)\n",
+      "aeon (True, 11, 4, <Direction.down: 4>)\n",
+      "alias (True, 15, 15, <Direction.left: 1>)\n",
+      "ancestor (False, 0, 0, <Direction.left: 1>)\n",
+      "baritone (False, 0, 0, <Direction.left: 1>)\n",
+      "bemusing (False, 0, 0, <Direction.left: 1>)\n",
+      "blonds (False, 0, 0, <Direction.left: 1>)\n",
+      "bran (True, 1, 9, <Direction.left: 1>)\n",
+      "calcite (True, 19, 9, <Direction.upright: 6>)\n",
+      "candor (True, 17, 12, <Direction.right: 2>)\n",
+      "conciseness (False, 0, 0, <Direction.left: 1>)\n",
+      "consequent (False, 0, 0, <Direction.left: 1>)\n",
+      "cuddle (False, 0, 0, <Direction.left: 1>)\n",
+      "damming (True, 17, 2, <Direction.right: 2>)\n",
+      "dashboards (False, 0, 0, <Direction.left: 1>)\n",
+      "despairing (False, 0, 0, <Direction.left: 1>)\n",
+      "dint (False, 0, 0, <Direction.left: 1>)\n",
+      "dullard (True, 8, 2, <Direction.down: 4>)\n",
+      "dynasty (True, 3, 4, <Direction.downright: 8>)\n",
+      "employer (False, 0, 0, <Direction.left: 1>)\n",
+      "exhorts (True, 0, 8, <Direction.left: 1>)\n",
+      "feted (True, 5, 10, <Direction.right: 2>)\n",
+      "fill (True, 9, 14, <Direction.upleft: 5>)\n",
+      "flattens (True, 10, 10, <Direction.upleft: 5>)\n",
+      "foghorn (True, 10, 11, <Direction.downright: 8>)\n",
+      "fortification (True, 19, 16, <Direction.left: 1>)\n",
+      "freakish (False, 0, 0, <Direction.left: 1>)\n",
+      "frolics (True, 16, 16, <Direction.up: 3>)\n",
+      "gall (False, 0, 0, <Direction.left: 1>)\n",
+      "gees (True, 17, 0, <Direction.upright: 6>)\n",
+      "genies (True, 5, 7, <Direction.upleft: 5>)\n",
+      "gets (True, 6, 4, <Direction.upleft: 5>)\n",
+      "hastening (True, 14, 13, <Direction.left: 1>)\n",
+      "hits (True, 2, 0, <Direction.down: 4>)\n",
+      "hopelessness (False, 0, 0, <Direction.left: 1>)\n",
+      "hurlers (True, 18, 0, <Direction.right: 2>)\n",
+      "impales (False, 0, 0, <Direction.left: 1>)\n",
+      "infix (False, 0, 0, <Direction.left: 1>)\n",
+      "inflow (False, 0, 0, <Direction.left: 1>)\n",
+      "innumerable (False, 0, 0, <Direction.left: 1>)\n",
+      "intentional (False, 0, 0, <Direction.left: 1>)\n",
+      "jerkin (False, 0, 0, <Direction.left: 1>)\n",
+      "justification (False, 0, 0, <Direction.left: 1>)\n",
+      "kitty (True, 8, 15, <Direction.upleft: 5>)\n",
+      "knuckles (True, 17, 19, <Direction.up: 3>)\n",
+      "leaving (False, 0, 0, <Direction.left: 1>)\n",
+      "like (True, 3, 11, <Direction.left: 1>)\n",
+      "limitation (True, 8, 3, <Direction.right: 2>)\n",
+      "locoweeds (False, 0, 0, <Direction.left: 1>)\n",
+      "loot (True, 3, 19, <Direction.up: 3>)\n",
+      "lucking (True, 7, 10, <Direction.upleft: 5>)\n",
+      "lumps (True, 0, 17, <Direction.down: 4>)\n",
+      "mercerising (True, 15, 17, <Direction.up: 3>)\n",
+      "monickers (False, 0, 0, <Direction.left: 1>)\n",
+      "motionless (True, 13, 1, <Direction.up: 3>)\n",
+      "naturally (True, 9, 16, <Direction.up: 3>)\n",
+      "nighest (True, 15, 4, <Direction.right: 2>)\n",
+      "notion (True, 17, 18, <Direction.up: 3>)\n",
+      "ogled (True, 1, 18, <Direction.down: 4>)\n",
+      "originality (False, 0, 0, <Direction.left: 1>)\n",
+      "outings (False, 0, 0, <Direction.left: 1>)\n",
+      "pendulous (False, 0, 0, <Direction.left: 1>)\n",
+      "piled (True, 1, 10, <Direction.right: 2>)\n",
+      "pins (True, 7, 4, <Direction.upleft: 5>)\n",
+      "pithier (False, 0, 0, <Direction.left: 1>)\n",
+      "prep (True, 10, 4, <Direction.right: 2>)\n",
+      "randomness (False, 0, 0, <Direction.left: 1>)\n",
+      "rectors (False, 0, 0, <Direction.left: 1>)\n",
+      "redrew (False, 0, 0, <Direction.left: 1>)\n",
+      "reformulated (False, 0, 0, <Direction.left: 1>)\n",
+      "remoteness (False, 0, 0, <Direction.left: 1>)\n",
+      "retaking (True, 6, 0, <Direction.down: 4>)\n",
+      "rethink (False, 0, 0, <Direction.left: 1>)\n",
+      "rope (True, 9, 4, <Direction.right: 2>)\n",
+      "rubier (True, 0, 4, <Direction.downright: 8>)\n",
+      "sailors (True, 7, 15, <Direction.up: 3>)\n",
+      "scowls (False, 0, 0, <Direction.left: 1>)\n",
+      "scum (True, 16, 11, <Direction.right: 2>)\n",
+      "sepals (True, 6, 10, <Direction.upright: 6>)\n",
+      "sequencers (False, 0, 0, <Direction.left: 1>)\n",
+      "serf (False, 0, 0, <Direction.left: 1>)\n",
+      "shoaled (True, 11, 18, <Direction.up: 3>)\n",
+      "shook (False, 0, 0, <Direction.left: 1>)\n",
+      "sonic (True, 18, 18, <Direction.left: 1>)\n",
+      "spottiest (False, 0, 0, <Direction.left: 1>)\n",
+      "stag (True, 7, 8, <Direction.left: 1>)\n",
+      "stood (False, 0, 0, <Direction.left: 1>)\n",
+      "stratum (True, 2, 13, <Direction.left: 1>)\n",
+      "strong (True, 4, 19, <Direction.down: 4>)\n",
+      "studying (True, 0, 16, <Direction.left: 1>)\n",
+      "surtaxing (False, 0, 0, <Direction.left: 1>)\n",
+      "tailing (True, 13, 6, <Direction.right: 2>)\n",
+      "tears (True, 13, 3, <Direction.up: 3>)\n",
+      "teazles (True, 4, 10, <Direction.downright: 8>)\n",
+      "vans (True, 18, 8, <Direction.upright: 6>)\n",
+      "wardrobes (False, 0, 0, <Direction.left: 1>)\n",
+      "wooded (True, 12, 5, <Direction.right: 2>)\n",
+      "worsts (True, 1, 0, <Direction.downright: 8>)\n",
+      "zings (True, 10, 14, <Direction.upleft: 5>)\n"
+     ]
+    }
+   ],
+   "source": [
+    "width, height, grid, words = read_wordsearch('wordsearch04.txt')\n",
+    "for w in words:\n",
+    "    print(w, present(grid, w))"
+   ]
+  },
   {
    "cell_type": "code",
    "execution_count": null,