14 "import collections\n",
17 "from enum import Enum\n",
18 "Direction = Enum('Direction', 'left right up down upleft upright downleft downright')\n",
20 "delta = {Direction.left: (0, -1),Direction.right: (0, 1), \n",
21 " Direction.up: (-1, 0), Direction.down: (1, 0), \n",
22 " Direction.upleft: (-1, -1), Direction.upright: (-1, 1), \n",
23 " Direction.downleft: (1, -1), Direction.downright: (1, 1)}\n",
38 "# all_words = [w.strip() for w in open('/usr/share/dict/british-english').readlines()\n",
39 "# if all(c in string.ascii_lowercase for c in w.strip())]\n",
40 "# words = [w for w in all_words\n",
41 "# if not any(w in w2 for w2 in all_words if w != w2)]\n",
42 "# open('wordsearch-words', 'w').write(lcat(words))"
69 "output_type": "execute_result"
73 "ws_words = [w.strip() for w in open('wordsearch-words').readlines()\n",
74 " if all(c in string.ascii_lowercase for c in w.strip())]\n",
86 "def empty_grid(w, h):\n",
87 " return [['.' for c in range(w)] for r in range(h)]"
98 "def show_grid(grid):\n",
99 " return lcat(cat(r) for r in grid)"
104 "execution_count": 7,
111 "output_type": "stream",
127 "grid = empty_grid(10, 10)\n",
128 "print(show_grid(grid))"
133 "execution_count": 8,
139 "def indices(grid, r, c, l, d):\n",
140 " dr, dc = delta[d]\n",
141 " w = len(grid[0])\n",
143 " inds = [(r + i * dr, c + i * dc) for i in range(l)]\n",
144 " return [(i, j) for i, j in inds\n",
153 "execution_count": 9,
159 "def gslice(grid, r, c, l, d):\n",
160 " return [grid[i][j] for i, j in indices(grid, r, c, l, d)]"
165 "execution_count": 10,
171 "def set_grid(grid, r, c, d, word):\n",
172 " for (i, j), l in zip(indices(grid, r, c, len(word), d), word):\n",
179 "execution_count": 11,
186 "output_type": "stream",
202 "set_grid(grid, 2, 3, Direction.downright, 'testword')\n",
203 "print(show_grid(grid))"
208 "execution_count": 12,
219 "execution_count": 12,
221 "output_type": "execute_result"
225 "cat(gslice(grid, 3, 2, 15, Direction.right))"
230 "execution_count": 13,
238 "<_sre.SRE_Match object; span=(0, 4), match='keen'>"
241 "execution_count": 13,
243 "output_type": "execute_result"
247 "re.match(cat(gslice(grid, 3, 2, 4, Direction.right)), 'keen')"
252 "execution_count": 14,
260 "<_sre.SRE_Match object; span=(0, 3), match='kee'>"
263 "execution_count": 14,
265 "output_type": "execute_result"
269 "re.match(cat(gslice(grid, 3, 2, 3, Direction.right)), 'keen')"
274 "execution_count": 15,
280 "re.fullmatch(cat(gslice(grid, 3, 2, 3, Direction.right)), 'keen')"
285 "execution_count": 16,
291 "re.match(cat(gslice(grid, 3, 2, 4, Direction.right)), 'kine')"
296 "execution_count": 17,
302 "def could_add(grid, r, c, d, word):\n",
303 " s = gslice(grid, r, c, len(word), d)\n",
304 " return re.fullmatch(cat(s), word)"
309 "execution_count": 18,
317 "<_sre.SRE_Match object; span=(0, 4), match='keen'>"
320 "execution_count": 18,
322 "output_type": "execute_result"
326 "could_add(grid, 3, 2, Direction.right, 'keen')"
331 "execution_count": 19,
337 "could_add(grid, 3, 2, Direction.right, 'kine')"
342 "execution_count": 20,
353 "execution_count": 20,
355 "output_type": "execute_result"
359 "random.choice(list(Direction))"
364 "execution_count": 21,
370 "def fill_grid(grid, words, word_count, max_attempts= 1000):\n",
372 " added_words = []\n",
373 " w = len(grid[0])\n",
375 " while len(added_words) < word_count and attempts < max_attempts:\n",
377 " r = random.randrange(w)\n",
378 " c = random.randrange(h)\n",
379 " word = random.choice(words)\n",
380 " d = random.choice(list(Direction))\n",
381 " if could_add(grid, r, c, d, word):\n",
382 " set_grid(grid, r, c, d, word)\n",
383 " added_words += [word]\n",
385 " return grid, added_words"
390 "execution_count": 22,
401 "execution_count": 22,
403 "output_type": "execute_result"
407 "g = empty_grid(20, 20)\n",
408 "g, ws = fill_grid(g, ws_words, 40)\n",
414 "execution_count": 23,
421 "output_type": "stream",
423 "......swoopingg.l.up\n",
424 "..dunsnapped.n.i..ne\n",
425 ".cee.gninarci.m...er\n",
426 "sotpt......k.pmv..mv\n",
427 "euirca.d..c.n.a...pa\n",
428 "snduo.o.eo.e.lgs..ld\n",
429 "itndny.ctks.i.nos.oe\n",
430 "rroev.lsrsss..ifr.ys\n",
431 "eycno.eb.aeub.ttebas\n",
432 "tmetyr..asgetmuemebe\n",
433 "nerie....tvuu.dsraln\n",
434 "in.adbdmbecls.etocei\n",
435 "w..loeu.lilu..s.fh.d\n",
436 "...rtl.e.ec.l...eimw\n",
437 "..oac.d.v..y.e..rnao\n",
438 ".nrhgniknilsc.n..gyd\n",
439 ".pignippay...l.i..f.\n",
440 ".n..skcenrehtael..l.\n",
441 "g....popinjays.s..y.\n",
442 "gnimmugspuds.relppus\n",
444 "ineluctably limpness countrymen slinking beaching restocking vellum convoyed winterises tusked leathernecks sugarcoated mayfly mulching popinjays magnitudes unsnapped prudential yapping spuds softest boron craning unemployable reformers bicycles swooping recondite dowdiness gumming pervades beveled valises suppler prated\n"
449 "print(show_grid(g))\n",
450 "print(len(ws), 'words added')\n",
456 "execution_count": 24,
462 "def present(grid, word):\n",
463 " w = len(grid[0])\n",
465 " for r in range(h):\n",
466 " for c in range(w):\n",
467 " for d in Direction:\n",
468 " if cat(gslice(grid, r, c, len(word), d)) == word:\n",
469 " return True, r, c, d\n",
470 " return False, 0, 0, list(Direction)[0]"
475 "execution_count": 25,
483 "output_type": "stream",
485 "ineluctably (True, 16, 15, <Direction.upleft: 5>)\n",
486 "limpness (True, 0, 16, <Direction.downleft: 7>)\n",
487 "countrymen (True, 2, 1, <Direction.down: 4>)\n",
488 "slinking (True, 15, 11, <Direction.left: 1>)\n",
489 "beaching (True, 8, 17, <Direction.down: 4>)\n",
490 "restocking (True, 9, 5, <Direction.upright: 6>)\n",
491 "vellum (True, 14, 8, <Direction.upright: 6>)\n",
492 "convoyed (True, 4, 4, <Direction.down: 4>)\n",
493 "winterises (True, 12, 0, <Direction.up: 3>)\n",
494 "tusked (True, 9, 12, <Direction.upleft: 5>)\n",
495 "leathernecks (True, 17, 15, <Direction.left: 1>)\n",
496 "sugarcoated (True, 11, 12, <Direction.upleft: 5>)\n",
497 "mayfly (True, 13, 18, <Direction.down: 4>)\n",
498 "mulching (True, 11, 7, <Direction.downleft: 7>)\n",
499 "popinjays (True, 18, 5, <Direction.right: 2>)\n",
500 "magnitudes (True, 3, 14, <Direction.down: 4>)\n",
501 "unsnapped (True, 1, 3, <Direction.right: 2>)\n",
502 "prudential (True, 3, 3, <Direction.down: 4>)\n",
503 "yapping (True, 16, 9, <Direction.left: 1>)\n",
504 "spuds (True, 19, 7, <Direction.right: 2>)\n",
505 "softest (True, 5, 15, <Direction.down: 4>)\n",
506 "boron (True, 11, 5, <Direction.downleft: 7>)\n",
507 "craning (True, 2, 11, <Direction.left: 1>)\n",
508 "unemployable (True, 0, 18, <Direction.down: 4>)\n",
509 "reformers (True, 14, 16, <Direction.up: 3>)\n",
510 "bicycles (True, 11, 8, <Direction.downright: 8>)\n",
511 "swooping (True, 0, 6, <Direction.right: 2>)\n",
512 "recondite (True, 10, 2, <Direction.up: 3>)\n",
513 "dowdiness (True, 15, 19, <Direction.up: 3>)\n",
514 "gumming (True, 19, 6, <Direction.left: 1>)\n",
515 "pervades (True, 0, 19, <Direction.down: 4>)\n",
516 "beveled (True, 8, 12, <Direction.downleft: 7>)\n",
517 "valises (True, 3, 15, <Direction.downleft: 7>)\n",
518 "suppler (True, 19, 19, <Direction.left: 1>)\n",
519 "prated (True, 16, 1, <Direction.upright: 6>)\n"
525 " print(w, present(g, w))"
530 "execution_count": 26,
536 "def interesting(grid, words):\n",
537 " dirs = set(present(grid, w)[3] for w in words)\n",
538 " return len(words) > 35 and len(words) < 40 and len(dirs) + 1 >= len(delta)"
543 "execution_count": 27,
554 "execution_count": 27,
556 "output_type": "execute_result"
565 "execution_count": 28,
571 "def interesting_grid():\n",
574 " grid = empty_grid(20, 20)\n",
575 " grid, words = fill_grid(grid, ws_words, 40)\n",
576 " boring = not interesting(grid, words)\n",
577 " return grid, words"
582 "execution_count": 29,
589 "output_type": "stream",
591 "..reittonk..ss......\n",
592 "tinctured.wcee.....w\n",
593 "serutats.oyozm....o.\n",
594 "b....s..l.eoia...m.r\n",
595 "e.b.y.lf..lpsd..bgye\n",
596 "a.ist.no..less.ssrgm\n",
597 "m.gtfi.lo.orae.n.ura\n",
598 "edaei..i.cwi.mo..mor\n",
599 "demrn..b..in.m...psk\n",
600 "epya...e..sgm....ile\n",
601 "slsg...l..hi.....nrd\n",
602 "tekisyassesdepeebeum\n",
603 "rtec.gninretni...sfo\n",
604 "oiinsetse..baggy.snd\n",
605 "ynn....p..sebircsaui\n",
606 "egs.noitasiretupmocf\n",
607 "r.....artefacts....y\n",
608 "s.....seilaog.winosi\n",
609 ".....eyelidsegener.n\n",
610 "regicidesesopatxuj.g\n",
611 "38 words added; 7 directions\n",
612 "wombs persimmons computerisation ascribes coopering goalies beamed modifying insets cigarets statures libels remarked baggy juxtaposes mesdames grumpiness artefacts skeins assizes inflow depleting beeped reneges interning yellowish regicides eyelids cools orgy nifty knottier destroyers unfurls tinctured bigamy winos essays\n"
617 "g, ws = interesting_grid()\n",
618 "print(show_grid(g))\n",
619 "print(len(ws), 'words added; ', len(set(present(g, w)[3] for w in ws)), 'directions')\n",
625 "execution_count": 30,
631 "def datafile(name, sep='\\t'):\n",
632 " \"\"\"Read key,value pairs from file.\n",
634 " with open(name) as f:\n",
636 " splits = line.split(sep)\n",
637 " yield [splits[0], int(splits[1])]"
642 "execution_count": 31,
648 "def normalise(frequencies):\n",
649 " \"\"\"Scale a set of frequencies so they sum to one\n",
651 " >>> sorted(normalise({1: 1, 2: 0}).items())\n",
652 " [(1, 1.0), (2, 0.0)]\n",
653 " >>> sorted(normalise({1: 1, 2: 1}).items())\n",
654 " [(1, 0.5), (2, 0.5)]\n",
655 " >>> sorted(normalise({1: 1, 2: 1, 3: 1}).items()) # doctest: +ELLIPSIS\n",
656 " [(1, 0.333...), (2, 0.333...), (3, 0.333...)]\n",
657 " >>> sorted(normalise({1: 1, 2: 2, 3: 1}).items())\n",
658 " [(1, 0.25), (2, 0.5), (3, 0.25)]\n",
660 " length = sum(f for f in frequencies.values())\n",
661 " return collections.defaultdict(int, ((k, v / length) \n",
662 " for (k, v) in frequencies.items()))\n"
667 "execution_count": 32,
673 "english_counts = collections.Counter(dict(datafile('count_1l.txt')))\n",
674 "normalised_english_counts = normalise(english_counts)"
679 "execution_count": 34,
685 "wordsearch_counts = collections.Counter(cat(ws_words))\n",
686 "normalised_wordsearch_counts = normalise(wordsearch_counts)"
691 "execution_count": 35,
697 "def weighted_choice(d):\n",
698 " \"\"\"Generate random item from a dictionary of item counts\n",
700 " target = random.uniform(0, sum(d.values()))\n",
702 " for (l, p) in d.items():\n",
704 " if cuml > target:\n",
708 "def random_english_letter():\n",
709 " \"\"\"Generate a random letter based on English letter counts\n",
711 " return weighted_choice(normalised_english_counts)\n",
713 "def random_wordsearch_letter():\n",
714 " \"\"\"Generate a random letter based on wordsearch letter counts\n",
716 " return weighted_choice(normalised_wordsearch_counts)"
721 "execution_count": 36,
729 "'aaaaaaaabcccddddeeeeeeeeeeeeeeefffggghhhhhiiiiiillllmnnnnnnoooooooooprrsssssssssssssttttttttuuuvwwwy'"
732 "execution_count": 36,
734 "output_type": "execute_result"
738 "cat(sorted(random_english_letter() for i in range(100)))"
743 "execution_count": 37,
751 "'aaaaaabcccddddddeeeeeeggggghhiiiiiiiiiiiiklllmmmmnnnnnnnnnnoooooooooppprrrrrrrrrssssssttttttuuuwwwyy'"
754 "execution_count": 37,
756 "output_type": "execute_result"
760 "cat(sorted(random_wordsearch_letter() for i in range(100)))"
765 "execution_count": 38,
776 "execution_count": 38,
778 "output_type": "execute_result"
782 "random_wordsearch_letter()"
787 "execution_count": 39,
793 "def pad_grid(g0):\n",
794 " grid = copy.deepcopy(g0)\n",
795 " w = len(grid[0])\n",
797 " for r in range(h):\n",
798 " for c in range(w):\n",
799 " if grid[r][c] == '.':\n",
800 " grid[r][c] = random_wordsearch_letter()\n",
806 "execution_count": 40,
813 "output_type": "stream",
815 "streittonkorsssatnal\n",
816 "tincturedswceedrlnuw\n",
817 "serutatsloyozmeieiot\n",
818 "baanfsollleoiasnlmar\n",
819 "ewblyhlfetlpsdyvbgye\n",
820 "aeistonoeilessassrgm\n",
821 "mlgtfitloioraeenwura\n",
822 "edaeiupiscwiamoygmor\n",
823 "demrnasbhcinsmiiapsk\n",
824 "epyakraedrsgmolsnile\n",
825 "slsgtuoloihireneonrd\n",
826 "tekisyassesdepeebeum\n",
827 "rtecigninretnincesfo\n",
828 "oiinsetseddbaggydsnd\n",
829 "ynnnsfapcfsebircsaui\n",
830 "egsonoitasiretupmocf\n",
831 "raioelartefactseawfy\n",
832 "speonsseilaogrwinosi\n",
833 "wrndfeyelidsegenerln\n",
834 "regicidesesopatxujrg\n"
839 "padded = pad_grid(g)\n",
840 "print(show_grid(padded))"
845 "execution_count": 41,
852 "output_type": "stream",
854 "..reittonk..ss......\n",
855 "tinctured.wcee.....w\n",
856 "serutats.oyozm....o.\n",
857 "b....s..l.eoia...m.r\n",
858 "e.b.y.lf..lpsd..bgye\n",
859 "a.ist.no..less.ssrgm\n",
860 "m.gtfi.lo.orae.n.ura\n",
861 "edaei..i.cwi.mo..mor\n",
862 "demrn..b..in.m...psk\n",
863 "epya...e..sgm....ile\n",
864 "slsg...l..hi.....nrd\n",
865 "tekisyassesdepeebeum\n",
866 "rtec.gninretni...sfo\n",
867 "oiinsetse..baggy.snd\n",
868 "ynn....p..sebircsaui\n",
869 "egs.noitasiretupmocf\n",
870 "r.....artefacts....y\n",
871 "s.....seilaog.winosi\n",
872 ".....eyelidsegener.n\n",
873 "regicidesesopatxuj.g\n"
878 "print(show_grid(g))"
883 "execution_count": 42,
891 "output_type": "stream",
893 "wombs (True, 1, 19, <Direction.downleft: 7>)\n",
894 "persimmons (True, 14, 7, <Direction.upright: 6>)\n",
895 "computerisation (True, 15, 18, <Direction.left: 1>)\n",
896 "ascribes (True, 14, 17, <Direction.left: 1>)\n",
897 "coopering (True, 1, 11, <Direction.down: 4>)\n",
898 "goalies (True, 17, 12, <Direction.left: 1>)\n",
899 "beamed (True, 3, 0, <Direction.down: 4>)\n",
900 "modifying (True, 11, 19, <Direction.down: 4>)\n",
901 "insets (True, 13, 2, <Direction.right: 2>)\n",
902 "cigarets (True, 12, 3, <Direction.up: 3>)\n",
903 "statures (True, 2, 7, <Direction.left: 1>)\n",
904 "libels (True, 6, 7, <Direction.down: 4>)\n",
905 "remarked (True, 3, 19, <Direction.down: 4>)\n",
906 "baggy (True, 13, 11, <Direction.right: 2>)\n",
907 "juxtaposes (True, 19, 17, <Direction.left: 1>)\n",
908 "mesdames (True, 7, 13, <Direction.up: 3>)\n",
909 "grumpiness (True, 4, 17, <Direction.down: 4>)\n",
910 "artefacts (True, 16, 6, <Direction.right: 2>)\n",
911 "skeins (True, 10, 2, <Direction.down: 4>)\n",
912 "assizes (True, 6, 12, <Direction.up: 3>)\n",
913 "inflow (True, 6, 5, <Direction.upright: 6>)\n",
914 "depleting (True, 7, 1, <Direction.down: 4>)\n",
915 "beeped (True, 11, 16, <Direction.left: 1>)\n",
916 "reneges (True, 18, 17, <Direction.left: 1>)\n",
917 "interning (True, 12, 13, <Direction.left: 1>)\n",
918 "yellowish (True, 2, 10, <Direction.down: 4>)\n",
919 "regicides (True, 19, 0, <Direction.right: 2>)\n",
920 "eyelids (True, 18, 5, <Direction.right: 2>)\n",
921 "cools (True, 7, 9, <Direction.upleft: 5>)\n",
922 "orgy (True, 7, 18, <Direction.up: 3>)\n",
923 "nifty (True, 8, 4, <Direction.up: 3>)\n",
924 "knottier (True, 0, 9, <Direction.left: 1>)\n",
925 "destroyers (True, 8, 0, <Direction.down: 4>)\n",
926 "unfurls (True, 14, 18, <Direction.up: 3>)\n",
927 "tinctured (True, 1, 0, <Direction.right: 2>)\n",
928 "bigamy (True, 4, 2, <Direction.down: 4>)\n",
929 "winos (True, 17, 14, <Direction.right: 2>)\n",
930 "essays (True, 11, 9, <Direction.left: 1>)\n"
936 " print(w, present(padded, w))"
941 "execution_count": 51,
947 "def decoys(grid, words, all_words, limit=60):\n",
948 " decoy_words = []\n",
949 " dlen_limit = max(len(w) for w in words)\n",
950 " while len(words) + len(decoy_words) < limit:\n",
951 " d = random.choice(all_words)\n",
952 " if d not in words and len(d) < dlen_limit and not present(grid, d)[0]:\n",
953 " decoy_words += [d]\n",
954 " return decoy_words"
959 "execution_count": 52,
990 "execution_count": 52,
992 "output_type": "execute_result"
996 "ds = decoys(padded, ws, ws_words)\n",
1001 "cell_type": "code",
1002 "execution_count": 53,
1010 "output_type": "stream",
1012 "freckled (False, 0, 0, <Direction.left: 1>)\n",
1013 "transcripts (False, 0, 0, <Direction.left: 1>)\n",
1014 "dinnering (False, 0, 0, <Direction.left: 1>)\n",
1015 "insulating (False, 0, 0, <Direction.left: 1>)\n",
1016 "regurgitates (False, 0, 0, <Direction.left: 1>)\n",
1017 "drouthes (False, 0, 0, <Direction.left: 1>)\n",
1018 "cocky (False, 0, 0, <Direction.left: 1>)\n",
1019 "stodgy (False, 0, 0, <Direction.left: 1>)\n",
1020 "bestrides (False, 0, 0, <Direction.left: 1>)\n",
1021 "perceives (False, 0, 0, <Direction.left: 1>)\n",
1022 "waned (False, 0, 0, <Direction.left: 1>)\n",
1023 "pisses (False, 0, 0, <Direction.left: 1>)\n",
1024 "alienating (False, 0, 0, <Direction.left: 1>)\n",
1025 "hyperbolas (False, 0, 0, <Direction.left: 1>)\n",
1026 "yeshivoth (False, 0, 0, <Direction.left: 1>)\n",
1027 "allured (False, 0, 0, <Direction.left: 1>)\n",
1028 "outstaying (False, 0, 0, <Direction.left: 1>)\n",
1029 "bureaus (False, 0, 0, <Direction.left: 1>)\n",
1030 "tragedians (False, 0, 0, <Direction.left: 1>)\n",
1031 "wooed (False, 0, 0, <Direction.left: 1>)\n",
1032 "unwary (False, 0, 0, <Direction.left: 1>)\n",
1033 "provoking (False, 0, 0, <Direction.left: 1>)\n",
1034 "curies (False, 0, 0, <Direction.left: 1>)\n",
1035 "deviltry (False, 0, 0, <Direction.left: 1>)\n",
1036 "wooly (False, 0, 0, <Direction.left: 1>)\n",
1037 "abysmally (False, 0, 0, <Direction.left: 1>)\n",
1038 "ladled (False, 0, 0, <Direction.left: 1>)\n",
1039 "tamable (False, 0, 0, <Direction.left: 1>)\n",
1040 "minors (False, 0, 0, <Direction.left: 1>)\n",
1041 "aortas (False, 0, 0, <Direction.left: 1>)\n",
1042 "souses (False, 0, 0, <Direction.left: 1>)\n",
1043 "heinously (False, 0, 0, <Direction.left: 1>)\n",
1044 "cardiac (False, 0, 0, <Direction.left: 1>)\n",
1045 "peons (True, 17, 1, <Direction.right: 2>)\n",
1046 "karate (False, 0, 0, <Direction.left: 1>)\n",
1047 "tansy (False, 0, 0, <Direction.left: 1>)\n",
1048 "unruly (False, 0, 0, <Direction.left: 1>)\n",
1049 "absently (False, 0, 0, <Direction.left: 1>)\n",
1050 "pads (False, 0, 0, <Direction.left: 1>)\n",
1051 "ditches (False, 0, 0, <Direction.left: 1>)\n",
1052 "fuzes (False, 0, 0, <Direction.left: 1>)\n",
1053 "antivirals (False, 0, 0, <Direction.left: 1>)\n",
1054 "chronology (False, 0, 0, <Direction.left: 1>)\n",
1055 "yacked (False, 0, 0, <Direction.left: 1>)\n",
1056 "percentages (False, 0, 0, <Direction.left: 1>)\n",
1057 "heftier (False, 0, 0, <Direction.left: 1>)\n",
1058 "inimitably (False, 0, 0, <Direction.left: 1>)\n",
1059 "conveys (False, 0, 0, <Direction.left: 1>)\n",
1060 "remaindered (False, 0, 0, <Direction.left: 1>)\n",
1061 "retaken (False, 0, 0, <Direction.left: 1>)\n",
1062 "reckoned (False, 0, 0, <Direction.left: 1>)\n",
1063 "emery (False, 0, 0, <Direction.left: 1>)\n",
1064 "squats (False, 0, 0, <Direction.left: 1>)\n",
1065 "tenderfoots (False, 0, 0, <Direction.left: 1>)\n",
1066 "sociology (False, 0, 0, <Direction.left: 1>)\n",
1067 "arbutuses (False, 0, 0, <Direction.left: 1>)\n",
1068 "betook (False, 0, 0, <Direction.left: 1>)\n",
1069 "coniferous (False, 0, 0, <Direction.left: 1>)\n",
1070 "gambled (False, 0, 0, <Direction.left: 1>)\n",
1071 "crouching (False, 0, 0, <Direction.left: 1>)\n"
1076 "for w in ws + ds:\n",
1077 " print(w, present(padded, w))"
1081 "cell_type": "code",
1082 "execution_count": 54,
1089 "output_type": "stream",
1091 "ihaceglstcongealedim\n",
1092 "locnlanmecdwsieyieyp\n",
1093 "uslrbacimdmedruyirfo\n",
1094 "hyacaascsatireeaiefm\n",
1095 "epyatooheutryldpifum\n",
1096 "chiuantaedrivgeouihe\n",
1097 "diehehdftsionrsdmoil\n",
1098 "ylrnpsounaonhspadtrs\n",
1099 "linhegiglgirgcidagug\n",
1100 "gsaornesallliseilnwo\n",
1101 "nlnenigpsnnhllsrlins\n",
1102 "ityvuprergselipdohyi\n",
1103 "mstismocwduusngeygsw\n",
1104 "oextoooincnhksshsuci\n",
1105 "cmiiprvfanedcwuctook\n",
1106 "ersnptyiaclippingsur\n",
1107 "biauindcemostlysietd\n",
1108 "rflpebesmsskrepppsil\n",
1109 "yssorgnileereouepyna\n",
1110 "taeaeweathercockswgs\n",
1111 "36 words added; 7 directions\n",
1112 "Present: acceding alloys annulled becomingly chorusing chugs clashes clayier clippings congealed dullness espies firmest groovy groupers hogans huffy kiwis matins mostly outmoded perks pommels punitive reeling scouting sixty soppier soughing specifics syphilis taillights tromping unrepeatable weathercocks wispy\n",
1113 "Decoys: belittled buzzwords climbs congaed criterions drifters exteriors filial flattery gambolling haversacks insiders interferon leukaemia liabilities mavens mentalities padlocking ptarmigans puking retarded seaming skimpiness wanderers\n"
1118 "g, ws = interesting_grid()\n",
1119 "p = pad_grid(g)\n",
1120 "ds = decoys(p, ws, ws_words)\n",
1121 "print(show_grid(p))\n",
1122 "print(len(ws), 'words added; ', len(set(present(g, w)[3] for w in ws)), 'directions')\n",
1123 "print('Present:', wcat(sorted(ws)))\n",
1124 "print('Decoys:', wcat(sorted(ds)))"
1128 "cell_type": "code",
1129 "execution_count": 55,
1136 "output_type": "stream",
1162 "for i in range(20):\n",
1164 " g, ws = interesting_grid()\n",
1165 " p = pad_grid(g)\n",
1166 " ds = decoys(p, ws, ws_words)\n",
1167 " with open('wordsearch{:02}.txt'.format(i), 'w') as f:\n",
1168 " f.write('20x20\\n')\n",
1169 " f.write(show_grid(p))\n",
1170 " f.write('\\n')\n",
1171 " f.write(lcat(sorted(ws + ds)))\n",
1172 " with open('wordsearch-solution{:02}.txt'.format(i), 'w') as f:\n",
1173 " f.write('20x20\\n')\n",
1174 " f.write(show_grid(g))\n",
1175 " f.write('\\n')\n",
1176 " f.write(lcat(sorted(ws)) + '\\n\\n')\n",
1177 " f.write(lcat(sorted(ds)))"
1181 "cell_type": "code",
1182 "execution_count": null,
1192 "display_name": "Python 3",
1193 "language": "python",
1197 "codemirror_mode": {
1201 "file_extension": ".py",
1202 "mimetype": "text/x-python",
1204 "nbconvert_exporter": "python",
1205 "pygments_lexer": "ipython3",