From b3934d614b144fccdb085ebae9158f91b475b63d Mon Sep 17 00:00:00 2001 From: Neil Smith Date: Sun, 11 Jan 2015 12:05:22 +0000 Subject: [PATCH] Added split-candidate player --- SIGNED.md | 39 +- hangman/hangman-split-player.ipynb | 1841 ++++++++++++++++++++++++++++ hangman/hangman.py | 396 ++++++ 3 files changed, 2252 insertions(+), 24 deletions(-) create mode 100644 hangman/hangman-split-player.ipynb create mode 100644 hangman/hangman.py diff --git a/SIGNED.md b/SIGNED.md index e609c44..fb70304 100644 --- a/SIGNED.md +++ b/SIGNED.md @@ -3,19 +3,19 @@ -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 -iQIcBAABAgAGBQJUj2cdAAoJEJPB2e07PgbqZdUP/R4/UJ4CU3o/my4s2frGUfjU -txc034TrbVZsjEHj7NuNtRifzVaIDx4nbTAlA6gGKsh9P4Kk74UM4N7rcTVD65YP -EcTKjwNgiUXBgVJ59f901zYR5QUA4yt7DHmxxuUrO7aFYXd5Du4op1ZcpMgmZwwG -MpWqr5Db0+Tkz4Od43C1EhafiVAucsczNWhxCblkX00dQH8gZlZk3QvR7pRuzOup -FyGHm531Or9gn1QhO9YTFE5el/X0XdDFFjKjtGFQ2+kBPk+W0dqlAnLPTc5K7FgP -/6OnLRVAI/aefr1ZICIqMeJqSO7MnoKYfqf3UUvoeB7MFpOoNN9Qhu6LIiu9R3pN -5Z9bkODE80u6+pycg4lS6kebIZz1K9VNA4Z7nV2ZaJBdPai13lR4JRsCb1iALncf -l0OduJ7lNSkg7PSQ8YBW4olIBMuW1yAVMgQpKM8ecRC/OAPu15N9YW+eQLW3q0cE -9n+1o2hKSwqEMVe4GcrUQYh3tQ+IPtNqgxH2+NlLkUkTX1qg0USgkv8AcVCWiRK0 -6Ek0vrNv+h9FA9SoIZVupiRP6G1yx6/aXW2dGJGEgxIbfotVdI+/XKoiZTqCmhez -MLrtx+mpCGFbNYRePbfFxozoOOPrqcND6iWvEbAL2esWeYm+FJ/ksZ4GzgS3P9MO -0WAw+3p/dXm/NCF5o74X -=TAdh +iQIcBAABAgAGBQJUsmceAAoJEJPB2e07PgbqA+UQAJ/0nqhYyF9IVNIQbO3vUV9Q +XrtNiQ5OmCsDpzq1DQ8CL767tR6HLInHjDcJ6sr9ti3Nl5nPGwww9mDBD4kzGsYU +wilJ4UUvgEO2+hzqH1v84gHeha2R0xWdQ+M3uQBNMD7XCgmrotLIlR8R0N+GDxEH +BwaypN5BBAdHv/DhZRyqDAglgmC4mZBwqyMJxETnh8XSW7bZXgGD234JGo9X3iws +bys42qyMch1oUiOasMwY1/UaT8pbSjhwSEwqU7XaPG+70gfPbWUfVuCj6pr5WVH2 +g82L14dMG079MQf8CTZdWulSXj9733oL8tBRS6NBuFmda8ip20R8CDfabHMgYdqg +bBhGjVIftSjFd4dgCxiZ1kFlkD1B24hdLei5pbbOET44h/QZfvk59/hqRNL1DwYj +gcUV/t8FhWJh1zjO8yddRAwna4cnge6C8zziaWTZ5UZIgkgnDnflFekcgaMmJ9yf +I8b91H8hbGdiNxaZBxQPaadbG49gHmkPyhc1y8T68NViRgb32ryNcvRpY7PCXXBk +rgTZXc0nHCikAJOb4MZrgDCUp2Y5IGhghG1Z6QwbY/g/JtlNeqtQlmdwUUDcOvbs +ALbUQsR3bmbaaSThUHZ69WhtkYseLq9I6i3DNigVLDw2kDz+7tkRoiqR6paQp8Cs +eCTbq7UZA4jo5t6kkUhG +=0kaS -----END PGP SIGNATURE----- ``` @@ -38,17 +38,6 @@ size exec file contents 27510 big-o-chart-2.png a9f40d4499bd43d07bad2b9674b3055a9a3f319349a1256d88a9419f206287d7|56acfe8154f080f9d3186170980a44efd640d4c1748c37c7031f1f20d2f3342e 11222 big-o-chart-smaller.png 5b453ac13c187ea797dbdcf03c2f1941c730a952e285d2afbfde83cf231f0bc3|ba81f54c5daae7c199d9eb66f58db952e52e6b15cf9c69ed34245c4400ffc318 31971 big-o-chart.png 82cea33b61f5af16f928d7037877b31526e532ea62a7cf99ca3761bc4313e4f1|0c43ead93dc010d2fee9724cfda23f2d922cf58931d6258f1da9977fd5bb8cd1 - controlled-assessment/ -21479 arithmetic-quiz-1.ipynb e697dd456bed3eda09fdca4c6974842ac5caa2cabc395a5e8a915566dd1ffb00 -27329 arithmetic-quiz-2.ipynb f88667746026264a7cb7fe0c9160b0911ef8fd20b9a89dda220d5807671be26d -64858 arithmetic-quiz-3.ipynb 7659839bbac84d035d42bd017903898063148833fa79768d78b1b1902eb54b88 -6713 arithmetic-quiz-analysis.py 54d3436f9c09a5a90af593475a049a06bc2ee12ea818b969b7a9699da6de5747 -3995 arithmetic-quiz.py 433575176f8abbc189a269ffbab66ea103c5203fe594fd295d55032029b37b98 -4064 class1.results cf32c1772a9b0252b946645c1a28fce0e1e1baae1214f318aa24974b58a7f045 -4058 class2.results 9bd729d73541984a846fda0f6151f6d413c6e45ca4d136ae22ba2144a3cbb82c -3989 class3.results 1afdc258a0f93fb039cb1c7d0f8c4371a20c4db9bc6a8d8b8f78fc49becaaa9b -260 classes.ini 87126cdcec2366f6f3dddd61869d6c1aff498ea23dca47849a45253439d41faa -23076 names.txt 3731fb885e6eee63d19f0915b05ae9b5529a6bb201056f2f317a3216fafe6433 21947 euler-11.ipynb 81780dca17496751894f582e8691935ee6f94949017fb3135087056489f8ad88 24903 euler-14.ipynb 3652a2be86ec270420431814efa453f8679ad054ae28c015d34232c48dac16bd hangman/ @@ -65,6 +54,8 @@ size exec file contents 9419 hangman-guesser.ipynb d867d7f57b1b59b9cf74f4594fe4b6fd5761e93799292abfb65dcf35381f25e1 181279 hangman-logging.ipynb fe153cdccb5fbdc5dfbd5bd828c17bfde8b479291410a817d6b73a80222acc17 12247 hangman-setter.ipynb bc8d8d7f0bddbe128d273ccd174bbf4ad338771c9159b5b07b262a3e5fede892 +44670 hangman-split-player.ipynb b72ff88817c6cce83d26a701e7e3b17d4332f10fa6cf97520dd7dd6ee6e00464 +10061 hangman.py f800a3e421c73b4174a5127b709ffbc973d4cfc41216aee0718e67e72ca2470c 10890 word_filter_comparison.ipynb 9b80fff718b9ff5620d9441123ebbf60073ea337d14e1e4825ef7860f4e1346b 5286 hangman.html b9a4e8d3f96c57d64dd678fecb1dbd453ee6b415a0bb5a1c232e4e224310eb88 4087 hangman2.html 18e1678e58a1d89f5d2e9fd68de94152f9f34bb2ad93023b6fb69b970bf53a4a diff --git a/hangman/hangman-split-player.ipynb b/hangman/hangman-split-player.ipynb new file mode 100644 index 0000000..a4a9fc8 --- /dev/null +++ b/hangman/hangman-split-player.ipynb @@ -0,0 +1,1841 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:5a2b414ce60f525ddfcbb85f2b57ef6ecf5d08662151337bdc833cd40f541f71" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import re\n", + "import random\n", + "import string\n", + "import collections" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 4 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "WORDS = [w.strip() for w in open('/usr/share/dict/british-english').readlines() \n", + " if re.match(r'^[a-z]*$', w.strip())]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 5 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "LETTER_COUNTS = collections.Counter(l.lower() for l in open('../sherlock-holmes.txt').read() if l in string.ascii_letters)\n", + "LETTERS_IN_ORDER = [p[0] for p in LETTER_COUNTS.most_common()]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 6 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "STARTING_LIVES = 10" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 7 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class Game:\n", + " def __init__(self, target, player=None, lives=STARTING_LIVES):\n", + " self.lives = lives\n", + " self.player = player\n", + " self.target = target\n", + " self.discovered = list('_' * len(target))\n", + " self.wrong_letters = []\n", + " self.game_finished = False\n", + " self.game_won = False\n", + " self.game_lost = False\n", + " \n", + " def find_all(self, letter):\n", + " return [p for p, l in enumerate(self.target) if l == letter]\n", + " \n", + " def update_discovered_word(self, guessed_letter):\n", + " locations = self.find_all(guessed_letter)\n", + " for location in locations:\n", + " self.discovered[location] = guessed_letter\n", + " return self.discovered\n", + " \n", + " def do_turn(self):\n", + " if self.player:\n", + " guess = self.player.guess(self.discovered, self.wrong_letters, self.lives)\n", + " else:\n", + " guess = self.ask_for_guess()\n", + " if guess in self.target:\n", + " self.update_discovered_word(guess)\n", + " else:\n", + " self.lives -= 1\n", + " if guess not in self.wrong_letters:\n", + " self.wrong_letters += [guess]\n", + " if self.lives == 0:\n", + " self.game_finished = True\n", + " self.game_lost = True\n", + " if '_' not in self.discovered:\n", + " self.game_finished = True\n", + " self.game_won = True\n", + " \n", + " def ask_for_guess(self):\n", + " print('Word:', ' '.join(self.discovered), \n", + " ' : Lives =', self.lives, \n", + " ', wrong guesses:', ' '.join(sorted(self.wrong_letters)))\n", + " guess = input('Enter letter: ').strip().lower()[0]\n", + " return guess\n", + " \n", + " def play_game(self):\n", + " while not self.game_finished:\n", + " self.do_turn()\n", + " if not self.player:\n", + " self.report_on_game()\n", + " return self.game_won\n", + " \n", + " def report_on_game(self):\n", + " if self.game_won:\n", + " print('You won! The word was', self.target)\n", + " else:\n", + " print('You lost. The word was', self.target)\n", + " return self.game_won" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 8 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "DICT_COUNTS = collections.Counter(l.lower() for l in open('/usr/share/dict/british-english').read() if l in string.ascii_letters)\n", + "DICT_LETTERS_IN_ORDER = [p[0] for p in DICT_COUNTS.most_common()]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 9 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class PlayerAdaptiveNoRegex:\n", + " def __init__(self, words):\n", + " self.candidate_words = words\n", + " \n", + " def guess(self, discovered, missed, lives):\n", + " self.filter_candidate_words(discovered, missed)\n", + " self.set_ordered_letters()\n", + " guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters]\n", + " return [l for l in self.ordered_letters if l not in guessed_letters][0]\n", + " \n", + " def filter_candidate_words(self, discovered, missed):\n", + " pass\n", + " \n", + " def set_ordered_letters(self):\n", + " counts = collections.Counter(l.lower() \n", + " for l in ''.join(self.candidate_words) + string.ascii_lowercase \n", + " if l in string.ascii_letters)\n", + " self.ordered_letters = [p[0] for p in counts.most_common()]\n", + "\n", + " def match(self, pattern, target, excluded=None):\n", + " if not excluded:\n", + " excluded = ''\n", + " if len(pattern) != len(target):\n", + " return False\n", + " for m, c in zip(pattern, target):\n", + " if m == '_' and c not in excluded:\n", + " # true\n", + " pass\n", + " elif m != '_' and m == c:\n", + " # true\n", + " pass\n", + " else:\n", + " return False\n", + " return True " + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class PlayerAdaptiveLengthNoRegex(PlayerAdaptiveNoRegex):\n", + " def __init__(self, words):\n", + " super().__init__(words)\n", + " self.word_len = None\n", + " self.ordered_letters = None\n", + " \n", + " def filter_candidate_words(self, discovered, missed):\n", + " if not self.word_len:\n", + " self.word_len = len(discovered)\n", + " self.candidate_words = [w for w in self.candidate_words if len(w) == self.word_len]\n", + " \n", + " def set_ordered_letters(self):\n", + " if not self.ordered_letters:\n", + " super().set_ordered_letters()" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 11 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class PlayerAdaptiveIncludedLettersNoRegex(PlayerAdaptiveNoRegex):\n", + " def filter_candidate_words(self, discovered, missed):\n", + " self.candidate_words = [w for w in self.candidate_words if self.match(discovered, w)]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 12 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class PlayerAdaptiveExcludedLettersNoRegex(PlayerAdaptiveNoRegex):\n", + " def filter_candidate_words(self, discovered, missed):\n", + " if missed:\n", + " empty_target = '_' * len(discovered)\n", + " self.candidate_words = [w for w in self.candidate_words if self.match(empty_target, w, missed)] " + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 13 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class PlayerAdaptivePatternNoRegex(PlayerAdaptiveNoRegex):\n", + " def filter_candidate_words(self, discovered, missed):\n", + " attempted_letters = [l for l in discovered if l != '_'] + missed\n", + " self.candidate_words = [w for w in self.candidate_words if self.match(discovered, w, attempted_letters)]" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 14 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%%timeit\n", + "\n", + "wins = 0\n", + "for _ in range(1000):\n", + " g = Game(random.choice(WORDS), player=PlayerAdaptivePatternNoRegex(WORDS))\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "993\n", + "992" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "994" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "991" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "1 loops, best of 3: 48.2 s per loop\n" + ] + } + ], + "prompt_number": 15 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "len([w for w in WORDS if 'r' in w])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 21, + "text": [ + "31398" + ] + } + ], + "prompt_number": 21 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "len([w for w in WORDS if 'r' not in w])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 22, + "text": [ + "31458" + ] + } + ], + "prompt_number": 22 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "letter_diffs = []\n", + "for l in string.ascii_lowercase:\n", + " n = 0\n", + " for w in WORDS:\n", + " if l in w:\n", + " n += 1\n", + " else:\n", + " n -=1\n", + " letter_diffs += [(l, abs(n))]\n", + "sorted(letter_diffs, key=lambda p: p[1])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 19, + "text": [ + "[('r', 60),\n", + " ('a', 98),\n", + " ('n', 3720),\n", + " ('t', 4728),\n", + " ('i', 6136),\n", + " ('s', 8662),\n", + " ('o', 12788),\n", + " ('l', 17878),\n", + " ('e', 22936),\n", + " ('c', 26102),\n", + " ('d', 26368),\n", + " ('u', 30282),\n", + " ('g', 33260),\n", + " ('p', 35960),\n", + " ('m', 37904),\n", + " ('h', 41134),\n", + " ('b', 44784),\n", + " ('y', 47462),\n", + " ('f', 49626),\n", + " ('v', 52502),\n", + " ('k', 53616),\n", + " ('w', 53688),\n", + " ('x', 60010),\n", + " ('q', 60816),\n", + " ('j', 60938),\n", + " ('z', 61244)]" + ] + } + ], + "prompt_number": 19 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "def letter_diff(l):\n", + " return abs(sum(1 if l in w else -1 for w in WORDS))\n", + "\n", + "letter_diffs = [(l, letter_diff(l)) \n", + " for l in string.ascii_lowercase]\n", + "sorted(letter_diffs, key=lambda p: p[1])" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 23, + "text": [ + "[('r', 60),\n", + " ('a', 98),\n", + " ('n', 3720),\n", + " ('t', 4728),\n", + " ('i', 6136),\n", + " ('s', 8662),\n", + " ('o', 12788),\n", + " ('l', 17878),\n", + " ('e', 22936),\n", + " ('c', 26102),\n", + " ('d', 26368),\n", + " ('u', 30282),\n", + " ('g', 33260),\n", + " ('p', 35960),\n", + " ('m', 37904),\n", + " ('h', 41134),\n", + " ('b', 44784),\n", + " ('y', 47462),\n", + " ('f', 49626),\n", + " ('v', 52502),\n", + " ('k', 53616),\n", + " ('w', 53688),\n", + " ('x', 60010),\n", + " ('q', 60816),\n", + " ('j', 60938),\n", + " ('z', 61244)]" + ] + } + ], + "prompt_number": 23 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "class PlayerAdaptiveSplit(PlayerAdaptivePatternNoRegex):\n", + " def set_ordered_letters(self):\n", + " def letter_diff(l):\n", + " return abs(sum(1 if l in w else -1 for w in self.candidate_words))\n", + " possible_letters = set(''.join(self.candidate_words))\n", + " # if len(self.candidate_words) > 1:\n", + " letter_diffs = [(l, letter_diff(l)) for l in possible_letters]\n", + " self.ordered_letters = [p[0] for p in sorted(letter_diffs, key=lambda p: p[1])]\n", + " # else:\n", + " # self.ordered_letters = list(self.candidate_words[0])" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 71 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g = Game(random.choice(WORDS), player=PlayerAdaptiveSplit(WORDS))\n", + "g.play_game()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 72, + "text": [ + "True" + ] + } + ], + "prompt_number": 72 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g.target" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 73, + "text": [ + "'baste'" + ] + } + ], + "prompt_number": 73 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g.discovered" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 74, + "text": [ + "['b', 'a', 's', 't', 'e']" + ] + } + ], + "prompt_number": 74 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g.wrong_letters" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 75, + "text": [ + "['c', 'h']" + ] + } + ], + "prompt_number": 75 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%%timeit\n", + "\n", + "wins = 0\n", + "for _ in range(1000):\n", + " g = Game(random.choice(WORDS), player=PlayerAdaptiveSplit(WORDS))\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "983\n", + "982" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "981" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "987" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "1 loops, best of 3: 55.6 s per loop\n" + ] + } + ], + "prompt_number": 78 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p=PlayerAdaptiveSplit(WORDS)" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 54 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "dsc = ['_'] * len('recognition')\n", + "dsc" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 55, + "text": [ + "['_', '_', '_', '_', '_', '_', '_', '_', '_', '_', '_']" + ] + } + ], + "prompt_number": 55 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.guess(dsc, [], 10)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 56, + "text": [ + "'o'" + ] + } + ], + "prompt_number": 56 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "len(p.candidate_words)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 57, + "text": [ + "5027" + ] + } + ], + "prompt_number": 57 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.guess(['_', '_', '_', 'o', '_', '_', '_', '_', '_', 'o', '_'], [], 10)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 58, + "text": [ + "'c'" + ] + } + ], + "prompt_number": 58 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.candidate_words" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 59, + "text": [ + "['association',\n", + " 'defoliation',\n", + " 'deformation',\n", + " 'denominator',\n", + " 'deportation',\n", + " 'excoriation',\n", + " 'exhortation',\n", + " 'exportation',\n", + " 'importation',\n", + " 'information',\n", + " 'liposuction',\n", + " 'negotiation',\n", + " 'recognition',\n", + " 'recondition',\n", + " 'reformation',\n", + " 'subornation']" + ] + } + ], + "prompt_number": 59 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.guess(['_', '_', 'c', 'o', '_', '_', '_', '_', '_', 'o', '_'], [], 10)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 60, + "text": [ + "'a'" + ] + } + ], + "prompt_number": 60 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.candidate_words" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 61, + "text": [ + "['excoriation', 'recognition', 'recondition']" + ] + } + ], + "prompt_number": 61 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.guess(['_', '_', 'c', 'o', '_', '_', '_', '_', '_', 'o', '_'], ['a'], 9)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 62, + "text": [ + "'d'" + ] + } + ], + "prompt_number": 62 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.candidate_words" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 63, + "text": [ + "['recognition', 'recondition']" + ] + } + ], + "prompt_number": 63 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.guess(['_', '_', 'c', 'o', '_', '_', '_', '_', '_', 'o', '_'], ['a', 'd'], 8)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 64, + "text": [ + "'r'" + ] + } + ], + "prompt_number": 64 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "p.candidate_words" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 65, + "text": [ + "['recognition']" + ] + } + ], + "prompt_number": 65 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g = Game('recognition', player=PlayerAdaptiveSplit(WORDS))\n", + "g.play_game()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 67, + "text": [ + "True" + ] + } + ], + "prompt_number": 67 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g.discovered" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 68, + "text": [ + "['r', 'e', 'c', 'o', 'g', 'n', 'i', 't', 'i', 'o', 'n']" + ] + } + ], + "prompt_number": 68 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g.lives" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 69, + "text": [ + "8" + ] + } + ], + "prompt_number": 69 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%%timeit\n", + "\n", + "wins = 0\n", + "for _ in range(10000):\n", + " g = Game(random.choice(WORDS), player=PlayerAdaptiveSplit(WORDS))\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "9857\n", + "9862" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "9844" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "9860" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "1 loops, best of 3: 9min 15s per loop\n" + ] + } + ], + "prompt_number": 79 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%%timeit\n", + "\n", + "wins = 0\n", + "for _ in range(10000):\n", + " g = Game(random.choice(WORDS), player=PlayerAdaptivePatternNoRegex(WORDS))\n", + " g.play_game()\n", + " if g.game_won:\n", + " wins += 1\n", + "print(wins)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "9934\n", + "9916" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "9921" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "9932" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "1 loops, best of 3: 8min 12s per loop\n" + ] + } + ], + "prompt_number": 81 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "for w in random.sample(WORDS, 5000):\n", + " gp = Game(w, player=PlayerAdaptivePatternNoRegex(WORDS))\n", + " gp.play_game()\n", + " gs = Game(w, player=PlayerAdaptiveSplit(WORDS))\n", + " gs.play_game()\n", + " if not gp.game_won and not gs.game_won:\n", + " print('Both:::::', gp.target, 'Pattern:', '[' + ' '.join(gp.discovered) + ']', ''.join(gp.wrong_letters), \n", + " ':: Split:', '[' + ' '.join(gs.discovered) + ']', ''.join(gs.wrong_letters))\n", + " if not gp.game_won and gs.game_won:\n", + " print('Pattern::', gp.target, '[' + ' '.join(gp.discovered) + ']', ''.join(gp.wrong_letters))\n", + " if gp.game_won and not gs.game_won:\n", + " print('Split::::', gs.target, '[' + ' '.join(gs.discovered) + ']', ''.join(gs.wrong_letters))" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Split:::: cut [_ _ t] aoeiybgnpj\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " reviewers [_ _ _ _ _ _ _ _ _] taoldgnupc\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " piped [_ i _ e d] saolrnkvbm\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " joying Pattern: [_ o _ i n g] esapwdtrkm :: Split: [_ o _ _ n _] srdatpwhvk\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " duck Pattern: [_ u _ _] esoailfrnm :: Split: [_ u _ _] esaorlnfmt\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " bum [b _ _] aoeiyrtgns\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " jibing [_ i _ i n g] esrldmpkvt\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " begged [_ _ _ _ _ d] srlnoauipt\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " bucked [b u _ _ e d] aoilstfgpr\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " bunk [_ u n k] esoailfrgp\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " dumping [_ u _ p _ _ g] srlaoecjhb\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " meekest [_ _ _ _ _ s _] iaournlpdw\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " wove [_ o v e] arnldptkmc\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " finking [_ _ _ _ _ _ g] srlaoeutpd\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fan Pattern: [_ a _] tpgwdmrbys :: Split: [_ a n] tpgwmbyrdv\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " hug [_ u g] aoeibpdmtj\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " feminism [_ _ _ _ _ _ _ _] ratlogdcuh\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " effect [_ _ _ _ c t] srdnaioulp\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " puff [_ u f f] esaorlnmgc\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " skivvies [_ _ _ _ _ _ _ _] ratlogdcuh\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " miffing [_ _ _ _ _ _ g] srlaoeutpd\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " dung Pattern: [_ u n _] esoailfrkt :: Split: [_ u n g] esaorlkthb\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " gibed [_ i _ e d] saomlprkvn\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " rubs [_ u b s] eaoicpdtnh\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " bat [_ a t] ecpsofmvhr\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " boobs [_ o o _ s] eatdklmpfn\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " yon Pattern: [_ o n] atbdwpiecs :: Split: [_ o n] atbdwpiesc\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " firs Pattern: [f i _ s] eaoptgbdmn :: Split: [_ i _ s] eaotpgbdmn\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " quipping [_ _ _ _ _ _ _ g] ratloscedh\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " ragging [r a _ _ _ n _] seotzclpdm\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fuddled [_ u _ _ l _ _] sraoibzmgc\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " yack Pattern: [_ a c k] esolrntmpj :: Split: [_ a c k] esrlntmjhb\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " vanning [_ a _ _ _ _ g] srltpbwmck\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fizziest [_ _ _ _ _ _ _ t] rauonlphdk\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " rug [_ u g] aoeibpdmtj\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fixed Pattern: [_ i _ e d] saomlprkvn :: Split: [_ i _ e d] saolrnkvbm\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " mop [_ o p] atbdwchlsf\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " separatists [_ _ p _ _ _ _ _ _ _ _] oldcgnymbx\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " miff [_ _ _ _] esaoutnlrc\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " putty [p u _ _ y] seaoimlnrf\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " mice [_ i _ e] aorlnvtdkw\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fixing Pattern: [_ i _ i n g] esrldmpkvt :: Split: [_ _ _ _ n _] srdaoeulbp\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " gaged [_ a _ e d] srwctpmzbh\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fag [_ a g] tpjnhrlbsw\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " woeful [_ o _ _ _ _] srdnaictyb\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " pauper [_ a _ _ _ r] sntlmidkvj\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " faxing Pattern: [f a _ i n g] esrwtlcdkz :: Split: [_ a _ _ n _] srdtwmpczh\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " yoking Pattern: [_ o k i n g] esapwdtrcj :: Split: [_ o k _ n _] srdatpwhvj\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " cox Pattern: [_ o _] atbdwpnsge :: Split: [_ o _] atbdwpngse\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " doff [_ o _ _] esalrnctyb\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " puck Pattern: [_ u _ _] esoailfrnm :: Split: [_ u _ _] esaorlnfmt\n", + "Pattern::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " tuck [_ u _ _] esoailfrnm\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " kerchiefs [_ _ _ c _ _ _ _ _] taoldgnupv\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " members [_ _ _ _ _ r s] aoiutdpcgv\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " foxing Pattern: [_ o _ i n g] esapwdtrkm :: Split: [_ o _ _ n _] srdatpwhvk\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " anaesthetises [_ _ _ _ _ _ _ _ _ _ _ _ _] clgmpdvuro\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " versifies [_ _ _ _ _ _ _ _ _] taoldgnupc\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " babes Pattern: [_ a _ e s] rltngcdkzv :: Split: [_ a _ e s] rltngcdkzv\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " huffing [_ u f f _ _ g] srlaoecpbm\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " weeper [_ _ _ p _ r] saioutdhbk\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " buffering [_ u _ _ _ _ _ _ g] taoldsphmv\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " dills [_ _ l l s] eaountghrb\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " wigging [_ _ g g _ _ g] srlaouejpd\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " indenting [_ _ d _ _ t _ _ _] aoscrlbvhf\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " morn [_ o r n] esaltchbpw\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " buff Pattern: [_ u f f] esoailgcpd :: Split: [_ u f f] esaorlnmgc\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " zero [_ e r _] satlbnhpyg\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " jazz Pattern: [_ a _ _] esolrntmky :: Split: [_ a _ _] esrlntmkdw\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " k [_] geopdtuyiz\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " find [_ _ n d] esaoutkhrb\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " happy [_ a _ _ y] sentdrglcz\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fibbing [_ _ _ _ _ _ g] srlaoeutpd\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " wifeliest [_ _ _ _ _ _ _ _ t] nroacmhpgu\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " r Pattern: [_] giecposdwk :: Split: [_] geopdtuyiz\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " businesses [_ _ _ _ n _ _ _ _ _] olatdgcphr\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fife Pattern: [_ i _ e] aorlndvtpm :: Split: [_ i _ e] aorlnvtdkw\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " fix Pattern: [_ i _] aoeptdngsb :: Split: [_ i _] aoetndpgbs\n", + "Both:::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " mil Pattern: [_ i _] aoeptdngsb :: Split: [_ i _] aoetndpgbs\n", + "Split::::" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " wetted [_ _ t t _ d] srlnoauipj\n" + ] + } + ], + "prompt_number": 90 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "gs = Game('businesses', player=PlayerAdaptiveSplit(WORDS))" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 91 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g = Game('feminism', player=PlayerAdaptiveSplit(WORDS))\n", + "while not g.game_finished:\n", + " guess = g.player.guess(g.discovered, g.wrong_letters, g.lives)\n", + " print(g.target, '(' + str(g.lives) + ')', \n", + " '[' + ' '.join(g.discovered) + ']', ''.join(g.wrong_letters), \n", + " ';', len(g.player.candidate_words), 'candidate words')\n", + " print('Guess = ', guess)\n", + " g.do_turn()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "feminism (10) [_ _ _ _ _ _ _ _] ; 10328 candidate words\n", + "Guess = r\n", + "feminism" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " (9) [_ _ _ _ _ _ _ _] r ; 5102 candidate words\n", + "Guess = a\n", + "feminism (8) [_ _ _ _ _ _ _ _] ra ; 2673 candidate words\n", + "Guess = t\n", + "feminism" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " (7) [_ _ _ _ _ _ _ _] rat ; 1466 candidate words\n", + "Guess = l\n", + "feminism (6) [_ _ _ _ _ _ _ _] ratl ; 704 candidate words\n", + "Guess = o\n", + "feminism (5) [_ _ _ _ _ _ _ _] ratlo ; 359 candidate words\n", + "Guess = g\n", + "feminism (4) [_ _ _ _ _ _ _ _] ratlog ; 189 candidate words\n", + "Guess = d\n", + "feminism (3) [_ _ _ _ _ _ _ _] ratlogd ; 94 candidate words\n", + "Guess = c\n", + "feminism (2) [_ _ _ _ _ _ _ _] ratlogdc ; 50 candidate words\n", + "Guess = u\n", + "feminism (1) [_ _ _ _ _ _ _ _] ratlogdcu ; 31 candidate words\n", + "Guess = h\n" + ] + } + ], + "prompt_number": 170 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g = Game('feminism', player=PlayerAdaptivePatternNoRegex(WORDS))\n", + "while not g.game_finished:\n", + " guess = g.player.guess(g.discovered, g.wrong_letters, g.lives)\n", + " print(g.target, '(' + str(g.lives) + ')', \n", + " '[' + ' '.join(g.discovered) + ']', ''.join(g.wrong_letters), \n", + " ';', len(g.player.candidate_words), 'candidate words')\n", + " print('Guess = ', guess)\n", + " g.do_turn()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "feminism (10) [_ _ _ _ _ _ _ _] ; 10328 candidate words\n", + "Guess = e\n", + "feminism" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + " (10) [_ e _ _ _ _ _ _] ; 540 candidate words\n", + "Guess = i\n", + "feminism (10) [_ e _ i _ i _ _] ; 42 candidate words\n", + "Guess = n\n", + "feminism (10) [_ e _ i n i _ _] ; 3 candidate words\n", + "Guess = s\n", + "feminism (10) [_ e _ i n i s _] ; 3 candidate words\n", + "Guess = f\n", + "feminism (10) [f e _ i n i s _] ; 2 candidate words\n", + "Guess = m\n" + ] + } + ], + "prompt_number": 172 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "g.player.candidate_words" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 171, + "text": [ + "['beehives',\n", + " 'enmeshes',\n", + " 'evenness',\n", + " 'expenses',\n", + " 'feminine',\n", + " 'feminism',\n", + " 'fineness',\n", + " 'finesses',\n", + " 'finishes',\n", + " 'fishwife',\n", + " 'inkiness',\n", + " 'keenness',\n", + " 'meekness',\n", + " 'minibike',\n", + " 'minimise',\n", + " 'missives',\n", + " 'ninepins',\n", + " 'penknife',\n", + " 'sexiness',\n", + " 'sheepish',\n", + " 'shimmies',\n", + " 'shinnies',\n", + " 'skivvies',\n", + " 'sphinxes',\n", + " 'vivifies',\n", + " 'vixenish',\n", + " 'whimseys',\n", + " 'whimsies',\n", + " 'whinnies',\n", + " 'whiskeys',\n", + " 'whiskies']" + ] + } + ], + "prompt_number": 171 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [], + "language": "python", + "metadata": {}, + "outputs": [] + } + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/hangman/hangman.py b/hangman/hangman.py new file mode 100644 index 0000000..4725c9d --- /dev/null +++ b/hangman/hangman.py @@ -0,0 +1,396 @@ + +# coding: utf-8 + +# In[4]: + +import re +import random +import string +import collections + + +# In[5]: + +WORDS = [w.strip() for w in open('/usr/share/dict/british-english').readlines() + if re.match(r'^[a-z]*$', w.strip())] + + +# In[6]: + +LETTER_COUNTS = collections.Counter(l.lower() for l in open('../sherlock-holmes.txt').read() if l in string.ascii_letters) +LETTERS_IN_ORDER = [p[0] for p in LETTER_COUNTS.most_common()] + + +# In[7]: + +STARTING_LIVES = 10 + + +# In[8]: + +class Game: + def __init__(self, target, player=None, lives=STARTING_LIVES): + self.lives = lives + self.player = player + self.target = target + self.discovered = list('_' * len(target)) + self.wrong_letters = [] + self.game_finished = False + self.game_won = False + self.game_lost = False + + def find_all(self, letter): + return [p for p, l in enumerate(self.target) if l == letter] + + def update_discovered_word(self, guessed_letter): + locations = self.find_all(guessed_letter) + for location in locations: + self.discovered[location] = guessed_letter + return self.discovered + + def do_turn(self): + if self.player: + guess = self.player.guess(self.discovered, self.wrong_letters, self.lives) + else: + guess = self.ask_for_guess() + if guess in self.target: + self.update_discovered_word(guess) + else: + self.lives -= 1 + if guess not in self.wrong_letters: + self.wrong_letters += [guess] + if self.lives == 0: + self.game_finished = True + self.game_lost = True + if '_' not in self.discovered: + self.game_finished = True + self.game_won = True + + def ask_for_guess(self): + print('Word:', ' '.join(self.discovered), + ' : Lives =', self.lives, + ', wrong guesses:', ' '.join(sorted(self.wrong_letters))) + guess = input('Enter letter: ').strip().lower()[0] + return guess + + def play_game(self): + while not self.game_finished: + self.do_turn() + if not self.player: + self.report_on_game() + return self.game_won + + def report_on_game(self): + if self.game_won: + print('You won! The word was', self.target) + else: + print('You lost. The word was', self.target) + return self.game_won + + +# In[9]: + +DICT_COUNTS = collections.Counter(l.lower() for l in open('/usr/share/dict/british-english').read() if l in string.ascii_letters) +DICT_LETTERS_IN_ORDER = [p[0] for p in DICT_COUNTS.most_common()] + + +# In[10]: + +class PlayerAdaptiveNoRegex: + def __init__(self, words): + self.candidate_words = words + + def guess(self, discovered, missed, lives): + self.filter_candidate_words(discovered, missed) + self.set_ordered_letters() + guessed_letters = [l.lower() for l in discovered + missed if l in string.ascii_letters] + return [l for l in self.ordered_letters if l not in guessed_letters][0] + + def filter_candidate_words(self, discovered, missed): + pass + + def set_ordered_letters(self): + counts = collections.Counter(l.lower() + for l in ''.join(self.candidate_words) + string.ascii_lowercase + if l in string.ascii_letters) + self.ordered_letters = [p[0] for p in counts.most_common()] + + def match(self, pattern, target, excluded=None): + if not excluded: + excluded = '' + if len(pattern) != len(target): + return False + for m, c in zip(pattern, target): + if m == '_' and c not in excluded: + # true + pass + elif m != '_' and m == c: + # true + pass + else: + return False + return True + + +# In[11]: + +class PlayerAdaptiveLengthNoRegex(PlayerAdaptiveNoRegex): + def __init__(self, words): + super().__init__(words) + self.word_len = None + self.ordered_letters = None + + def filter_candidate_words(self, discovered, missed): + if not self.word_len: + self.word_len = len(discovered) + self.candidate_words = [w for w in self.candidate_words if len(w) == self.word_len] + + def set_ordered_letters(self): + if not self.ordered_letters: + super().set_ordered_letters() + + +# In[12]: + +class PlayerAdaptiveIncludedLettersNoRegex(PlayerAdaptiveNoRegex): + def filter_candidate_words(self, discovered, missed): + self.candidate_words = [w for w in self.candidate_words if self.match(discovered, w)] + + +# In[13]: + +class PlayerAdaptiveExcludedLettersNoRegex(PlayerAdaptiveNoRegex): + def filter_candidate_words(self, discovered, missed): + if missed: + empty_target = '_' * len(discovered) + self.candidate_words = [w for w in self.candidate_words if self.match(empty_target, w, missed)] + + +# In[14]: + +class PlayerAdaptivePatternNoRegex(PlayerAdaptiveNoRegex): + def filter_candidate_words(self, discovered, missed): + attempted_letters = [l for l in discovered if l != '_'] + missed + self.candidate_words = [w for w in self.candidate_words if self.match(discovered, w, attempted_letters)] + + +# In[15]: + +get_ipython().run_cell_magic('timeit', '', '\nwins = 0\nfor _ in range(1000):\n g = Game(random.choice(WORDS), player=PlayerAdaptivePatternNoRegex(WORDS))\n g.play_game()\n if g.game_won:\n wins += 1\nprint(wins)') + + +# In[21]: + +len([w for w in WORDS if 'r' in w]) + + +# In[22]: + +len([w for w in WORDS if 'r' not in w]) + + +# In[19]: + +letter_diffs = [] +for l in string.ascii_lowercase: + n = 0 + for w in WORDS: + if l in w: + n += 1 + else: + n -=1 + letter_diffs += [(l, abs(n))] +sorted(letter_diffs, key=lambda p: p[1]) + + +# In[23]: + +def letter_diff(l): + return abs(sum(1 if l in w else -1 for w in WORDS)) + +letter_diffs = [(l, letter_diff(l)) + for l in string.ascii_lowercase] +sorted(letter_diffs, key=lambda p: p[1]) + + +# In[71]: + +class PlayerAdaptiveSplit(PlayerAdaptivePatternNoRegex): + def set_ordered_letters(self): + def letter_diff(l): + return abs(sum(1 if l in w else -1 for w in self.candidate_words)) + possible_letters = set(''.join(self.candidate_words)) + # if len(self.candidate_words) > 1: + letter_diffs = [(l, letter_diff(l)) for l in possible_letters] + self.ordered_letters = [p[0] for p in sorted(letter_diffs, key=lambda p: p[1])] + # else: + # self.ordered_letters = list(self.candidate_words[0]) + + +# In[72]: + +g = Game(random.choice(WORDS), player=PlayerAdaptiveSplit(WORDS)) +g.play_game() + + +# In[73]: + +g.target + + +# In[74]: + +g.discovered + + +# In[75]: + +g.wrong_letters + + +# In[78]: + +get_ipython().run_cell_magic('timeit', '', '\nwins = 0\nfor _ in range(1000):\n g = Game(random.choice(WORDS), player=PlayerAdaptiveSplit(WORDS))\n g.play_game()\n if g.game_won:\n wins += 1\nprint(wins)') + + +# In[54]: + +p=PlayerAdaptiveSplit(WORDS) + + +# In[55]: + +dsc = ['_'] * len('recognition') +dsc + + +# In[56]: + +p.guess(dsc, [], 10) + + +# In[57]: + +len(p.candidate_words) + + +# In[58]: + +p.guess(['_', '_', '_', 'o', '_', '_', '_', '_', '_', 'o', '_'], [], 10) + + +# In[59]: + +p.candidate_words + + +# In[60]: + +p.guess(['_', '_', 'c', 'o', '_', '_', '_', '_', '_', 'o', '_'], [], 10) + + +# In[61]: + +p.candidate_words + + +# In[62]: + +p.guess(['_', '_', 'c', 'o', '_', '_', '_', '_', '_', 'o', '_'], ['a'], 9) + + +# In[63]: + +p.candidate_words + + +# In[64]: + +p.guess(['_', '_', 'c', 'o', '_', '_', '_', '_', '_', 'o', '_'], ['a', 'd'], 8) + + +# In[65]: + +p.candidate_words + + +# In[67]: + +g = Game('recognition', player=PlayerAdaptiveSplit(WORDS)) +g.play_game() + + +# In[68]: + +g.discovered + + +# In[69]: + +g.lives + + +# In[79]: + +get_ipython().run_cell_magic('timeit', '', '\nwins = 0\nfor _ in range(10000):\n g = Game(random.choice(WORDS), player=PlayerAdaptiveSplit(WORDS))\n g.play_game()\n if g.game_won:\n wins += 1\nprint(wins)') + + +# In[81]: + +get_ipython().run_cell_magic('timeit', '', '\nwins = 0\nfor _ in range(10000):\n g = Game(random.choice(WORDS), player=PlayerAdaptivePatternNoRegex(WORDS))\n g.play_game()\n if g.game_won:\n wins += 1\nprint(wins)') + + +# In[90]: + +for w in random.sample(WORDS, 5000): + gp = Game(w, player=PlayerAdaptivePatternNoRegex(WORDS)) + gp.play_game() + gs = Game(w, player=PlayerAdaptiveSplit(WORDS)) + gs.play_game() + if not gp.game_won and not gs.game_won: + print('Both:::::', gp.target, 'Pattern:', '[' + ' '.join(gp.discovered) + ']', ''.join(gp.wrong_letters), + ':: Split:', '[' + ' '.join(gs.discovered) + ']', ''.join(gs.wrong_letters)) + if not gp.game_won and gs.game_won: + print('Pattern::', gp.target, '[' + ' '.join(gp.discovered) + ']', ''.join(gp.wrong_letters)) + if gp.game_won and not gs.game_won: + print('Split::::', gs.target, '[' + ' '.join(gs.discovered) + ']', ''.join(gs.wrong_letters)) + + +# In[91]: + +gs = Game('businesses', player=PlayerAdaptiveSplit(WORDS)) + + +# In[170]: + +g = Game('feminism', player=PlayerAdaptiveSplit(WORDS)) +while not g.game_finished: + guess = g.player.guess(g.discovered, g.wrong_letters, g.lives) + print(g.target, '(' + str(g.lives) + ')', + '[' + ' '.join(g.discovered) + ']', ''.join(g.wrong_letters), + ';', len(g.player.candidate_words), 'candidate words') + print('Guess = ', guess) + g.do_turn() + + +# In[172]: + +g = Game('feminism', player=PlayerAdaptivePatternNoRegex(WORDS)) +while not g.game_finished: + guess = g.player.guess(g.discovered, g.wrong_letters, g.lives) + print(g.target, '(' + str(g.lives) + ')', + '[' + ' '.join(g.discovered) + ']', ''.join(g.wrong_letters), + ';', len(g.player.candidate_words), 'candidate words') + print('Guess = ', guess) + g.do_turn() + + +# In[171]: + +g.player.candidate_words + + +# In[ ]: + + + -- 2.34.1