4 "signature": "sha256:b93ed7f85302bd806b23e539f31a6d8afd7554cafe052439a06de6aa5a19b08d"
29 "WORDS = [w.strip() for w in open('/usr/share/dict/british-english').readlines() \n",
30 " if re.match(r'^[a-z]*$', w.strip())]"
41 "LETTER_COUNTS = collections.Counter(l.lower() for l in open('sherlock-holmes.txt').read() if l in string.ascii_letters)\n",
42 "LETTERS_IN_ORDER = [p[0] for p in LETTER_COUNTS.most_common()]"
65 " def __init__(self, target, player=None, lives=STARTING_LIVES):\n",
66 " self.lives = lives\n",
67 " self.player = player\n",
68 " self.target = target\n",
69 " self.discovered = list('_' * len(target))\n",
70 " self.wrong_letters = []\n",
71 " self.game_finished = False\n",
72 " self.game_won = False\n",
73 " self.game_lost = False\n",
75 " def find_all(self, letter):\n",
78 " location = self.target.find(letter)\n",
79 " while location > -1:\n",
80 " locations += [location]\n",
81 " starting = location + 1\n",
82 " location = self.target.find(letter, starting)\n",
83 " return locations\n",
85 " def update_discovered_word(self, guessed_letter):\n",
86 " locations = self.find_all(guessed_letter)\n",
87 " for location in locations:\n",
88 " self.discovered[location] = guessed_letter\n",
89 " return self.discovered\n",
91 " def do_turn(self):\n",
93 " guess = self.player.guess(self.discovered, self.wrong_letters, self.lives)\n",
95 " guess = self.ask_for_guess()\n",
96 " if guess in self.target:\n",
97 " self.update_discovered_word(guess)\n",
100 " if guess not in self.wrong_letters:\n",
101 " self.wrong_letters += [guess]\n",
102 " if self.lives == 0:\n",
103 " self.game_finished = True\n",
104 " self.game_lost = True\n",
105 " if '_' not in self.discovered:\n",
106 " self.game_finished = True\n",
107 " self.game_won = True\n",
109 " def ask_for_guess(self):\n",
110 " print('Word:', ' '.join(self.discovered), \n",
111 " ' : Lives =', self.lives, \n",
112 " ', wrong guesses:', ' '.join(sorted(self.wrong_letters)))\n",
113 " guess = input('Enter letter: ').strip().lower()[0]\n",
116 " def play_game(self):\n",
118 " while not self.game_finished:\n",
120 " if not self.player:\n",
121 " self.report_on_game()\n",
122 " return self.game_won\n",
124 " def report_on_game(self):\n",
125 " if self.game_won:\n",
126 " print('You won! The word was', self.target)\n",
128 " print('You lost. The word was', self.target)\n",
129 " return self.game_won"
131 "language": "python",
140 "class PlayerFixedOrder:\n",
141 " def __init__(self, ordered_letters):\n",
142 " self.ordered_letters = ordered_letters\n",
144 " def guess(self, discovered, missed, lives):\n",
145 " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
146 " self.ordered_subtract(guessed_letters)\n",
147 " return self.ordered_letters[0]\n",
149 " def ordered_subtract(self, to_remove):\n",
150 " for r in to_remove:\n",
151 " if r in self.ordered_letters:\n",
152 " ri = self.ordered_letters.index(r)\n",
153 " self.ordered_letters = self.ordered_letters[:ri] + self.ordered_letters[ri+1:]"
155 "language": "python",
164 "class PlayerAlphabetical(PlayerFixedOrder):\n",
165 " def __init__(self):\n",
166 " super().__init__(string.ascii_lowercase)\n",
168 "class PlayerFreqOrdered(PlayerFixedOrder):\n",
169 " def __init__(self):\n",
170 " super().__init__(LETTERS_IN_ORDER)\n"
172 "language": "python",
182 "for _ in range(1000):\n",
183 " g = Game(random.choice(WORDS), player=PlayerAlphabetical())\n",
189 "language": "python",
193 "output_type": "stream",
207 "for _ in range(1000):\n",
208 " g = Game(random.choice(WORDS), player=PlayerFreqOrdered())\n",
214 "language": "python",
218 "output_type": "stream",
232 "for _ in range(1000):\n",
233 " g = Game(random.choice(WORDS), player=PlayerFixedOrder(list(reversed(string.ascii_lowercase))))\n",
239 "language": "python",
243 "output_type": "stream",
256 "DICT_COUNTS = collections.Counter(l.lower() for l in open('/usr/share/dict/british-english').read() if l in string.ascii_letters)\n",
257 "DICT_LETTERS_IN_ORDER = [p[0] for p in DICT_COUNTS.most_common()]"
259 "language": "python",
270 "language": "python",
275 "output_type": "pyout",
278 "Counter({'s': 91332, 'e': 88692, 'i': 66900, 'a': 64468, 'r': 57460, 'n': 57128, 't': 52949, 'o': 49121, 'l': 40995, 'c': 31854, 'd': 28505, 'u': 26372, 'g': 22693, 'm': 22549, 'p': 22249, 'h': 19337, 'b': 15540, 'y': 12652, 'f': 10679, 'k': 8386, 'v': 8000, 'w': 7505, 'x': 2125, 'z': 2058, 'j': 1950, 'q': 1536})"
288 "print(DICT_LETTERS_IN_ORDER)\n",
289 "print(LETTERS_IN_ORDER)"
291 "language": "python",
295 "output_type": "stream",
298 "['s', 'e', 'i', 'a', 'r', 'n', 't', 'o', 'l', 'c', 'd', 'u', 'g', 'm', 'p', 'h', 'b', 'y', 'f', 'k', 'v', 'w', 'x', 'z', 'j', 'q']\n",
299 "['e', 't', 'a', 'o', 'i', 'h', 'n', 's', 'r', 'd', 'l', 'u', 'm', 'w', 'c', 'y', 'f', 'g', 'p', 'b', 'v', 'k', 'x', 'j', 'q', 'z']\n"
310 "for _ in range(1000):\n",
311 " g = Game(random.choice(WORDS), player=PlayerFixedOrder(DICT_LETTERS_IN_ORDER))\n",
317 "language": "python",
321 "output_type": "stream",
334 "class PlayerAdaptiveLength:\n",
335 " def __init__(self, words):\n",
336 " self.all_words = words\n",
337 " self.candidate_words = None\n",
339 " def guess(self, discovered, missed, lives):\n",
340 " if not self.candidate_words:\n",
341 " self.set_ordered_letters(len(discovered))\n",
342 " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
343 " self.ordered_subtract(guessed_letters)\n",
344 " return self.ordered_letters[0]\n",
346 " def ordered_subtract(self, to_remove):\n",
347 " for r in to_remove:\n",
348 " if r in self.ordered_letters:\n",
349 " ri = self.ordered_letters.index(r)\n",
350 " self.ordered_letters = self.ordered_letters[:ri] + self.ordered_letters[ri+1:]\n",
352 " def set_ordered_letters(self, word_len):\n",
353 " self.candidate_words = [w for w in self.all_words if len(w) == word_len]\n",
354 " counts = collections.Counter(l.lower() for l in ''.join(self.candidate_words) if l in string.ascii_letters)\n",
355 " self.ordered_letters = [p[0] for p in counts.most_common()]"
357 "language": "python",
367 "for _ in range(1000):\n",
368 " g = Game(random.choice(WORDS), player=PlayerAdaptiveLength(WORDS))\n",
374 "language": "python",
378 "output_type": "stream",
391 "class PlayerAdaptiveIncludedLetters:\n",
392 " def __init__(self, words):\n",
393 " self.candidate_words = words\n",
395 " def guess(self, discovered, missed, lives):\n",
396 " self.filter_candidate_words(discovered)\n",
397 " self.set_ordered_letters()\n",
398 " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
399 " self.ordered_subtract(guessed_letters)\n",
400 " return self.ordered_letters[0]\n",
402 " def ordered_subtract(self, to_remove):\n",
403 " for r in to_remove:\n",
404 " if r in self.ordered_letters:\n",
405 " ri = self.ordered_letters.index(r)\n",
406 " self.ordered_letters = self.ordered_letters[:ri] + self.ordered_letters[ri+1:]\n",
408 " def filter_candidate_words(self, discovered):\n",
409 " exp = re.compile('^' + ''.join(discovered).replace('_', '.') + '$')\n",
410 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)]\n",
412 " def set_ordered_letters(self):\n",
413 " counts = collections.Counter(l.lower() for l in ''.join(self.candidate_words) if l in string.ascii_letters)\n",
414 " self.ordered_letters = [p[0] for p in counts.most_common()]"
416 "language": "python",
426 "for _ in range(1000):\n",
427 " g = Game(random.choice(WORDS), player=PlayerAdaptiveIncludedLetters(WORDS))\n",
433 "language": "python",
437 "output_type": "stream",
450 "re.match('^[^xaz]*$', 'happy')"
452 "language": "python",
461 "class PlayerAdaptiveExcludedLetters:\n",
462 " def __init__(self, words):\n",
463 " self.candidate_words = words\n",
465 " def guess(self, discovered, missed, lives):\n",
466 " self.filter_candidate_words(missed)\n",
467 " self.set_ordered_letters()\n",
468 " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
469 " self.ordered_subtract(guessed_letters)\n",
470 " return self.ordered_letters[0]\n",
472 " def ordered_subtract(self, to_remove):\n",
473 " for r in to_remove:\n",
474 " if r in self.ordered_letters:\n",
475 " ri = self.ordered_letters.index(r)\n",
476 " self.ordered_letters = self.ordered_letters[:ri] + self.ordered_letters[ri+1:]\n",
478 " def filter_candidate_words(self, missed):\n",
480 " exp = re.compile('^[^' + ''.join(missed) + ']*$')\n",
481 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)]\n",
483 " def set_ordered_letters(self):\n",
484 " counts = collections.Counter(l.lower() for l in ''.join(self.candidate_words) if l in string.ascii_letters)\n",
485 " self.ordered_letters = [p[0] for p in counts.most_common()]"
487 "language": "python",
497 "for _ in range(1000):\n",
498 " g = Game(random.choice(WORDS), player=PlayerAdaptiveExcludedLetters(WORDS))\n",
504 "language": "python",
508 "output_type": "stream",
521 "g.player.candidate_words"
523 "language": "python",
528 "output_type": "pyout",
543 "language": "python",
548 "output_type": "pyout",
561 "class PlayerAdaptivePattern:\n",
562 " def __init__(self, words):\n",
563 " self.candidate_words = words\n",
565 " def guess(self, discovered, missed, lives):\n",
566 " self.filter_candidate_words(discovered, missed)\n",
567 " self.set_ordered_letters()\n",
568 " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
569 " self.ordered_subtract(guessed_letters)\n",
570 " return self.ordered_letters[0]\n",
572 " def ordered_subtract(self, to_remove):\n",
573 " for r in to_remove:\n",
574 " if r in self.ordered_letters:\n",
575 " ri = self.ordered_letters.index(r)\n",
576 " self.ordered_letters = self.ordered_letters[:ri] + self.ordered_letters[ri+1:]\n",
578 " def filter_candidate_words(self, discovered, missed):\n",
580 " exclusion_pattern = '(?!.*[' + ''.join(missed) + '])'\n",
582 " exclusion_pattern = ''\n",
583 " exp = re.compile('^' + exclusion_pattern + ''.join(discovered).replace('_', '.') + '$')\n",
584 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)]\n",
586 " def set_ordered_letters(self):\n",
587 " counts = collections.Counter(l.lower() for l in ''.join(self.candidate_words) if l in string.ascii_letters)\n",
588 " self.ordered_letters = [p[0] for p in counts.most_common()]"
590 "language": "python",
599 "def fcw(words, discovered, missed):\n",
601 " exclusion_pattern = '(?!.*[' + ''.join(missed) + '])'\n",
603 " exclusion_pattern = ''\n",
604 " exp = re.compile('^' + exclusion_pattern + ''.join(discovered).replace('_', '.') + '$')\n",
605 " return [w for w in words if exp.match(w)]"
607 "language": "python",
616 "def fcwp(discovered, missed):\n",
618 " exclusion_pattern = '(?!.*[' + ''.join(missed) + '])'\n",
620 " exclusion_pattern = ''\n",
621 " return '^' + exclusion_pattern + ''.join(discovered).replace('_', '.') + '$'"
623 "language": "python",
632 "fcwp(['h', '_', 'p', '_'], ['x', 'w'])"
634 "language": "python",
639 "output_type": "pyout",
640 "prompt_number": 103,
652 "re.match('^(?!.*[xw])h.p.$', 'hwpe')"
654 "language": "python",
663 "re.match('^(?!.*[xw])h.p.$', 'hape')"
665 "language": "python",
670 "output_type": "pyout",
671 "prompt_number": 104,
673 "<_sre.SRE_Match object; span=(0, 4), match='hape'>"
683 "fcw(WORDS, ['h', '_', 'p', '_'], ['x', 'w', 's'])"
685 "language": "python",
690 "output_type": "pyout",
691 "prompt_number": 108,
693 "['hope', 'hype', 'hypo']"
704 "for _ in range(1000):\n",
705 " g = Game(random.choice(WORDS), player=PlayerAdaptivePattern(WORDS))\n",
711 "language": "python",
715 "output_type": "stream",
731 "for _ in range(1000):\n",
732 " g = Game(random.choice(WORDS), player=PlayerAdaptiveIncludedLetters(WORDS))\n",
738 "language": "python",
742 "output_type": "stream",
750 "output_type": "stream",
758 "output_type": "stream",
766 "output_type": "stream",
770 "1 loops, best of 3: 52.9 s per loop\n"
783 "for _ in range(1000):\n",
784 " g = Game(random.choice(WORDS), player=PlayerAdaptivePattern(WORDS))\n",
790 "language": "python",
794 "output_type": "stream",
802 "output_type": "stream",
810 "output_type": "stream",
818 "output_type": "stream",
822 "1 loops, best of 3: 44.7 s per loop\n"
832 "class PlayerAdaptive:\n",
833 " def __init__(self, words):\n",
834 " self.candidate_words = words\n",
836 " def guess(self, discovered, missed, lives):\n",
837 " self.filter_candidate_words(discovered, missed)\n",
838 " self.set_ordered_letters()\n",
839 " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n",
840 " self.ordered_subtract(guessed_letters)\n",
841 " return self.ordered_letters[0]\n",
843 " def ordered_subtract(self, to_remove):\n",
844 " for r in to_remove:\n",
845 " if r in self.ordered_letters:\n",
846 " ri = self.ordered_letters.index(r)\n",
847 " self.ordered_letters = self.ordered_letters[:ri] + self.ordered_letters[ri+1:]\n",
849 " def filter_candidate_words(self, discovered, missed):\n",
852 " def set_ordered_letters(self):\n",
853 " counts = collections.Counter(l.lower() \n",
854 " for l in ''.join(self.candidate_words) + string.ascii_lowercase \n",
855 " if l in string.ascii_letters)\n",
856 " self.ordered_letters = [p[0] for p in counts.most_common()]"
858 "language": "python",
867 "class PlayerAdaptiveLength(PlayerAdaptive):\n",
868 " def __init__(self, words):\n",
869 " super().__init__(words)\n",
870 " self.word_len = None\n",
871 " self.ordered_letters = None\n",
873 " def filter_candidate_words(self, discovered, missed):\n",
874 " if not self.word_len:\n",
875 " self.word_len = len(discovered)\n",
876 " self.candidate_words = [w for w in self.candidate_words if len(w) == self.word_len]\n",
878 " def set_ordered_letters(self):\n",
879 " if not self.ordered_letters:\n",
880 " super().set_ordered_letters()"
882 "language": "python",
891 "class PlayerAdaptiveIncludedLetters(PlayerAdaptive):\n",
892 " def filter_candidate_words(self, discovered, missed):\n",
893 " exp = re.compile('^' + ''.join(discovered).replace('_', '.') + '$')\n",
894 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)]"
896 "language": "python",
905 "class PlayerAdaptiveExcludedLetters(PlayerAdaptive):\n",
906 " def filter_candidate_words(self, discovered, missed):\n",
908 " exp = re.compile('^[^' + ''.join(missed) + ']*$')\n",
909 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)] "
911 "language": "python",
920 "class PlayerAdaptivePatternNegLookahead(PlayerAdaptive):\n",
921 " def filter_candidate_words(self, discovered, missed):\n",
923 " exclusion_pattern = '(?!.*[' + ''.join(missed) + '])'\n",
925 " exclusion_pattern = ''\n",
926 " exp = re.compile('^' + exclusion_pattern + ''.join(discovered).replace('_', '.') + '$')\n",
927 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)]"
929 "language": "python",
938 "class PlayerAdaptivePattern(PlayerAdaptive):\n",
939 " def filter_candidate_words(self, discovered, missed):\n",
940 " attempted_letters = [l for l in discovered if l != '_'] + missed\n",
941 " if attempted_letters:\n",
942 " exclusion_pattern = '[^' + ''.join(attempted_letters) + ']'\n",
944 " exclusion_pattern = '.'\n",
945 " exp = re.compile('^' + ''.join(discovered).replace('_', exclusion_pattern) + '$')\n",
946 " self.candidate_words = [w for w in self.candidate_words if exp.match(w)]"
948 "language": "python",
960 "for _ in range(1000):\n",
961 " g = Game(random.choice(WORDS), player=PlayerAdaptiveLength(WORDS))\n",
967 "language": "python",
971 "output_type": "stream",
979 "output_type": "stream",
987 "output_type": "stream",
995 "output_type": "stream",
999 "1 loops, best of 3: 24.3 s per loop\n"
1003 "prompt_number": 179
1006 "cell_type": "code",
1012 "for _ in range(1000):\n",
1013 " g = Game(random.choice(WORDS), player=PlayerAdaptiveIncludedLetters(WORDS))\n",
1015 " if g.game_won:\n",
1019 "language": "python",
1023 "output_type": "stream",
1031 "output_type": "stream",
1039 "output_type": "stream",
1047 "output_type": "stream",
1051 "1 loops, best of 3: 52.9 s per loop\n"
1055 "prompt_number": 180
1058 "cell_type": "code",
1064 "for _ in range(1000):\n",
1065 " g = Game(random.choice(WORDS), player=PlayerAdaptiveExcludedLetters(WORDS))\n",
1067 " if g.game_won:\n",
1071 "language": "python",
1075 "output_type": "stream",
1083 "output_type": "stream",
1091 "output_type": "stream",
1099 "output_type": "stream",
1103 "1 loops, best of 3: 11min 14s per loop\n"
1107 "prompt_number": 181
1110 "cell_type": "code",
1116 "for _ in range(1000):\n",
1117 " g = Game(random.choice(WORDS), player=PlayerAdaptivePattern(WORDS))\n",
1119 " if g.game_won:\n",
1123 "language": "python",
1127 "output_type": "stream",
1135 "output_type": "stream",
1143 "output_type": "stream",
1151 "output_type": "stream",
1155 "1 loops, best of 3: 44.1 s per loop\n"
1159 "prompt_number": 197
1162 "cell_type": "code",
1168 "for _ in range(1000):\n",
1169 " g = Game(random.choice(WORDS), player=PlayerAdaptivePatternNegLookahead(WORDS))\n",
1171 " if g.game_won:\n",
1175 "language": "python",
1179 "output_type": "stream",
1187 "output_type": "stream",
1195 "output_type": "stream",
1203 "output_type": "stream",
1207 "1 loops, best of 3: 46 s per loop\n"
1211 "prompt_number": 198
1214 "cell_type": "code",
1217 "for _ in range(1000):\n",
1218 " g = Game(random.choice(WORDS), player=PlayerAdaptivePattern(WORDS))\n",
1220 " if not g.game_won:\n",
1221 " print(g.target, g.discovered, g.wrong_letters)"
1223 "language": "python",
1227 "output_type": "stream",
1230 "rutted ['_', 'u', 't', 't', 'e', 'd'] ['a', 'o', 'i', 'l', 's', 'g', 'b', 'j', 'n', 'p']\n",
1235 "output_type": "stream",
1238 " ['_', 'u', '_'] ['a', 'o', 'e', 'i', 'b', 'g', 'n', 'm', 'p', 't']\n",
1243 "output_type": "stream",
1246 " ['_', 'i', '_', 'e', 's'] ['a', 'm', 'n', 'v', 't', 'r', 'k', 'f', 'p', 'd']\n",
1251 "output_type": "stream",
1254 " ['_', 'a', '_'] ['t', 'p', 'g', 'w', 'd', 'y', 'r', 'm', 'b', 's']\n"
1258 "prompt_number": 217
1261 "cell_type": "code",
1264 "language": "python",