{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import string\n", "import re\n", "import random\n", "import collections\n", "import copy\n", "\n", "from enum import Enum\n", "Direction = Enum('Direction', 'left right up down upleft upright downleft downright')\n", " \n", "delta = {Direction.left: (0, -1),Direction.right: (0, 1), \n", " Direction.up: (-1, 0), Direction.down: (1, 0), \n", " Direction.upleft: (-1, -1), Direction.upright: (-1, 1), \n", " Direction.downleft: (1, -1), Direction.downright: (1, 1)}\n", "\n", "cat = ''.join\n", "wcat = ' '.join\n", "lcat = '\\n'.join" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# all_words = [w.strip() for w in open('/usr/share/dict/british-english').readlines()\n", "# if all(c in string.ascii_lowercase for c in w.strip())]\n", "# words = [w for w in all_words\n", "# if not any(w in w2 for w2 in all_words if w != w2)]\n", "# open('wordsearch-words', 'w').write(lcat(words))" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# ws_words = [w.strip() for w in open('wordsearch-words').readlines()\n", "# if all(c in string.ascii_lowercase for c in w.strip())]\n", "# ws_words[:10]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": true }, "outputs": [], "source": [ "ws_words = [w.strip() for w in open('/usr/share/dict/british-english').readlines()\n", " if all(c in string.ascii_lowercase for c in w.strip())]" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def empty_grid(w, h):\n", " return [['.' for c in range(w)] for r in range(h)]" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def show_grid(grid):\n", " return lcat(cat(r) for r in grid)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "..........\n", "..........\n", "..........\n", "..........\n", "..........\n", "..........\n", "..........\n", "..........\n", "..........\n", "..........\n" ] } ], "source": [ "grid = empty_grid(10, 10)\n", "print(show_grid(grid))" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def indices(grid, r, c, l, d):\n", " dr, dc = delta[d]\n", " w = len(grid[0])\n", " h = len(grid)\n", " inds = [(r + i * dr, c + i * dc) for i in range(l)]\n", " return [(i, j) for i, j in inds\n", " if i >= 0\n", " if j >= 0\n", " if i < h\n", " if j < w]" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def gslice(grid, r, c, l, d):\n", " return [grid[i][j] for i, j in indices(grid, r, c, l, d)]" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def set_grid(grid, r, c, d, word):\n", " for (i, j), l in zip(indices(grid, r, c, len(word), d), word):\n", " grid[i][j] = l\n", " return grid" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "..........\n", "..........\n", "...t......\n", "....e.....\n", ".....s....\n", "......t...\n", ".......w..\n", "........o.\n", ".........r\n", "..........\n" ] } ], "source": [ "set_grid(grid, 2, 3, Direction.downright, 'testword')\n", "print(show_grid(grid))" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'..e.....'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(gslice(grid, 3, 2, 15, Direction.right))" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<_sre.SRE_Match object; span=(0, 4), match='keen'>" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "re.match(cat(gslice(grid, 3, 2, 4, Direction.right)), 'keen')" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<_sre.SRE_Match object; span=(0, 3), match='kee'>" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "re.match(cat(gslice(grid, 3, 2, 3, Direction.right)), 'keen')" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "re.fullmatch(cat(gslice(grid, 3, 2, 3, Direction.right)), 'keen')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": true }, "outputs": [], "source": [ "re.match(cat(gslice(grid, 3, 2, 4, Direction.right)), 'kine')" ] }, { "cell_type": "code", "execution_count": 17, "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": 18, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "<_sre.SRE_Match object; span=(0, 4), match='keen'>" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "could_add(grid, 3, 2, Direction.right, 'keen')" ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [], "source": [ "could_add(grid, 3, 2, Direction.right, 'kine')" ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 20, "metadata": {}, "output_type": "execute_result" } ], "source": [ "random.choice(list(Direction))" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def fill_grid(grid, words, word_count, max_attempts=10000):\n", " attempts = 0\n", " added_words = []\n", " w = len(grid[0])\n", " h = len(grid)\n", " while len(added_words) < word_count and attempts < max_attempts:\n", " attempts += 1\n", " r = random.randrange(w)\n", " c = random.randrange(h)\n", " word = random.choice(words)\n", " d = random.choice(list(Direction))\n", " if len(word) >=4 and not any(word in w2 for w2 in added_words) and could_add(grid, r, c, d, word):\n", " set_grid(grid, r, c, d, word)\n", " added_words += [word]\n", " attempts = 0\n", " return grid, added_words" ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "40" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "g = empty_grid(20, 20)\n", "g, ws = fill_grid(g, ws_words, 40)\n", "len(ws)" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "..pouchexecrate.....\n", ".hazardous....t.wive\n", "...sniradnam.aselcnu\n", "s.weeklies.rnb......\n", "e..lamenessse.o.....\n", "i.tsallab..s.a.i....\n", "tslim.......f.c.l...\n", "iwheelbase...f.tges.\n", "ed....llabhgihinirr.\n", "dw.limbs..nj.bitev.s\n", "te.wiltediu.ructs.e.\n", "elsombretv.oqes..a..\n", "ll..e..te.iela....m.\n", "ie.a..un.lheleiretoc\n", "ord..bi.scsp...kiths\n", "ts.malcentilitren...\n", "..i.e.sexetrov.stolb\n", ".r.s...ruof....htrof\n", "bgnihsirevopmi.....c\n", "....graciousness....\n", "40 words added\n", "lameness impoverishing plasters wilted toilet forth coterie hazardous abutting chequing weeklies sombre execrate mastiffs boilers uncles centilitre mandarins wheelbase graciousness vortexes dwellers ballast limbs four tans highball wive broils beads mils reactive select deities shtik juveniles blots pouch brim coon\n" ] } ], "source": [ "print(show_grid(g))\n", "print(len(ws), 'words added')\n", "print(wcat(ws))" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def present(grid, word):\n", " w = len(grid[0])\n", " h = len(grid)\n", " for r in range(h):\n", " for c in range(w):\n", " for d in Direction:\n", " if cat(gslice(grid, r, c, len(word), d)) == word:\n", " return True, r, c, d\n", " return False, 0, 0, list(Direction)[0]" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "lameness (True, 4, 3, )\n", "impoverishing (True, 18, 13, )\n", "plasters (True, 14, 11, )\n", "wilted (True, 10, 3, )\n", "toilet (True, 15, 0, )\n", "forth (True, 17, 19, )\n", "coterie (True, 13, 19, )\n", "hazardous (True, 1, 1, )\n", "abutting (True, 15, 4, )\n", "chequing (True, 14, 9, )\n", "weeklies (True, 3, 2, )\n", "sombre (True, 11, 2, )\n", "execrate (True, 0, 7, )\n", "mastiffs (True, 12, 18, )\n", "boilers (True, 3, 13, )\n", "uncles (True, 2, 19, )\n", "centilitre (True, 15, 6, )\n", "mandarins (True, 2, 11, )\n", "wheelbase (True, 7, 1, )\n", "graciousness (True, 19, 4, )\n", "vortexes (True, 16, 13, )\n", "dwellers (True, 8, 1, )\n", "ballast (True, 5, 8, )\n", "limbs (True, 9, 3, )\n", "four (True, 17, 10, )\n", "tans (True, 1, 14, )\n", "highball (True, 8, 13, )\n", "wive (True, 1, 16, )\n", "broils (True, 9, 13, )\n", "beads (True, 11, 5, )\n", "mils (True, 6, 4, )\n", "reactive (True, 3, 11, )\n", "select (True, 14, 10, )\n", "deities (True, 9, 0, )\n", "shtik (True, 14, 19, )\n", "juveniles (True, 9, 11, )\n", "blots (True, 16, 19, )\n", "pouch (True, 0, 2, )\n", "brim (True, 18, 0, )\n", "coon (True, 18, 19, )\n" ] } ], "source": [ "for w in ws:\n", " print(w, present(g, w))" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def interesting(grid, words, words_limit=40, direction_slack=1):\n", " dirs = set(present(grid, w)[3] for w in words)\n", " return len(words) > words_limit and len(dirs) + direction_slack >= len(delta)" ] }, { "cell_type": "code", "execution_count": 48, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 48, "metadata": {}, "output_type": "execute_result" } ], "source": [ "interesting(g, ws)" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def interesting_grid(width=20, height=20, words_limit=40, direction_slack=1):\n", " boring = True\n", " while boring:\n", " grid = empty_grid(width, height)\n", " grid, words = fill_grid(grid, ws_words, 80)\n", " boring = not interesting(grid, words, words_limit=words_limit, direction_slack=direction_slack)\n", " return grid, words" ] }, { "cell_type": "code", "execution_count": 52, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dexawwt....ybossm..t\n", "snaprhlukulele..o.er\n", "...erioteb.hrevordla\n", "..sivc..pr.tdekcahkp\n", "atve..h.oiselapcy.cd\n", "nesrehpargohtill.pue\n", "n.leaveyis.smuguhhrt\n", "eyhsifnt.r...aeesetc\n", "xverbseebasedlritl.a\n", ".r..k.wie..mdonaiaeg\n", "..ac.nsof.admeeulsoo\n", "g.opo.cmanaotpqiinmp\n", "nc.us.a.lpnteaerdkiu\n", "ionjoys.leirinioicns\n", "wnkcent.skeracllkase\n", "oab..erusopxeao.antt\n", "dureifidimuhed.nskea\n", "aga...capitols..scrl\n", "h.v.sandblaster..i.i\n", "s.e..sdratoelhitsn.d\n", "61 words added; 8 directions\n", "newscast kittenish cocks lithographers truckle leotards they exposure dehumidifier sandblaster alien paddle shadowing gondola wrest joys minster pales chairs fishy capitols based gums pheromones saki moiety waxed guano thriven dilate moray icons adman ukulele hacked rope rise clue acted nicknack spar verbs boss annex neck repeater befalls drover leave pans brave brigs opus live noun tail riot care hits quilt part\n" ] } ], "source": [ "g, ws = interesting_grid()\n", "print(show_grid(g))\n", "print(len(ws), 'words added; ', len(set(present(g, w)[3] for w in ws)), 'directions')\n", "print(wcat(ws))" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def datafile(name, sep='\\t'):\n", " \"\"\"Read key,value pairs from file.\n", " \"\"\"\n", " with open(name) as f:\n", " for line in f:\n", " splits = line.split(sep)\n", " yield [splits[0], int(splits[1])]" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def normalise(frequencies):\n", " \"\"\"Scale a set of frequencies so they sum to one\n", " \n", " >>> sorted(normalise({1: 1, 2: 0}).items())\n", " [(1, 1.0), (2, 0.0)]\n", " >>> sorted(normalise({1: 1, 2: 1}).items())\n", " [(1, 0.5), (2, 0.5)]\n", " >>> sorted(normalise({1: 1, 2: 1, 3: 1}).items()) # doctest: +ELLIPSIS\n", " [(1, 0.333...), (2, 0.333...), (3, 0.333...)]\n", " >>> sorted(normalise({1: 1, 2: 2, 3: 1}).items())\n", " [(1, 0.25), (2, 0.5), (3, 0.25)]\n", " \"\"\"\n", " length = sum(f for f in frequencies.values())\n", " return collections.defaultdict(int, ((k, v / length) \n", " for (k, v) in frequencies.items()))\n" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [], "source": [ "english_counts = collections.Counter(dict(datafile('count_1l.txt')))\n", "normalised_english_counts = normalise(english_counts)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [], "source": [ "wordsearch_counts = collections.Counter(cat(ws_words))\n", "normalised_wordsearch_counts = normalise(wordsearch_counts)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [], "source": [ "normalised_wordsearch_counts = normalise(collections.Counter(normalised_wordsearch_counts) + collections.Counter({l: 0.05 for l in string.ascii_lowercase}))" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def weighted_choice(d):\n", " \"\"\"Generate random item from a dictionary of item counts\n", " \"\"\"\n", " target = random.uniform(0, sum(d.values()))\n", " cuml = 0.0\n", " for (l, p) in d.items():\n", " cuml += p\n", " if cuml > target:\n", " return l\n", " return None\n", "\n", "def random_english_letter():\n", " \"\"\"Generate a random letter based on English letter counts\n", " \"\"\"\n", " return weighted_choice(normalised_english_counts)\n", "\n", "def random_wordsearch_letter():\n", " \"\"\"Generate a random letter based on wordsearch letter counts\n", " \"\"\"\n", " return weighted_choice(normalised_wordsearch_counts)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'aaaaaabbccddeeeeeeeeeeeffggghhhhhhiiiiiiiiillllmmnnnnnnnooooooooooppppqrrrrrrrssstttttttttuuwyyyyyyz'" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(sorted(random_english_letter() for i in range(100)))" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'aaaaaaaabbbccccddeeeeeeeeggghhhiiiiiiiijjkkllllnnnnoooooooooopppqqrrrrrssssssttttttuuuuvvwxxxxxyzzzz'" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cat(sorted(random_wordsearch_letter() for i in range(100)))" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'x'" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "random_wordsearch_letter()" ] }, { "cell_type": "code", "execution_count": 39, "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": 53, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dexawwtmxepybossmezt\n", "snaprhlukulelefaoder\n", "ijreriotebahrevordla\n", "jrsivcciprstdekcahkp\n", "atvecshkoiselapcydcd\n", "nesrehpargohtilljpue\n", "nuleaveyisasmuguhhrt\n", "eyhsifntzrmnsaeesetc\n", "xverbseebasedlritlla\n", "prcckzwiefamdonaiaeg\n", "osacqnsofgadmeeulsoo\n", "gdoporcmanaotpqiinmp\n", "ncmusbaslpnteaerdkiu\n", "ionjoyswleirinioicns\n", "wnkcentcskeracllkase\n", "oabsuerusopxeaodantt\n", "dureifidimuhedgnskea\n", "agagvccapitolsgyscrl\n", "hkvgsandblasterdhihi\n", "syenesdratoelhitsnod\n" ] } ], "source": [ "padded = pad_grid(g)\n", "print(show_grid(padded))" ] }, { "cell_type": "code", "execution_count": 54, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "dexawwt....ybossm..t\n", "snaprhlukulele..o.er\n", "...erioteb.hrevordla\n", "..sivc..pr.tdekcahkp\n", "atve..h.oiselapcy.cd\n", "nesrehpargohtill.pue\n", "n.leaveyis.smuguhhrt\n", "eyhsifnt.r...aeesetc\n", "xverbseebasedlritl.a\n", ".r..k.wie..mdonaiaeg\n", "..ac.nsof.admeeulsoo\n", "g.opo.cmanaotpqiinmp\n", "nc.us.a.lpnteaerdkiu\n", "ionjoys.leirinioicns\n", "wnkcent.skeracllkase\n", "oab..erusopxeao.antt\n", "dureifidimuhed.nskea\n", "aga...capitols..scrl\n", "h.v.sandblaster..i.i\n", "s.e..sdratoelhitsn.d\n" ] } ], "source": [ "print(show_grid(g))" ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "newscast (True, 7, 6, )\n", "kittenish (True, 14, 9, )\n", "cocks (True, 12, 1, )\n", "lithographers (True, 5, 14, )\n", "truckle (True, 7, 18, )\n", "leotards (True, 19, 12, )\n", "they (True, 3, 11, )\n", "exposure (True, 15, 12, )\n", "dehumidifier (True, 16, 13, )\n", "sandblaster (True, 18, 4, )\n", "alien (True, 9, 17, )\n", "paddle (True, 12, 9, )\n", "shadowing (True, 19, 0, )\n", "gondola (True, 9, 19, )\n", "wrest (True, 0, 5, )\n", "joys (True, 13, 3, )\n", "minster (True, 11, 18, )\n", "pales (True, 4, 14, )\n", "chairs (True, 3, 5, )\n", "fishy (True, 7, 5, )\n", "capitols (True, 17, 6, )\n", "based (True, 8, 8, )\n", "gums (True, 6, 14, )\n", "pheromones (True, 5, 17, )\n", "saki (True, 16, 16, )\n", "moiety (True, 11, 7, )\n", "waxed (True, 0, 4, )\n", "guano (True, 17, 1, )\n", "thriven (True, 0, 6, )\n", "dilate (True, 19, 19, )\n", "moray (True, 0, 16, )\n", "icons (True, 13, 12, )\n", "adman (True, 7, 13, )\n", "ukulele (True, 1, 7, )\n", "hacked (True, 3, 17, )\n", "rope (True, 5, 8, )\n", "rise (True, 12, 15, )\n", "clue (True, 4, 15, )\n", "acted (True, 8, 19, )\n", "nicknack (True, 19, 17, )\n", "spar (True, 12, 4, )\n", "verbs (True, 8, 1, )\n", "boss (True, 0, 12, )\n", "annex (True, 4, 0, )\n", "neck (True, 14, 5, )\n", "repeater (True, 13, 11, )\n", "befalls (True, 8, 8, )\n", "drover (True, 2, 17, )\n", "leave (True, 6, 2, )\n", "pans (True, 1, 3, )\n", "brave (True, 15, 2, )\n", "brigs (True, 2, 9, )\n", "opus (True, 10, 19, )\n", "live (True, 1, 6, )\n", "noun (True, 10, 5, )\n", "tail (True, 11, 12, )\n", "riot (True, 2, 4, )\n", "care (True, 14, 13, )\n", "hits (True, 19, 13, )\n", "quilt (True, 11, 14, )\n", "part (True, 3, 19, )\n" ] } ], "source": [ "for w in ws:\n", " print(w, present(padded, w))" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [], "source": [ "def decoys(grid, words, all_words, limit=100):\n", " decoy_words = []\n", " dlen_limit = max(len(w) for w in words)\n", " while len(words) + len(decoy_words) < limit:\n", " d = random.choice(all_words)\n", " if d not in words and len(d) >= 4 and len(d) <= dlen_limit and not present(grid, d)[0]:\n", " decoy_words += [d]\n", " return decoy_words" ] }, { "cell_type": "code", "execution_count": 44, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['friendship',\n", " 'stepping',\n", " 'featheriest',\n", " 'thriftily',\n", " 'mutilation',\n", " 'nook',\n", " 'clewing',\n", " 'meditated',\n", " 'gooier',\n", " 'cripples',\n", " 'ponderously',\n", " 'roundelay',\n", " 'curtailed',\n", " 'redeemed',\n", " 'perimeters',\n", " 'harelips',\n", " 'overcompensating',\n", " 'rejoicings',\n", " 'adobe',\n", " 'decreasing',\n", " 'interstices',\n", " 'curd',\n", " 'orientate',\n", " 'blueberries',\n", " 'juniors',\n", " 'broadloom',\n", " 'debarring',\n", " 'chandeliers',\n", " 'segues',\n", " 'army',\n", " 'snuck',\n", " 'pugilistic',\n", " 'snugs',\n", " 'dexterity',\n", " 'dallies',\n", " 'curving',\n", " 'newsletter',\n", " 'torn',\n", " 'beaching',\n", " 'limit',\n", " 'blackguards',\n", " 'breezier',\n", " 'reoccur',\n", " 'cabins']" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds = decoys(padded, ws, ws_words)\n", "ds" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "opted (True, 5, 7, )\n", "haywire (True, 8, 9, )\n", "busting (True, 4, 17, )\n", "succinct (True, 7, 17, )\n", "institute (True, 16, 18, )\n", "illicit (True, 13, 14, )\n", "hypersensitivity (True, 16, 15, )\n", "placement (True, 3, 11, )\n", "bathrobe (True, 0, 5, )\n", "inured (True, 4, 0, )\n", "caveats (True, 3, 8, )\n", "revisiting (True, 2, 11, )\n", "pulp (True, 15, 11, )\n", "teacup (True, 7, 16, )\n", "threading (True, 18, 6, )\n", "queered (True, 5, 13, )\n", "parking (True, 6, 9, )\n", "advent (True, 1, 11, )\n", "chasuble (True, 19, 19, )\n", "mosey (True, 7, 5, )\n", "highboys (True, 19, 4, )\n", "recharging (True, 18, 19, )\n", "flue (True, 12, 2, )\n", "plywood (True, 3, 18, )\n", "gluing (True, 12, 12, )\n", "worrier (True, 1, 12, )\n", "karma (True, 17, 9, )\n", "peepers (True, 8, 7, )\n", "vulnerable (True, 17, 10, )\n", "boycott (True, 15, 1, )\n", "rummy (True, 5, 4, )\n", "tonic (True, 8, 13, )\n", "children (True, 15, 0, )\n", "reales (True, 6, 1, )\n", "rectal (True, 7, 15, )\n", "sledded (True, 14, 16, )\n", "collocates (True, 14, 5, )\n", "edict (True, 17, 4, )\n", "captor (True, 14, 5, )\n", "amulet (True, 9, 4, )\n", "slipper (True, 2, 13, )\n", "foot (True, 0, 0, )\n", "chef (True, 14, 4, )\n", "goods (True, 6, 15, )\n", "salter (True, 1, 5, )\n", "crows (True, 18, 0, )\n", "paeans (True, 12, 14, )\n", "fences (True, 0, 18, )\n", "iron (True, 5, 9, )\n", "liras (True, 0, 19, )\n", "stages (True, 19, 16, )\n", "defer (True, 14, 2, )\n", "racy (True, 5, 4, )\n", "gaps (True, 7, 11, )\n", "aspen (True, 12, 10, )\n", "rams (True, 6, 0, )\n", "friendship (False, 0, 0, )\n", "stepping (False, 0, 0, )\n", "featheriest (False, 0, 0, )\n", "thriftily (False, 0, 0, )\n", "mutilation (False, 0, 0, )\n", "nook (False, 0, 0, )\n", "clewing (False, 0, 0, )\n", "meditated (False, 0, 0, )\n", "gooier (False, 0, 0, )\n", "cripples (False, 0, 0, )\n", "ponderously (False, 0, 0, )\n", "roundelay (False, 0, 0, )\n", "curtailed (False, 0, 0, )\n", "redeemed (False, 0, 0, )\n", "perimeters (False, 0, 0, )\n", "harelips (False, 0, 0, )\n", "overcompensating (False, 0, 0, )\n", "rejoicings (False, 0, 0, )\n", "adobe (False, 0, 0, )\n", "decreasing (False, 0, 0, )\n", "interstices (False, 0, 0, )\n", "curd (False, 0, 0, )\n", "orientate (False, 0, 0, )\n", "blueberries (False, 0, 0, )\n", "juniors (False, 0, 0, )\n", "broadloom (False, 0, 0, )\n", "debarring (False, 0, 0, )\n", "chandeliers (False, 0, 0, )\n", "segues (False, 0, 0, )\n", "army (False, 0, 0, )\n", "snuck (False, 0, 0, )\n", "pugilistic (False, 0, 0, )\n", "snugs (False, 0, 0, )\n", "dexterity (False, 0, 0, )\n", "dallies (False, 0, 0, )\n", "curving (False, 0, 0, )\n", "newsletter (False, 0, 0, )\n", "torn (False, 0, 0, )\n", "beaching (False, 0, 0, )\n", "limit (False, 0, 0, )\n", "blackguards (False, 0, 0, )\n", "breezier (False, 0, 0, )\n", "reoccur (False, 0, 0, )\n", "cabins (False, 0, 0, )\n" ] } ], "source": [ "for w in ws + ds:\n", " print(w, present(padded, w))" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "s.esevresed...dwhims\n", "e.tbk..vapourse.bn.d\n", "h.ificembracesnslo.e\n", "ctr.egukiwic..ddui.r\n", "inor.dwh.rips.rrftsa\n", "reue.eeisrar.tiefiyl\n", "mmli.mgrg.muarth.slc\n", "ieft.un.a.bnbuemdole\n", "nn.nesimrliertseepad\n", "ei.imeloeccdeh.epob.\n", "dfsaprlrio.saf.smri.\n", "cnpdt.ofrn.usu..ap.h\n", "oom.ispeccgntlpew.sa\n", "tcu.e.l.lu.eda.vsgin\n", "e.bdsb.oarrmneloplsg\n", "r.olaetrleromrkr.isa\n", "ibatnhd.nlpoaeic.bir\n", "eesiee.i.luepno.o.e.\n", "snt.d.o.y.pcte.p.mr.\n", "u....jtoquesylduol..\n", "sfesevresedpzcdwhims\n", "eotbkvgvapoursehbnyd\n", "hiificembracesnslone\n", "ctrnegukiwicurdduivr\n", "inorydwhrripscrrftsa\n", "reueleeisrarvtiefiyl\n", "mmlinmgrgzmuarthgslc\n", "ieftuunyanbnbuemdole\n", "nncnesimrliertseepad\n", "eirimeloeccdehzepobm\n", "dfsaprlrioisafesmriq\n", "cnpdtsofrnausuodapxh\n", "oomlispeccgntlpewasa\n", "tcuaehlzluledakvsgin\n", "eibdsbeoarrmneloplsg\n", "rbolaetrleromrkrnisa\n", "ibatnhdtnlpoaeicibir\n", "eesieerimluepnoholey\n", "sntadvoaycpctespsmro\n", "uamapjtoquesylduoldp\n", "56 words added; 8 directions\n", "Present: abreast bigwig bluff bodes bumps clothe concur confinement coteries crier cull daintier declared dendrites denim deserves embraces empties federal fluorite from glib guarded hangar herds iambic joiner kiwi loudly menus mocked panoply pearl poem polling prints proposition pruned resume rices riches rips roped rove seal seem shucks sissier swamped syllabi tine toque truthful unstabler vapours whims\n", "Decoys: abrasions adapters aimlessness alkali awakens blowing burnouses burped cattily coal commences confusion contrivance crudest curies depravity distribute diva emigrate emulsion giveaway hangman house lifeboats maze middy mines mystified obtain organic parsons postulate prefixes pretenders razors scone sloes spuds straight subtleties systematise turncoats unpacked waivers\n" ] } ], "source": [ "g, ws = interesting_grid()\n", "p = pad_grid(g)\n", "ds = decoys(p, ws, ws_words)\n", "print(show_grid(g))\n", "print(show_grid(p))\n", "print(len(ws), 'words added; ', len(set(present(g, w)[3] for w in ws)), 'directions')\n", "print('Present:', wcat(sorted(ws)))\n", "print('Decoys:', wcat(sorted(ds)))" ] }, { "cell_type": "code", "execution_count": 63, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "...p.mown.\n", ".sdse..ee.\n", ".e.elad.cr\n", "pi.dtir.ah\n", "rzsiwovspu\n", "oawh.kieab\n", "brow.c.rda\n", "ecnotops.r\n", "d.kc.d...b\n", ".staple...\n", "\n", "fhjpamownq\n", "wsdseuqeev\n", "ieaeladhcr\n", "piedtiriah\n", "rzsiwovspu\n", "oawhakieab\n", "browpcfrda\n", "ecnotopssr\n", "dikchdnpnb\n", "bstapleokr\n", "14 words added; 6 directions\n", "Present: apace cowhides crazies dock knows lived mown pears probed rhubarb rioted staple tops wide\n", "Decoys: adapting bombing boor brick cackles carnal casino chaplets chump coaster coccyxes coddle collies creels crumbled cunt curds curled curlier deepen demeanor dicier dowses ensuing faddish fest fickler foaming gambol garoting gliding gristle grunts guts ibex impugns instants kielbasy lanyard loamier lugs market meanly minuend misprint mitts molested moonshot mucking oaks olives orgasmic pastrami perfect proceed puckered quashed refined regards retraces revel ridges ringlet scoff shinier siren solaria sprain sunder sunup tamped tapes thirds throw tiller times trains tranquil transfix typesets uric wariness welts whimsy winced winced\n" ] } ], "source": [ "g, ws = interesting_grid(width=10, height=10, words_limit=5, direction_slack=6)\n", "p = pad_grid(g)\n", "ds = decoys(p, ws, ws_words)\n", "print(show_grid(g))\n", "print()\n", "print(show_grid(p))\n", "print(len(ws), 'words added; ', len(set(present(g, w)[3] for w in ws)), 'directions')\n", "print('Present:', wcat(sorted(ws)))\n", "print('Decoys:', wcat(sorted(ds)))" ] }, { "cell_type": "code", "execution_count": 98, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['fickler',\n", " 'adapting',\n", " 'chump',\n", " 'foaming',\n", " 'molested',\n", " 'carnal',\n", " 'crumbled',\n", " 'guts',\n", " 'minuend',\n", " 'bombing',\n", " 'winced',\n", " 'coccyxes',\n", " 'solaria',\n", " 'shinier',\n", " 'cackles']" ] }, "execution_count": 98, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds_original = ['regards', 'perfect', 'instants', 'refined', 'coddle', 'fickler', 'gambol', 'misprint', 'tapes', 'impugns', 'moonshot', 'chump', 'brick', 'siren', 'faddish', 'winced', 'kielbasy', 'market', 'puckered', 'trains', 'welts', 'cackles', 'foaming', 'proceed', 'gliding', 'guts', 'uric', 'oaks', 'molested', 'curled', 'boor', 'solaria', 'gristle', 'bombing', 'loamier', 'ensuing', 'cunt', 'sunder', 'revel', 'coaster', 'grunts', 'mucking', 'typesets', 'carnal', 'whimsy', 'scoff', 'coccyxes', 'meanly', 'sprain', 'minuend', 'ringlet', 'fest', 'winced', 'shinier', 'dicier', 'thirds', 'olives', 'garoting', 'pastrami', 'tranquil', 'tamped', 'sunup', 'crumbled', 'throw', 'ridges', 'chaplets', 'curlier', 'lugs', 'collies', 'adapting', 'demeanor', 'deepen', 'lanyard', 'tiller', 'transfix', 'wariness', 'times', 'mitts', 'dowses', 'creels', 'curds', 'quashed', 'orgasmic', 'ibex', 'retraces', 'casino']\n", "ds = random.sample(ds_original, 15)\n", "ds" ] }, { "cell_type": "code", "execution_count": 89, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "['regards',\n", " 'perfect',\n", " 'instants',\n", " 'refined',\n", " 'coddle',\n", " 'fickler',\n", " 'gambol',\n", " 'misprint',\n", " 'tapes',\n", " 'impugns',\n", " 'moonshot',\n", " 'chump',\n", " 'brick',\n", " 'siren',\n", " 'faddish',\n", " 'winced',\n", " 'kielbasy',\n", " 'market',\n", " 'puckered',\n", " 'trains',\n", " 'welts',\n", " 'cackles',\n", " 'foaming',\n", " 'proceed',\n", " 'gliding',\n", " 'guts',\n", " 'uric',\n", " 'oaks',\n", " 'molested',\n", " 'curled',\n", " 'boor',\n", " 'solaria',\n", " 'gristle',\n", " 'bombing',\n", " 'loamier',\n", " 'ensuing',\n", " 'cunt',\n", " 'sunder',\n", " 'revel',\n", " 'coaster',\n", " 'grunts',\n", " 'mucking',\n", " 'typesets',\n", " 'carnal',\n", " 'whimsy',\n", " 'scoff',\n", " 'coccyxes',\n", " 'meanly',\n", " 'sprain',\n", " 'minuend',\n", " 'ringlet',\n", " 'fest',\n", " 'winced',\n", " 'shinier',\n", " 'dicier',\n", " 'thirds',\n", " 'olives',\n", " 'garoting',\n", " 'pastrami',\n", " 'tranquil',\n", " 'tamped',\n", " 'sunup',\n", " 'crumbled',\n", " 'throw',\n", " 'ridges',\n", " 'chaplets',\n", " 'curlier',\n", " 'lugs',\n", " 'collies',\n", " 'adapting',\n", " 'demeanor',\n", " 'deepen',\n", " 'lanyard',\n", " 'tiller',\n", " 'transfix',\n", " 'wariness',\n", " 'times',\n", " 'mitts',\n", " 'dowses',\n", " 'creels',\n", " 'curds',\n", " 'quashed',\n", " 'orgasmic',\n", " 'ibex',\n", " 'retraces',\n", " 'casino']" ] }, "execution_count": 89, "metadata": {}, "output_type": "execute_result" } ], "source": [ "ds_original" ] }, { "cell_type": "code", "execution_count": 99, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "grid = [['.', '.', '.', 'p', '.', 'm', 'o', 'w', 'n', '.'], ['.', 's', 'd', 's', 'e', '.', '.', 'e', 'e', '.'], ['.', 'e', '.', 'e', 'l', 'a', 'd', '.', 'c', 'r'], ['p', 'i', '.', 'd', 't', 'i', 'r', '.', 'a', 'h'], ['r', 'z', 's', 'i', 'w', 'o', 'v', 's', 'p', 'u'], ['o', 'a', 'w', 'h', '.', 'k', 'i', 'e', 'a', 'b'], ['b', 'r', 'o', 'w', '.', 'c', '.', 'r', 'd', 'a'], ['e', 'c', 'n', 'o', 't', 'o', 'p', 's', '.', 'r'], ['d', '.', 'k', 'c', '.', 'd', '.', '.', '.', 'b'], ['.', 's', 't', 'a', 'p', 'l', 'e', '.', '.', '.']]\n", "padded_grid = [['f', 'h', 'j', 'p', 'a', 'm', 'o', 'w', 'n', 'q'], ['w', 's', 'd', 's', 'e', 'u', 'q', 'e', 'e', 'v'], ['i', 'e', 'a', 'e', 'l', 'a', 'd', 'h', 'c', 'r'], ['p', 'i', 'e', 'd', 't', 'i', 'r', 'i', 'a', 'h'], ['r', 'z', 's', 'i', 'w', 'o', 'v', 's', 'p', 'u'], ['o', 'a', 'w', 'h', 'a', 'k', 'i', 'e', 'a', 'b'], ['b', 'r', 'o', 'w', 'p', 'c', 'f', 'r', 'd', 'a'], ['e', 'c', 'n', 'o', 't', 'o', 'p', 's', 's', 'r'], ['d', 'i', 'k', 'c', 'h', 'd', 'n', 'p', 'n', 'b'], ['b', 's', 't', 'a', 'p', 'l', 'e', 'o', 'k', 'r']]\n", "present_words = ['probed', 'staple', 'rioted', 'cowhides', 'tops', 'knows', 'lived', 'rhubarb', 'crazies', 'dock', 'apace', 'mown', 'pears', 'wide']\n", "decoy_words = ['fickler', 'adapting', 'chump', 'foaming', 'molested', 'carnal', 'crumbled', 'guts', 'minuend', 'bombing', 'winced', 'coccyxes', 'solaria', 'shinier', 'cackles']\n", "Directions: [('probed', '`(True, 3, 0, )`'), ('staple', '`(True, 9, 1, )`'), ('rioted', '`(True, 6, 7, )`'), ('cowhides', '`(True, 8, 3, )`'), ('tops', '`(True, 7, 4, )`'), ('knows', '`(True, 8, 2, )`'), ('lived', '`(True, 2, 4, )`'), ('rhubarb', '`(True, 2, 9, )`'), ('crazies', '`(True, 7, 1, )`'), ('dock', '`(True, 8, 5, )`'), ('apace', '`(True, 5, 8, )`'), ('mown', '`(True, 0, 5, )`'), ('pears', '`(True, 0, 3, )`'), ('wide', '`(True, 4, 4, )`')]\n" ] } ], "source": [ "print('grid = ', g)\n", "print('padded_grid = ', p)\n", "print('present_words = ', ws)\n", "print('decoy_words = ', ds)\n", "print('Directions: ', [(w, '`' + str(present(g, w)) + '`') for w in ws])" ] }, { "cell_type": "code", "execution_count": 100, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# with open('example-wordsearch.txt', 'w') as f:\n", "# f.write('10x10\\n')\n", "# f.write(show_grid(p))\n", "# f.write('\\n')\n", "# f.write(lcat(sorted(ws + ds)))\n", "# with open('exmaple-wordsearch-solution.txt', 'w') as f:\n", "# f.write('10x10\\n')\n", "# f.write(show_grid(g))\n", "# f.write('\\n')\n", "# f.write(lcat(sorted(ws)) + '\\n\\n')\n", "# f.write(lcat(sorted(ds)))" ] }, { "cell_type": "code", "execution_count": 77, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "probed 3 0 6 Direction.down [(3, 0), (4, 0), (5, 0), (6, 0), (7, 0), (8, 0)]\n", "staple 9 1 6 Direction.right [(9, 1), (9, 2), (9, 3), (9, 4), (9, 5), (9, 6)]\n", "rioted 6 7 6 Direction.upleft [(6, 7), (5, 6), (4, 5), (3, 4), (2, 3), (1, 2)]\n", "cowhides 8 3 8 Direction.up [(8, 3), (7, 3), (6, 3), (5, 3), (4, 3), (3, 3), (2, 3), (1, 3)]\n", "tops 7 4 4 Direction.right [(7, 4), (7, 5), (7, 6), (7, 7)]\n", "knows 8 2 5 Direction.up [(8, 2), (7, 2), (6, 2), (5, 2), (4, 2)]\n", "lived 2 4 5 Direction.downright [(2, 4), (3, 5), (4, 6), (5, 7), (6, 8)]\n", "rhubarb 2 9 7 Direction.down [(2, 9), (3, 9), (4, 9), (5, 9), (6, 9), (7, 9), (8, 9)]\n", "crazies 7 1 7 Direction.up [(7, 1), (6, 1), (5, 1), (4, 1), (3, 1), (2, 1), (1, 1)]\n", "dock 8 5 4 Direction.up [(8, 5), (7, 5), (6, 5), (5, 5)]\n", "apace 5 8 5 Direction.up [(5, 8), (4, 8), (3, 8), (2, 8), (1, 8)]\n", "mown 0 5 4 Direction.right [(0, 5), (0, 6), (0, 7), (0, 8)]\n", "pears 0 3 5 Direction.downright [(0, 3), (1, 4), (2, 5), (3, 6), (4, 7)]\n", "wide 4 4 4 Direction.upright [(4, 4), (3, 5), (2, 6), (1, 7)]\n" ] }, { "data": { "text/plain": [ "[(7, 5), (2, 3), (3, 5)]" ] }, "execution_count": 77, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cts = collections.Counter()\n", "for w in ws:\n", " _, r, c, d = present(g, w)\n", " inds = indices(g, r, c, len(w), d)\n", " for i in inds:\n", " cts[i] += 1\n", " print(w, r, c, len(w), d, inds)\n", "[i for i in cts if cts[i] > 1]" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 143, "metadata": { "scrolled": true }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n", "7\n", "8\n", "9\n", "10\n", "11\n", "12\n", "13\n", "14\n", "15\n", "16\n", "17\n", "18\n", "19\n", "20\n", "21\n", "22\n", "23\n", "24\n", "25\n", "26\n", "27\n", "28\n", "29\n", "30\n", "31\n", "32\n", "33\n", "34\n", "35\n", "36\n", "37\n", "38\n", "39\n", "40\n", "41\n", "42\n", "43\n", "44\n", "45\n", "46\n", "47\n", "48\n", "49\n", "50\n", "51\n", "52\n", "53\n", "54\n", "55\n", "56\n", "57\n", "58\n", "59\n", "60\n", "61\n", "62\n", "63\n", "64\n", "65\n", "66\n", "67\n", "68\n", "69\n", "70\n", "71\n", "72\n", "73\n", "74\n", "75\n", "76\n", "77\n", "78\n", "79\n", "80\n", "81\n", "82\n", "83\n", "84\n", "85\n", "86\n", "87\n", "88\n", "89\n", "90\n", "91\n", "92\n", "93\n", "94\n", "95\n", "96\n", "97\n", "98\n", "99\n" ] } ], "source": [ "# for i in range(100):\n", "# print(i)\n", "# g, ws = interesting_grid()\n", "# p = pad_grid(g)\n", "# ds = decoys(p, ws, ws_words)\n", "# with open('wordsearch{:02}.txt'.format(i), 'w') as f:\n", "# f.write('20x20\\n')\n", "# f.write(show_grid(p))\n", "# f.write('\\n')\n", "# f.write(lcat(sorted(ws + ds)))\n", "# with open('wordsearch-solution{:02}.txt'.format(i), 'w') as f:\n", "# f.write('20x20\\n')\n", "# f.write(show_grid(g))\n", "# f.write('\\n')\n", "# f.write(lcat(sorted(ws)) + '\\n\\n')\n", "# f.write(lcat(sorted(ds)))" ] }, { "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": 1 }