{ "cells": [ { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "
Peter Norvig
29 December 2015
\n", "\n", "# Refactoring a Crossword Game Program\n", "\n", "In my [CS 212 class](https://www.udacity.com/course/design-of-computer-programs--cs212) on Udacity, the [most complex lesson](https://www.udacity.com/course/viewer#!/c-cs212/l-48634860) involved a crossword game program (for games such as Scrabble® and Words with Friends®). The program was developed *incrementally*. First I asked \"what words can be made with a rack of seven letters?\", then I asked \"how can you place words onto a single row?\", and finally, I, with the help of the students, developed a program to find the highest scoring play anywhere on the board. This approach made for a good sequence of exercises, each building on the previous one. But the code ended up being overly complicated—it accumlated [technical debt](https://en.wikipedia.org/wiki/Technical_debt)—because it kept around ideas from each iteration.\n", "\n", "In this notebook I will refactor the program to pay off the debt.\n", "\n", "# Vocabulary\n", "\n", "Our program uses these concepts:\n", "\n", "* **Dictionary**: A set of all legal words.\n", "* **Word**: a string of letters that form a word. Words in the dictionary are all uppercase.\n", "* **Tile**: a letter (or a blank) that can be played on the board to form words. \n", "* **Blank**: a tile with no letter on it; the player who places it on the board gets to choose which letter it will represent. (It scores no points.)\n", "* **Rack**: a collection of up to seven tiles that a player may use to make words.\n", "* **Board**: a grid of squares onto which players play tiles to make words. \n", "* **Square**: a location on the board; a square can hold one tile. (The variable `s` will stand for a square number, and `sq` for the contents of a square.)\n", "* **Bonus**: some squares give you bonus scores: double or triple letter or word scores.\n", "* **Play**: a play consists of placing some tiles on the board to form a continuous string of letters in one direction (across or down), such that only valid words are formed, and such that one of the letters is placed on an anchor square.\n", "* **Anchor square**: Either the center start square or a square that is adjacent to a tile previously played on the board. \n", "* **Direction:** Every play must be in either the `ACROSS` or `DOWN` direction. (The variable `dir` stands for a direction.)\n", "* **Cross word**: a word formed in the other direction from a play. For example, a play forms a word in the across direction, and in doing so, places a letter that extends a word in the down direction. This new extended *cross word* must be in the dictionary.\n", "* **Score**: the points awarded for a play, consisting of the sum of the word scores for each word made (the main word and possibly any cross words), plus a bingo bonus if all seven letters are used. \n", "* **Word score**: Each word scores the sum of the letter scores for each tile (either placed by the player or already on the board but part of the word) times the word bonus score. The word bonus score starts at 1, and is multiplied by 2 for each double word square and 3 for each triple word square covered by a tile on this play.\n", "* **Letter score**: The letter score is the value on the letter tile (for example, 1 for `A` and 10 for `Q`) times the letter bonus score. The letter bonus is 2 when a tile is first placed on a double letter square (or the center star) and 3 when first placed on a triple letter square; it is 1 for a tile already on the board, or for a new tile played on a non-letter-bonus square. The letter score for a blank tile is always zero.\n", "* **Bingo**: a bonus gained by using all seven tiles in one play. In Words with Friends® the bingo bonus is 35; in Scrabble® it is 50.\n", "* **Game**: players take turns making plays until one player has no more tiles, or neither player can make a play. \n", "* **Replenish**: After making a play, the player's rack is replenished with tiles until the player has 7 tiles or until the bag of tiles is empty.\n", "* **Prefix**: a string of zero or more letters that starts some word in the dictionary. Not a concept that has to do\n", "with the *rules* of the game; it will be important in our *algorithm* that finds valid plays.\n", "\n", "This notebook uses these imports:\n", "\n" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "import random\n", "from collections import defaultdict, namedtuple\n", "from IPython.display import HTML, display" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "\n", "# Dictionary and Words\n", "\n", "We will represent the dictionary as a set of words. A word is an uppercase string of letters, like `'WORD'`. There are several standard dictionaries used by different communities of players; we will use the ENABLE dictionary—we can cache a local copy with this shell command:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "! [ -e enable1.txt ] || curl -O http://norvig.com/ngrams/enable1.txt" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Now we can define a word and load the dictionary:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def Word(w) -> str: return w.strip().upper()\n", "\n", "DICTIONARY = {Word(w) for w in open('enable1.txt')}\n", "\n", "def is_word(word) -> bool: \n", " \"Is this a legal word in the dictionary?\"\n", " return word.upper() in DICTIONARY" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "172820" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(DICTIONARY)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "['SARCOIDOSES',\n", " 'ARGLES',\n", " 'GRATIS',\n", " 'DISENTHRALS',\n", " 'ANIMATING',\n", " 'POLYTONALLY',\n", " 'DERMATITISES',\n", " 'UNMEMORABLY',\n", " 'NUCLEATE',\n", " 'PRELUDER']" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "list(DICTIONARY)[:10]" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "'WORD' in DICTIONARY" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Tiles, Blanks, and Racks\n", "\n", "We'll represent a tile as a one-character string, like `'W'`. We'll represent a rack as a string of tiles, usually of length 7, such as `'EELRTTS'`. (I also considered a `collections.Counter` to represent a rack, but felt that `str` was simpler, and with the rack size limited to 7, efficiency was not a major issue.)\n", "\n", "The blank tile causes some complications. We'll represent a blank in a player's rack as the underscore character, `'_'`. But once the blank is played on the board, it must be used as if it was a specific letter. However, it doesn't score the points of the letter. I chose to use the lowercase version of the letter to represent this. That way, we know what letter the blank is standing for, and we can distingush between scoring and non-scoring tiles. For example, `'EELRTT_'` is a rack that contains a blank; and `'LETTERs'` is a word played on the board that uses the blank to stand for the letter `S`. \n", "\n", "We'll define `letters` to give all the distinct letters that can be made by a rack, and `remove` to remove letters from a rack (after they have been played)." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "BLANK = '_' # The blank tile (as it appears in the rack)\n", "cat = ''.join # Function to concatenate strings\n", "\n", "def letters(rack) -> str:\n", " \"All the distinct letters in a rack (including lowercase if there is a blank).\"\n", " if BLANK in rack:\n", " return cat(set(rack.replace(BLANK, ''))) + 'abcdefghijklmnopqrstuvwxyz'\n", " else:\n", " return cat(set(rack))\n", " \n", "def remove(tiles, rack) -> str:\n", " \"Return a copy of rack with the given tile(s) removed.\"\n", " for tile in tiles:\n", " if tile.islower(): tile = BLANK\n", " rack = rack.replace(tile, '', 1)\n", " return rack" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "is_word('LETTERs')" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'RLEST'" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "letters('LETTERS')" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'LRETabcdefghijklmnopqrstuvwxyz'" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "letters('EELRTT_')" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'LTER'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remove('SET', 'LETTERS')" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'LE'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "remove('TREaT', 'LETTER_') " ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# The Board, Squares, Directions, and Bonus Squares\n", "\n", "In the [previous version](https://www.udacity.com/course/viewer#!/c-cs212/l-48634860) of this program, the board was a two-dimensional matrix, and a square on the board was denoted by a `(row, col)` pair of indexes. There's nothing wrong with that representation, but for this version we will choose a different representation that is simpler in most ways:\n", "\n", "* The board is represented as a one-dimensional list of squares.\n", "* The default board is 15×15 squares, but\n", "we will include a *border* around the outside, making the board of size 17×17. \n", "* Squares are denoted by integer indexes, from 0 to 288.\n", "* To move in the `ACROSS` direction from one square to the next, increment the square index by 1.\n", "* To move in the `DOWN` direction from one square to the next, increment the square index by 17.\n", "* The border squares are filled with a symbol, `OFF`, indicating that they are off the board.\n", "The advantage of the border is that the code never has to check if it is at the edge of the board; it can always\n", "look at the neighboring square without fear of indexing off the end of the board.\n", "* Each square on the board is initially filled by a symbol indicating the bonus value of the square. When a tile is placed on a square,\n", "the tile replaces the bonus value.\n", "\n", "How will we implement this? We'll define `Board` as a subclass of `list` and give it two additional attributes: \n", "\n", "- `down`: the increment to move in the down direction; 17 for a standard board.\n", "- `directions`: the four increments to move to any neighboring square; `(1, 17, -1, -17)` in a standard board.\n", "\n", "Jupyter/Ipython notebooks have a special convention for displaying objects in HTML. We will adopt it as a method of `Board`:\n", "\n", "- `_repr_html_`: return a string of HTML that displays the board as a table." ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "ACROSS = 1 # The 'across' direction; 'down' depends on the size of the board\n", "OFF = '#' # A square that is off the board\n", "SL, DL, TL, STAR, DW, TW = EMPTY = '.:;*-=' # Single/double/triple letter; star, double/triple word bonuses\n", "\n", "Square = int # Squares are implemented as integer indexes.\n", "Direction = int # Directions are implemented as integer increments\n", "\n", "class Board(list):\n", " \"\"\"A Board is a (linear) list of squares, each a single character.\n", " Note that board[s + down] is directly below board[s].\"\"\"\n", "\n", " def __init__(self, squares):\n", " list.__init__(self, squares)\n", " down = int(len(squares)**0.5)\n", " self.down = down\n", " self.directions = (ACROSS, down, -ACROSS, -down)\n", " \n", " def _repr_html_(self) -> str: return board_html(self)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "We'll define `WWF` as the standard board for Words with Friends®." ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "WWF = Board(\"\"\"\n", "# # # # # # # # # # # # # # # # #\n", "# . . . = . . ; . ; . . = . . . #\n", "# . . : . . - . . . - . . : . . #\n", "# . : . . : . . . . . : . . : . #\n", "# = . . ; . . . - . . . ; . . = #\n", "# . . : . . . : . : . . . : . . #\n", "# . - . . . ; . . . ; . . . - . #\n", "# ; . . . : . . . . . : . . . ; #\n", "# . . . - . . . * . . . - . . . #\n", "# ; . . . : . . . . . : . . . ; #\n", "# . - . . . ; . . . ; . . . - . #\n", "# . . : . . . : . : . . . : . . #\n", "# = . . ; . . . - . . . ; . . = #\n", "# . : . . : . . . . . : . . : . #\n", "# . . : . . - . . . - . . : . . #\n", "# . . . = . . ; . ; . . = . . . #\n", "# # # # # # # # # # # # # # # # #\n", "\"\"\".split())" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "assert len(WWF) == 17 * 17" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Displaying the Board in HTML\n", "\n", "I want to diaplay the board in HTML, as a table with different background colors for the bonus squares; and gold-colored letter tiles. I also want to display the point values for each letter on the tiles; I'll use a `defaultdict` of `{letter: int}` named `POINTS` for that. (It has been a source of frustration for me that different environments (Jupyter on local machine, nbviewer, github, etc.) choose to ignore certain HTML/CSS directives. I use both CSS `background-color` and the deprecated HTML `bgcolor` in an attempt to get around this.)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def board_html(board) -> str:\n", " \"An HTML representation of the board.\"\n", " size = board.down - 2\n", " squares = [square_html(sq) for sq in board if sq != OFF]\n", " row = ('' + '{}' * size)\n", " return ('' + row * size + '
').format(*squares)\n", " \n", "board_colors = {\n", " DL: ('lightblue', 66, 'DL'),\n", " TL: ('lightgreen', 66, 'TL'),\n", " DW: ('lightcoral', 66, 'DW'),\n", " TW: ('orange', 66, 'TW'),\n", " SL: ('whitesmoke', 66, ''),\n", " STAR: ('violet', 100, '✭')}\n", "\n", "def square_html(sq) -> str:\n", " \"An HTML representation of a square.\"\n", " color, size, text = board_colors.get(sq, ('gold', 120, sq))\n", " if text.isupper(): \n", " text = '{}{}'.format(text, POINTS.get(text, ''))\n", " style = (\"background-color:{}; font-size:{}%; width:25px; height:25px; \"\n", " \"text-align:center; padding:0px; border-style:solid; border-width: thin\")\n", " return ('{}').format(color, color, size, text)\n", "\n", "POINTS = defaultdict(int, \n", " A=1, B=3, C=3, D=2, E=1, F=4, G=2, H=4, I=1, J=8, K=5, L=1, M=3, \n", " N=1, O=1, P=3, Q=10, R=1, S=1, T=1, U=1, V=4, W=4, X=8, Y=4, Z=10)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDW
TLDLDLTL
DWDW
TLDLDLTL
DWTLTLDW
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DLDWDWDL
TWTLTLTW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '*',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "WWF" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Plays\n", "\n", "A `Play` describes the placement of tiles on the board. We will implement `Play` as a named tuple of four components:\n", "- `start`: the index number of the square that holds the first letter in the word.\n", "- `dir`: the direction, with 1 indicating `ACROSS` and `board.down` (normally, 17) indicating `DOWN`.\n", "- `letters`: the letters of the word, in order, as a `str`. Blanks are lowercase. Some letters are from the rack; some may have been on the board.\n", "- `rack`: the letters that would remain in the player's rack after making this play. Not strictly necessary as part of the play, but useful information.\n", "\n", "The function `make_play` returns a new board with the play made on it. It does not do any checking to see if the play follows the rules." ] }, { "cell_type": "code", "execution_count": 18, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "Play = namedtuple('Play', 'start, dir, letters, rack')\n", "\n", "def make_play(board, play) -> Board:\n", " \"Make the play on a copy of board and return the copy.\"\n", " copy = Board(board)\n", " end = play.start + len(play.letters) * play.dir\n", " copy[play.start:end:play.dir] = play.letters\n", " return copy" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Example Board\n", "\n", "Let's test out what we've done so far. I'll put some words on a board, which I will call `board`:" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2DWB3E1C3DWI1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'B',\n", " 'E',\n", " '.',\n", " 'C',\n", " '-',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 19, "metadata": {}, "output_type": "execute_result" } ], "source": [ "DOWN = WWF.down\n", "plays = {Play(145, DOWN, 'ENTER', ''),\n", " Play(144, ACROSS, 'BE', ''),\n", " Play(138, DOWN, 'GAVE', ''),\n", " Play(158, DOWN, 'MUSES', ''),\n", " Play(172, ACROSS, 'VIRULeNT', ''),\n", " Play(213, ACROSS, 'RED', ''),\n", " Play(198, ACROSS, 'LYTHE', ''),\n", " Play(147, DOWN, 'CHILDREN', ''),\n", " Play(164, ACROSS, 'HEARD', ''),\n", " Play(117, DOWN, 'BRIDLES', ''),\n", " Play(131, ACROSS, 'TOUR', '')}\n", "\n", "board = Board(WWF)\n", "for play in plays:\n", " board = make_play(board, play)\n", "board" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Strategy for Finding Legal Plays\n", "\n", "This is our strategy for finding all possible legal plays on a board:\n", "\n", "- Find all *anchor squares* on the board. An anchor square is a square that is adjacent to a letter on the board—every legal move must place a letter on an anchor square. (On the game's first play, there are no letters on the board, and the `STAR` square in the center counts as the only anchor square.)\n", "- Using just the letters in the rack, find all *prefixes* of words in the dictionary. For example, with the rack `ABC`, we find that `B`, `BA`, and `BAC` are all prefixes of the word `BACK` (and the rack contains other prefixes of other words as well).\n", "- For each anchor square and for both directions (across and down):\n", " - Try each prefix before the anchor (that is, to the left or above the anchor). Don't allow a prefix to extend to another anchor or off the board. That means we won't have to worry about *cross words* for the prefix. If there are already letters on the board before the anchor point, use them as the prefix rather than prefixes from the rack.\n", " - Starting at the anchor, march forward one square at a time, trying to fill empty squares with each possible letter from the rack that forms a valid word prefix. If the march forward hits letters that are already on the board, make sure they form a valid prefix too. Also check that any cross words are valid words. When we make a complete word (with an empty or `OFF` square ahead), yield the play that made the word.\n", " \n", "So, each legal play will have a prefix of zero or more letters, followed by one letter from the rack covering an anchor square, followed by zero or more additional letters, which can be from the rack or already on the board." ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Prefixes\n", "\n", "Here we define the set of all prefixes of all words in the dictionary:" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def dict_prefixes(dictionary) -> set:\n", " \"The set of all prefixes of each word in a dictionary.\"\n", " return {word[:i] for word in dictionary for i in range(len(word))}\n", "\n", "PREFIXES = dict_prefixes(DICTIONARY)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "276374" ] }, "execution_count": 21, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(PREFIXES)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "That's too many prefixes to look at; let's try a smaller example below. Note that the empty string is a prefix, and we include `HELP` because it is a prefix of `HELPER`, but we don't include `HELPER`, because there is nothing we can add to it to make a word in this dictionary:" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "{'', 'H', 'HE', 'HEL', 'HELL', 'HELP', 'HELPE'}" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dict_prefixes({'HELLO', 'HELP', 'HELPER'})" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "The function `rack_prefixes` gives the set of prefixes that can be made just from the letters in the rack. Most of the work is done by `extend_prefixes`, which accumulates a set of prefixes into `results`:" ] }, { "cell_type": "code", "execution_count": 23, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def rack_prefixes(rack) -> set: \n", " \"All word prefixes that can be made by the rack.\"\n", " return extend_prefixes('', rack, set())\n", "\n", "def extend_prefixes(prefix, rack, results) -> set:\n", " if prefix.upper() in PREFIXES:\n", " results.add(prefix)\n", " for L in letters(rack):\n", " extend_prefixes(prefix+L, remove(L, rack), results)\n", " return results" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "{'', 'A', 'AB', 'AC', 'B', 'BA', 'BAC', 'C', 'CA', 'CAB'}" ] }, "execution_count": 24, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rack = 'ABC'\n", "rack_prefixes(rack)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "The number of prefixes in a rack is usually on the order of a hundred, unless there is a blank in the rack:" ] }, { "cell_type": "code", "execution_count": 25, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "155" ] }, "execution_count": 25, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(rack_prefixes('LETTERS'))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "1590" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" } ], "source": [ "len(rack_prefixes('LETTER_'))" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Anchor Squares\n", "\n", "An anchor square is either the star in the middle of the board, or an empty square that is adjacent to a letter:" ] }, { "cell_type": "code", "execution_count": 27, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def is_anchor(board, s) -> bool:\n", " \"Is this square next to a letter already on the board? (Or is it a '*')?\"\n", " return (board[s] == STAR or\n", " board[s] in EMPTY and any(board[s + d].isalpha() for d in board.directions))\n", "\n", "def all_anchors(board) -> list:\n", " \"A list of all anchor squares on the board.\"\n", " return [s for s in range(len(board)) if is_anchor(board, s)]" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "[144]" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "all_anchors(WWF)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Plays on Example Board\n", "\n", "Let's work through the process of finding plays on the example `board`. First, we'll find all the anchors:" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "53" ] }, "execution_count": 29, "metadata": {}, "output_type": "execute_result" } ], "source": [ "anchors = all_anchors(board)\n", "len(anchors)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "To visualize these anchors, we'll make each one be a star, on a copy of `board`:" ] }, { "cell_type": "code", "execution_count": 30, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLB3
TLDLT1O1U1R1
G2DWB3E1C3I1
A1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1I1L1
E1S1E1L1Y4T1H4E1
TWE1R1E1D2S1
DLS1R1DL
DLDWE1DL
TWTLTLN1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '*',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '*',\n", " '*',\n", " '*',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '*',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '*',\n", " '*',\n", " '.',\n", " '*',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '*',\n", " 'G',\n", " '*',\n", " '-',\n", " '*',\n", " '.',\n", " '*',\n", " 'B',\n", " 'E',\n", " '*',\n", " 'C',\n", " '*',\n", " '*',\n", " '*',\n", " 'I',\n", " '#',\n", " '#',\n", " '*',\n", " 'A',\n", " '*',\n", " '*',\n", " 'M',\n", " '*',\n", " '*',\n", " '*',\n", " 'N',\n", " '*',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '*',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " '*',\n", " 'I',\n", " '*',\n", " '*',\n", " '*',\n", " 'L',\n", " '#',\n", " '#',\n", " '*',\n", " 'E',\n", " '*',\n", " '*',\n", " 'S',\n", " '*',\n", " '*',\n", " '*',\n", " 'E',\n", " '*',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '*',\n", " '.',\n", " '*',\n", " 'E',\n", " '*',\n", " '.',\n", " '*',\n", " 'R',\n", " 'E',\n", " 'D',\n", " '*',\n", " '*',\n", " '*',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '*',\n", " 'S',\n", " '*',\n", " '.',\n", " '.',\n", " '*',\n", " '*',\n", " 'R',\n", " '*',\n", " '.',\n", " ':',\n", " '*',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '*',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '*',\n", " 'E',\n", " '*',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '*',\n", " 'N',\n", " '*',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 30, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board2 = Board(board)\n", "for a in anchors:\n", " board2[a] = STAR\n", " \n", "board2" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Now we'll define a rack, and find all the prefixes for the rack:" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "88" ] }, "execution_count": 31, "metadata": {}, "output_type": "execute_result" } ], "source": [ "rack = 'ABCHKNQ'\n", "\n", "prefixes = rack_prefixes(rack)\n", "len(prefixes)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "' BANK KANB ANC HACKN BAN CAB Q CHAQ CHA CANK BACK ABH BHAN BA ANCH ANK ABN KHAN ACKN AC HACK AB AH CAK HAB BH HANK KAB AQ HAN ACQ QA ACK KAN KAH KHA BAC HANC HAK NACH KH CH BANC AHC BACKH KB BHA ACN BAK HACKB ANKH BANKC HAC AN KBA NAB CHAN CAH QAN KA A KAC BACH BHAK CHAB C ACH KACH H CA BANQ NA HA BAH AK B N NAC KN CAN CN NAK KNA KNAC K CHAK ANH'" ] }, "execution_count": 32, "metadata": {}, "output_type": "execute_result" } ], "source": [ "' '.join(prefixes)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "We won't go through all the anchor/prefix combinations; we'll just pick one: the anchor above the `M` in `MUSES`:" ] }, { "cell_type": "code", "execution_count": 33, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2DWB3E1C3DWI1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " '-',\n", " '*',\n", " '.',\n", " '.',\n", " 'B',\n", " 'E',\n", " '.',\n", " 'C',\n", " '-',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 33, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board3 = Board(board)\n", "anchor = board3.index('M') - board3.down\n", "board3[anchor] = STAR\n", "board3" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "There's only room for prefixes of length 0 or 1, because anything longer than that would hit the anchor to the right of the `G` in `GAVE`; to avoid duplication of effort, we only allow words to run into other anchors on the right, not the left. Let's try the 1-letter prefix `B` first:" ] }, { "cell_type": "code", "execution_count": 34, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2B3B3E1C3DWI1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " 'B',\n", " '*',\n", " '.',\n", " '.',\n", " 'B',\n", " 'E',\n", " '.',\n", " 'C',\n", " '-',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board3[anchor - 1] = 'B'\n", "board3" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Now we can start to march forward. On the anchor square we can place any letter from the rack that makes a valid prefix, and that also turns `.MUSES` into a valid word. There's only one such letter, `A`:" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2B3A1B3E1C3DWI1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " 'B',\n", " 'A',\n", " '.',\n", " '.',\n", " 'B',\n", " 'E',\n", " '.',\n", " 'C',\n", " '-',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 35, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board3[anchor] = 'A'\n", "assert 'BA' in PREFIXES and is_word('A' + 'MUSES')\n", "board3" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "We can continue marching forward, trying letters from the rack that form valid prefixes. Let's try the combination `CK`. That spells the word `BACK`, but we can't count it as a legal play, because we've hit two adjacent letters, `BE`, that are already on the board. We check that `BACKBE` forms a valid prefix:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2B3A1C3K5B3E1C3DWI1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " 'B',\n", " 'A',\n", " 'C',\n", " 'K',\n", " 'B',\n", " 'E',\n", " '.',\n", " 'C',\n", " '-',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 36, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board3[anchor + 1:anchor + 3] = 'CK'\n", "assert 'BACKBE' in PREFIXES\n", "board3" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "But `BACKBE` is not a word, so continue to the next empty square in the row, where we can choose an `N`:" ] }, { "cell_type": "code", "execution_count": 37, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2B3A1C3K5B3E1N1C3DWI1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " 'B',\n", " 'A',\n", " 'C',\n", " 'K',\n", " 'B',\n", " 'E',\n", " 'N',\n", " 'C',\n", " '-',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board3[anchor + 5] = 'N'\n", "assert 'BACKBENC' in PREFIXES\n", "board3" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Finally, continue to the next square (a double word square), and place an `H`, which completes a word, `BACKBENCH`, and simultaneously makes a cross word, `THE`:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2B3A1C3K5B3E1N1C3H4I1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " 'B',\n", " 'A',\n", " 'C',\n", " 'K',\n", " 'B',\n", " 'E',\n", " 'N',\n", " 'C',\n", " 'H',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "board3[anchor + 7] = 'H'\n", "assert is_word('BACKBENCH') and is_word('THE')\n", "board3" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "We would record this play, and backtrack to consider other letters for this and other prefix/anchor combinations. Now let's code this up! \n", "\n", "# Code for Finding All Plays\n", "\n", "The function `all_plays` generates all legal plays by first trying all prefix plays, and then trying to extend each one, one letter at a time. (Note that it also generates the empty play, because a player always has the option of passing.)" ] }, { "cell_type": "code", "execution_count": 39, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def all_plays(board, rack):\n", " \"\"\"Generate all plays that can be played on board with this rack.\n", " Try placing every possible prefix before every anchor point; \n", " then extend one letter at a time, looking for valid plays.\"\"\"\n", " anchors = all_anchors(board)\n", " prefixes = rack_prefixes(rack)\n", " yield Play(0, 1, '', rack) # The empty play (no letters, no points)\n", " for anchor in anchors:\n", " for dir in (ACROSS, board.down):\n", " for play in prefix_plays(prefixes, board, anchor, dir, rack):\n", " yield from extend_play(board, play)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Note the syntax `yield from`, new in Python 3.3: \"`yield from c`\" is similar to \"`for x in c: yield x`\". \n", "\n", "Now for the function `prefix_plays`, which returns a list of all partial plays consisting of a prefix placed before the anchor. Note that these are not *legal* plays; they are *partial* plays, some of which will end up being extended into legal plays. \n", "\n", "There are two cases: if there are letters on the board immediately before the anchor, then those letters form the only allowable prefix. If not, we can use any prefix from the rack up to `maxlen`, which is the number of empty squares that do not run into another anchor, nor off the board." ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def prefix_plays(prefixes, board, anchor, dir, rack) -> list:\n", " \"Return all Plays of a prefix to the left/above anchor.\"\n", " if board[anchor-dir].isalpha(): # Prefix already on the board; only 1 prefix\n", " start = scan_letters(board, anchor, -dir)\n", " return [Play(start, dir, cat(board[start:anchor:dir]), rack)]\n", " else: # Prefixes from rack fit in space before anchor\n", " maxlen = (anchor - scan_to_anchor(board, anchor, -dir)) // dir\n", " return [Play(anchor - len(prefix) * dir, dir, prefix, remove(prefix, rack))\n", " for prefix in prefixes if len(prefix) <= maxlen]" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Now `extend_play` takes a partial play, determines the square, `s`, that is one square past the end of the play, and tries all possible letters there. If adding a letter forms a valid prefix (and also does not form an invalid cross word), then we continue on (by calling `extend_play` recursively). If adding the letter forms a valid word, we yield the play." ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def extend_play(board, play):\n", " \"Explore all ways of adding to end of play; return ones that form full words.\"\n", " s = play.start + play.dir * len(play.letters)\n", " if board[s] == OFF: return\n", " cword = crossword(board, s, play.dir)\n", " possible_letters = board[s].upper() if board[s].isalpha() else letters(play.rack)\n", " for L in possible_letters:\n", " prefix2 = play.letters + L\n", " if prefix2.upper() in PREFIXES and valid_crossword(cword, L):\n", " rack2 = play.rack if board[s].isalpha() else remove(L, play.rack)\n", " play2 = Play(play.start, play.dir, prefix2, rack2)\n", " if is_word(prefix2) and not board[s + play.dir].isalpha():\n", " yield play2\n", " yield from extend_play(board, play2)\n", "\n", "def scan_letters(board, s, dir) -> Square:\n", " \"Return the last square number going from s in dir that is a letter.\"\n", " while board[s + dir].isalpha():\n", " s += dir\n", " return s\n", "\n", "def scan_to_anchor(board, s, dir) -> Square:\n", " \"Return the last square number going from s in dir that is not an anchor nor off board.\"\n", " while board[s + dir] != OFF and not is_anchor(board, s + dir):\n", " s += dir\n", " return s" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Crosswords\n", "\n", "If adding a letter in, say, the `ACROSS` direction also adds on to a word in the `DOWN` direction, then we need to make sure that this *cross word* is also valid. The function `crossword` finds the cross word at square `s` and returns it with a `'.'` indicating the empty square where the new letter will be placed, so we would get `'.MUSES'` and `'T.E'` for the two crosswords in the `'BACKBENCH'` play." ] }, { "cell_type": "code", "execution_count": 42, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def crossword(board, s, dir) -> str:\n", " \"\"\"The word that intersects s in the other direction from dir.\n", " Use '.' for the one square that is missing a letter.\"\"\"\n", " def canonical(L): return L if L.isalpha() else '.'\n", " d = other(dir, board)\n", " start = scan_letters(board, s, -d)\n", " end = scan_letters(board, s, d)\n", " return cat(canonical(board[s]) for s in range(start, end+d, d))\n", "\n", "def valid_crossword(cword, L) -> bool:\n", " \"Is placing letter L valid (with respective to the crossword)?\"\n", " return len(cword) == 1 or cword.replace('.', L).upper() in DICTIONARY\n", "\n", "def other(dir, board) -> Direction:\n", " \"The other direction (across/down) on the board.\"\n", " return board.down if dir == ACROSS else ACROSS" ] }, { "cell_type": "code", "execution_count": 43, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'.MUSES'" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "crossword(board, anchor, ACROSS)" ] }, { "cell_type": "code", "execution_count": 44, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'T.E'" ] }, "execution_count": 44, "metadata": {}, "output_type": "execute_result" } ], "source": [ "crossword(board, anchor + 7, ACROSS)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "The function `valid_crossword` checks if replacing the empty square with a specific letter will form a valid word:" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 45, "metadata": {}, "output_type": "execute_result" } ], "source": [ "valid_crossword('.MUSES', 'A')" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "We can now see all the prefix plays for the anchor square just above `MUSES` (square number 141):" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "[Play(start=141, dir=1, letters='', rack='ABCHKNQ'),\n", " Play(start=140, dir=1, letters='Q', rack='ABCHKN'),\n", " Play(start=140, dir=1, letters='A', rack='BCHKNQ'),\n", " Play(start=140, dir=1, letters='C', rack='ABHKNQ'),\n", " Play(start=140, dir=1, letters='H', rack='ABCKNQ'),\n", " Play(start=140, dir=1, letters='B', rack='ACHKNQ'),\n", " Play(start=140, dir=1, letters='N', rack='ABCHKQ'),\n", " Play(start=140, dir=1, letters='K', rack='ABCHNQ')]" ] }, "execution_count": 46, "metadata": {}, "output_type": "execute_result" } ], "source": [ "prefix_plays(rack_prefixes(rack), board, anchor, ACROSS, rack)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "And we can see all the ways to extend the play of `'B'` there:" ] }, { "cell_type": "code", "execution_count": 47, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "{Play(start=140, dir=1, letters='BA', rack='CHKNQ'),\n", " Play(start=140, dir=1, letters='BACKBENCH', rack='Q'),\n", " Play(start=140, dir=1, letters='BAH', rack='CKNQ'),\n", " Play(start=140, dir=1, letters='BAN', rack='CHKQ')}" ] }, "execution_count": 47, "metadata": {}, "output_type": "execute_result" } ], "source": [ "set(extend_play(board, Play(anchor - 1, ACROSS, 'B', 'ACHKNQ')))" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Scoring\n", "\n", "Now we'll show how to count up the points made by a play. The score is the sum of the word score for the play, plus a bingo score if all seven letters are used, plus the sum of the word scores for any cross words. The word score is the sum of the letter scores (where each letter score may be doubled or tripled by a bonus square when the letter is first played on the square), all multiplied by any word bonus(es) encountered by the newly-placed letters." ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def score(board, play) -> int:\n", " \"The number of points scored by making this play on the board.\"\n", " return (word_score(board, play) \n", " + bingo(board, play) \n", " + sum(word_score(board, cplay) \n", " for cplay in cross_plays(board, play)))\n", "\n", "def word_score(board, play) -> int:\n", " \"Points for a single word, counting word- and letter-bonuses.\"\n", " total, word_bonus = 0, 1\n", " for (s, L) in enumerate_play(play):\n", " sq = board[s]\n", " word_bonus *= (3 if sq == TW else 2 if sq == DW else 1)\n", " total += POINTS[L] * (3 if sq == TL else 2 if sq == DL else 1)\n", " return word_bonus * total\n", "\n", "def bingo(board, play) -> int:\n", " \"A bonus for using 7 letters from the rack.\"\n", " return BINGO if (play.rack == '' and letters_played(board, play) == 7) else 0\n", "\n", "BINGO = 35 # 35 for Words with Friends; 50 for Scrabble" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Here are the various helper functions:" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def letters_played(board, play) -> int:\n", " \"The number of letters played from the rack.\"\n", " return sum(board[s] in EMPTY for (s, L) in enumerate_play(play))\n", " \n", "def enumerate_play(play) -> list:\n", " \"List (square_number, letter) pairs for each tile in the play.\"\n", " return [(play.start + i * play.dir, L) \n", " for (i, L) in enumerate(play.letters)]\n", " \n", "def cross_plays(board, play):\n", " \"Generate all plays for words that cross this play.\"\n", " cross = other(play.dir, board)\n", " for (s, L) in enumerate_play(play):\n", " if board[s] in EMPTY and (board[s-cross].isalpha() or board[s+cross].isalpha()):\n", " start, end = scan_letters(board, s, -cross), scan_letters(board, s, cross)\n", " before, after = cat(board[start:s:cross]), cat(board[s+cross:end+cross:cross])\n", " yield Play(start, cross, before + L + after, play.rack)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "What should the `BACKBENCH` play score? The word covers two double-word bonuses, but no letter bonuses. The sum of the letter point values is 3+1+3+5+3+1+1+3+4 = 24, and 24×2×2 = 96. The cross word `AMUSES` scores 8, and `THE` is on a double word bonus, so it scores 6×2 = 12. There is one letter remaining in the rack, so no bingo, just a total score of 96 + 8 + 12 = 116." ] }, { "cell_type": "code", "execution_count": 50, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "116" ] }, "execution_count": 50, "metadata": {}, "output_type": "execute_result" } ], "source": [ "score(board, Play(start=anchor - 1, dir=ACROSS, letters='BACKBENCH', rack='Q'))" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "We can find the highest scoring play by enumerating all plays and taking the one with the maximum score:" ] }, { "cell_type": "code", "execution_count": 51, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def highest_scoring_play(board, rack) -> Play: \n", " \"Return the Play that gives the most points.\"\n", " return max(all_plays(board, rack), key=lambda play: score(board, play))" ] }, { "cell_type": "code", "execution_count": 52, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "Play(start=140, dir=1, letters='BACKBENCH', rack='Q')" ] }, "execution_count": 52, "metadata": {}, "output_type": "execute_result" } ], "source": [ "highest_scoring_play(board, rack)" ] }, { "cell_type": "code", "execution_count": 53, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDWB3
TLDLDLT1O1U1R1
G2B3A1C3K5B3E1N1C3H4I1
TLA1M3N1H4E1A1R1D2
V4I1R1U1L1eN1T1TLI1DWL1
E1DLS1DLE1L1Y4T1H4E1
TWTLE1DWR1E1D2TLS1
DLS1R1DL
DLDWDWE1DL
TWTLTLN1TW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'B',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'T',\n", " 'O',\n", " 'U',\n", " 'R',\n", " '#',\n", " '#',\n", " '.',\n", " 'G',\n", " '.',\n", " 'B',\n", " 'A',\n", " 'C',\n", " 'K',\n", " 'B',\n", " 'E',\n", " 'N',\n", " 'C',\n", " 'H',\n", " '.',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " ';',\n", " 'A',\n", " '.',\n", " '.',\n", " 'M',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " '.',\n", " 'H',\n", " 'E',\n", " 'A',\n", " 'R',\n", " 'D',\n", " '#',\n", " '#',\n", " '.',\n", " 'V',\n", " 'I',\n", " 'R',\n", " 'U',\n", " 'L',\n", " 'e',\n", " 'N',\n", " 'T',\n", " ';',\n", " 'I',\n", " '.',\n", " '.',\n", " '-',\n", " 'L',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ':',\n", " '.',\n", " 'E',\n", " '.',\n", " 'L',\n", " 'Y',\n", " 'T',\n", " 'H',\n", " 'E',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'E',\n", " '.',\n", " '.',\n", " '-',\n", " 'R',\n", " 'E',\n", " 'D',\n", " ';',\n", " '.',\n", " '.',\n", " 'S',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'S',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'R',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'E',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " 'N',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "make_play(board, Play(start=140, dir=1, letters='BACKBENCH', rack='Q'))" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Playing a Game\n", "\n", "Now let's play a complete game. We start with the standard bag of 100 tiles:" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "100" ] }, "execution_count": 54, "metadata": {}, "output_type": "execute_result" } ], "source": [ "BAG = 'AAAAAAAAABBCCDDDDEEEEEEEEEEEEFFGGGHHIIIIIIIIIJKLLLLMMNNNNNNOOOOOOOOPPQRRRRRRSSSSTTTTTTUUUUVVWWXYYZ__'\n", "len(BAG)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "Then the function `play_game` will take a list of *player strategies* as input, and play those strategies against each other over the course of a game. A strategy is a function that takes a board and a rack as input and returns a play. For example, `highest_scoring_play` is a strategy. If the optional argument `verbose` is true, then the board is displayed after each play." ] }, { "cell_type": "code", "execution_count": 55, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [], "source": [ "def play_game(strategies=[highest_scoring_play]*2, verbose=True, seed=None) -> list:\n", " \"A number of players play a game; return a list of their scores.\"\n", " board = Board(WWF)\n", " bag = list(BAG)\n", " random.seed(seed)\n", " random.shuffle(bag)\n", " scores = [0 for _ in strategies]\n", " racks = [replenish('', bag) for _ in strategies]\n", " while True:\n", " old_board = board\n", " for (p, strategy) in enumerate(strategies):\n", " board = make_one_play(board, p, strategy, scores, racks, bag, verbose)\n", " if racks[p] == '':\n", " # Player p has gone out; game over\n", " return subtract_remaining_tiles(racks, scores, p)\n", " if old_board == board:\n", " # No player has a move; game over\n", " return scores\n", "\n", "def make_one_play(board, p, strategy, scores, racks, bag, verbose) -> Board:\n", " \"\"\"One player, player p, chooses a move according to the strategy.\n", " We make the move, replenish the rack, update scores, and return the new Board.\"\"\"\n", " rack = racks[p]\n", " play = strategy(board, racks[p])\n", " racks[p] = replenish(play.rack, bag)\n", " points = score(board, play)\n", " scores[p] += points\n", " board = make_play(board, play)\n", " if verbose:\n", " display(HTML('Player {} with rack {} makes {}
for {} points; draws: {}; scores: {}'\n", " .format(p, rack, play, points, racks[p], scores)),\n", " board)\n", " return board\n", "\n", "def subtract_remaining_tiles(racks, scores, p) -> list:\n", " \"Subtract point values from each player and give them to player p.\"\n", " for i in range(len(racks)):\n", " points = sum(POINTS[L] for L in racks[i])\n", " scores[i] -= points\n", " scores[p] += points\n", " return scores\n", "\n", "def replenish(rack, bag) -> str:\n", " \"Fill rack with 7 letters (as long as there are letters left in the bag).\"\n", " while len(rack) < 7 and bag:\n", " rack += bag.pop()\n", " return rack" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "I'll make sure you can see all the output:" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "application/javascript": [ "IPython.OutputArea.auto_scroll_threshold = 9999;\n" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "%%javascript\n", "IPython.OutputArea.auto_scroll_threshold = 9999;" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "And we'll play a game, specifying the seed to make it somewhat reproducable (*Note: the seed means that the bag will be shuffled the same way. But enumerating sets may happen differently, because different instances of Python start with different hash functions. So when two or more possible plays get the same score, different ones may be chosen on different runs.*)" ] }, { "cell_type": "code", "execution_count": 57, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/html": [ "Player 0 with rack ACBKEXT makes Play(start=144, dir=1, letters='EXACT', rack='BK')
for 28 points; draws: BKENTLO; scores: [28, 0]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DWTLTLDW
TLDLDLTL
DWE1X8A1C3T1
TLDLDLTL
DWTLTLDW
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DLDWDWDL
TWTLTLTW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack IGSEVAR makes Play(start=98, dir=17, letters='VISAGE', rack='R')
for 29 points; draws: RLQNOHU; scores: [28, 29]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLV4
DWTLTLI1DW
TLDLDLS1TL
DWE1X8A1C3T1A1
TLDLDLG2TL
DWTLTLE1DW
DLDLDLDL
TWTLDWTLTW
DLDLDLDL
DLDWDWDL
TWTLTLTW
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'I',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'E',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack BKENTLO makes Play(start=182, dir=17, letters='BEKNOT', rack='L')
for 70 points; draws: LAYOILN; scores: [98, 29]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLV4
DWTLTLI1DW
TLDLDLS1TL
DWE1X8A1C3T1A1
TLDLDLG2TL
DWTLTLB3E1DW
DLDLDLE1DL
TWTLDWK5TW
DLDLDLN1DL
DLDWDWO1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'I',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'B',\n", " 'E',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'K',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack RLQNOHU makes Play(start=112, dir=1, letters='QUOIN', rack='RLH')
for 68 points; draws: RLHPYEF; scores: [98, 97]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLV4
DWTLQ10U1O1I1N1
TLDLDLS1TL
DWE1X8A1C3T1A1
TLDLDLG2TL
DWTLTLB3E1DW
DLDLDLE1DL
TWTLDWK5TW
DLDLDLN1DL
DLDWDWO1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'B',\n", " 'E',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'K',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack LAYOILN makes Play(start=216, dir=1, letters='KAYO', rack='LILN')
for 33 points; draws: LILNFU_; scores: [131, 97]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLDWTLTW
DLDLDLV4
DWTLQ10U1O1I1N1
TLDLDLS1TL
DWE1X8A1C3T1A1
TLDLDLG2TL
DWTLTLB3E1DW
DLDLDLE1DL
TWTLDWK5A1Y4O1
DLDLDLN1DL
DLDWDWO1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'B',\n", " 'E',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack RLHPYEF makes Play(start=76, dir=17, letters='PHYLE', rack='REF')
for 26 points; draws: REFWOAV; scores: [131, 123]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLP3TLTW
DLDLH4DLV4
DWTLY4Q10U1O1I1N1
TLDLL1DLS1TL
DWE1X8A1C3T1A1
TLDLDLG2TL
DWTLTLB3E1DW
DLDLDLE1DL
TWTLDWK5A1Y4O1
DLDLDLN1DL
DLDWDWO1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'B',\n", " 'E',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack LILNFU_ makes Play(start=83, dir=17, letters='FUsIL', rack='LN')
for 41 points; draws: LNNENIH; scores: [172, 123]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLP3TLF4
DLDLH4DLV4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLTLB3E1DW
DLDLDLE1DL
TWTLDWK5A1Y4O1
DLDLDLN1DL
DLDWDWO1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'B',\n", " 'E',\n", " '-',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack REFWOAV makes Play(start=180, dir=1, letters='WEBER', rack='FOAV')
for 36 points; draws: FOAVOET; scores: [172, 159]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLP3TLF4
DLDLH4DLV4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLE1DL
TWTLDWK5A1Y4O1
DLDLDLN1DL
DLDWDWO1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack LNNENIH makes Play(start=180, dir=17, letters='WHINE', rack='LNN')
for 22 points; draws: LNNETGS; scores: [194, 159]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLTLTW
DLDWDWDL
DLDLDLDL
TWTLP3TLF4
DLDLH4DLV4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
DLDWE1O1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack FOAVOET makes Play(start=26, dir=17, letters='FOVEA', rack='OT')
for 30 points; draws: OTIORMZ; scores: [194, 189]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLF4TW
DLDWO1DWDL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
DLDWE1O1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'F',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " 'O',\n", " '-',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack LNNETGS makes Play(start=39, dir=1, letters='NELSON', rack='TG')
for 24 points; draws: TGEURDG; scores: [218, 189]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLF4TW
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
DLDWE1O1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'F',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack OTIORMZ makes Play(start=241, dir=1, letters='MOTORIZE', rack='')
for 79 points; draws: EITIIPI; scores: [218, 268]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
TWTLF4TW
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'F',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack TGEURDG makes Play(start=21, dir=1, letters='GUDE', rack='TRG')
for 33 points; draws: TRGDWME; scores: [251, 268]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4TW
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
TWTLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack EITIIPI makes Play(start=257, dir=1, letters='TIPI', rack='EII')
for 36 points; draws: EIISNUJ; scores: [251, 304]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4TW
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWTLY4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack TRGDWME makes Play(start=108, dir=1, letters='WRY', rack='TGDME')
for 17 points; draws: TGDME_I; scores: [268, 304]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4TW
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWW4R1Y4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " '.',\n", " '.',\n", " '=',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack EIISNUJ makes Play(start=26, dir=1, letters='FUJI', rack='EISN')
for 44 points; draws: EISNART; scores: [268, 348]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWW4R1Y4Q10U1O1I1N1s
TLDLL1DLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack TGDME_I makes Play(start=127, dir=1, letters='LEu', rack='TGDMI')
for 22 points; draws: TGDMIBR; scores: [290, 348]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLP3E1TLF4
DLDLH4A1V4U1
DWW4R1Y4Q10U1O1I1N1s
TLDLL1E1uDLS1I1
DWE1X8A1C3T1A1L1
TLDLDLG2TL
DWTLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack EISNART makes Play(start=73, dir=17, letters='STAINER', rack='')
for 54 points; draws: CLEDEDA; scores: [290, 402]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
DLDLV4DLDL
TWTLS1P3E1TLF4
DLT1DLH4A1V4U1
DWA1W4R1Y4Q10U1O1I1N1s
TLI1L1E1uDLS1I1
DWN1E1X8A1C3T1A1L1
TLE1DLG2TL
DWR1TLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'T',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack TGDMIBR makes Play(start=69, dir=1, letters='BRIMS', rack='TGD')
for 45 points; draws: TGDARAO; scores: [335, 402]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
DLDLV4DLDL
B3R1I1M3S1P3E1TLF4
DLT1DLH4A1V4U1
DWA1W4R1Y4Q10U1O1I1N1s
TLI1L1E1uDLS1I1
DWN1E1X8A1C3T1A1L1
TLE1DLG2TL
DWR1TLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " 'B',\n", " 'R',\n", " 'I',\n", " 'M',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'T',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack CLEDEDA makes Play(start=53, dir=17, letters='CRADLE', rack='ED')
for 24 points; draws: EDOSA; scores: [335, 426]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
C3DLV4DLDL
B3R1I1M3S1P3E1TLF4
A1DLT1DLH4A1V4U1
D2A1W4R1Y4Q10U1O1I1N1s
TLL1I1L1E1uDLS1I1
E1DWN1E1X8A1C3T1A1L1
TLE1DLG2TL
DWR1TLW4E1B3E1R1
DLDLDLH4E1DL
TWTLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'C',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " 'B',\n", " 'R',\n", " 'I',\n", " 'M',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " 'A',\n", " ':',\n", " '.',\n", " 'T',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " 'D',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " 'L',\n", " '.',\n", " '.',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " '.',\n", " 'E',\n", " '.',\n", " '-',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " '.',\n", " '-',\n", " '.',\n", " '.',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '=',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack TGDARAO makes Play(start=137, dir=17, letters='AGORA', rack='TD')
for 32 points; draws: TD; scores: [367, 426]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
C3DLV4DLDL
B3R1I1M3S1P3E1TLF4
A1DLT1DLH4A1V4U1
D2A1W4R1Y4Q10U1O1I1N1s
TLL1I1L1E1uDLS1I1
A1E1DWN1E1X8A1C3T1A1L1
G2E1DLG2TL
O1DWR1TLW4E1B3E1R1
R1DLDLDLH4E1DL
A1TLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'C',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " 'B',\n", " 'R',\n", " 'I',\n", " 'M',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " 'A',\n", " ':',\n", " '.',\n", " 'T',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " 'D',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " 'L',\n", " '.',\n", " '.',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " 'A',\n", " 'E',\n", " '.',\n", " '-',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " 'G',\n", " '.',\n", " '.',\n", " '.',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " 'O',\n", " '-',\n", " '.',\n", " '.',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " 'R',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " 'A',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack EDOSA makes Play(start=123, dir=17, letters='SADE', rack='O')
for 21 points; draws: O; scores: [367, 447]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
C3DLV4DLDL
B3R1I1M3S1P3E1TLF4
A1DLT1DLH4A1V4U1
D2A1W4R1Y4Q10U1O1I1N1s
TLL1S1I1L1E1uDLS1I1
A1E1A1N1E1X8A1C3T1A1L1
G2D2E1DLG2TL
O1DWE1R1TLW4E1B3E1R1
R1DLDLDLH4E1DL
A1TLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'C',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " 'B',\n", " 'R',\n", " 'I',\n", " 'M',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " 'A',\n", " ':',\n", " '.',\n", " 'T',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " 'D',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " 'L',\n", " '.',\n", " 'S',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " 'A',\n", " 'E',\n", " '.',\n", " 'A',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " 'G',\n", " '.',\n", " '.',\n", " 'D',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " 'O',\n", " '-',\n", " '.',\n", " 'E',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " 'R',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " 'A',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 0 with rack TD makes Play(start=87, dir=1, letters='AD', rack='T')
for 10 points; draws: T; scores: [377, 447]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
C3DLV4DLDL
B3R1I1M3S1P3E1TLF4
A1D2T1DLH4A1V4U1
D2A1W4R1Y4Q10U1O1I1N1s
TLL1S1I1L1E1uDLS1I1
A1E1A1N1E1X8A1C3T1A1L1
G2D2E1DLG2TL
O1DWE1R1TLW4E1B3E1R1
R1DLDLDLH4E1DL
A1TLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'C',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " 'B',\n", " 'R',\n", " 'I',\n", " 'M',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " 'A',\n", " 'D',\n", " '.',\n", " 'T',\n", " '.',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " 'D',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " 'L',\n", " '.',\n", " 'S',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " 'A',\n", " 'E',\n", " '.',\n", " 'A',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " 'G',\n", " '.',\n", " '.',\n", " 'D',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " 'O',\n", " '-',\n", " '.',\n", " 'E',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " 'R',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " 'A',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "Player 1 with rack O makes Play(start=90, dir=1, letters='TO', rack='')
for 7 points; draws: ; scores: [377, 454]" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "
G2U1D2E1F4U1J8I1
DLN1E1L1S1O1N1DL
C3DLV4DLDL
B3R1I1M3S1P3E1TLF4
A1D2T1O1DLH4A1V4U1
D2A1W4R1Y4Q10U1O1I1N1s
TLL1S1I1L1E1uDLS1I1
A1E1A1N1E1X8A1C3T1A1L1
G2D2E1DLG2TL
O1DWE1R1TLW4E1B3E1R1
R1DLDLDLH4E1DL
A1TLDWI1K5A1Y4O1
DLDLN1DLN1DL
M3O1T1O1R1I1Z10E1O1DL
T1I1P3I1TLTLT1
" ], "text/plain": [ "['#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " '.',\n", " 'G',\n", " 'U',\n", " 'D',\n", " 'E',\n", " '.',\n", " 'F',\n", " 'U',\n", " 'J',\n", " 'I',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'N',\n", " 'E',\n", " 'L',\n", " 'S',\n", " 'O',\n", " 'N',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'C',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " 'B',\n", " 'R',\n", " 'I',\n", " 'M',\n", " 'S',\n", " '.',\n", " '.',\n", " 'P',\n", " 'E',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'F',\n", " '#',\n", " '#',\n", " '.',\n", " 'A',\n", " 'D',\n", " '.',\n", " 'T',\n", " 'O',\n", " ':',\n", " 'H',\n", " 'A',\n", " '.',\n", " '.',\n", " '.',\n", " 'V',\n", " '.',\n", " 'U',\n", " '#',\n", " '#',\n", " '.',\n", " 'D',\n", " '.',\n", " '.',\n", " 'A',\n", " 'W',\n", " 'R',\n", " 'Y',\n", " '.',\n", " 'Q',\n", " 'U',\n", " 'O',\n", " 'I',\n", " 'N',\n", " 's',\n", " '#',\n", " '#',\n", " ';',\n", " 'L',\n", " '.',\n", " 'S',\n", " 'I',\n", " '.',\n", " '.',\n", " 'L',\n", " 'E',\n", " 'u',\n", " ':',\n", " '.',\n", " 'S',\n", " '.',\n", " 'I',\n", " '#',\n", " '#',\n", " 'A',\n", " 'E',\n", " '.',\n", " 'A',\n", " 'N',\n", " '.',\n", " '.',\n", " 'E',\n", " 'X',\n", " 'A',\n", " 'C',\n", " 'T',\n", " 'A',\n", " '.',\n", " 'L',\n", " '#',\n", " '#',\n", " 'G',\n", " '.',\n", " '.',\n", " 'D',\n", " 'E',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " 'G',\n", " '.',\n", " ';',\n", " '#',\n", " '#',\n", " 'O',\n", " '-',\n", " '.',\n", " 'E',\n", " 'R',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " 'W',\n", " 'E',\n", " 'B',\n", " 'E',\n", " 'R',\n", " '.',\n", " '#',\n", " '#',\n", " 'R',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " ':',\n", " 'H',\n", " '.',\n", " 'E',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " 'A',\n", " '.',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " '.',\n", " '-',\n", " '.',\n", " 'I',\n", " '.',\n", " 'K',\n", " 'A',\n", " 'Y',\n", " 'O',\n", " '#',\n", " '#',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " ':',\n", " '.',\n", " '.',\n", " '.',\n", " '.',\n", " 'N',\n", " ':',\n", " 'N',\n", " '.',\n", " ':',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " '.',\n", " 'M',\n", " 'O',\n", " 'T',\n", " 'O',\n", " 'R',\n", " 'I',\n", " 'Z',\n", " 'E',\n", " '.',\n", " 'O',\n", " ':',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '.',\n", " 'T',\n", " 'I',\n", " 'P',\n", " 'I',\n", " '.',\n", " ';',\n", " '.',\n", " ';',\n", " '.',\n", " '.',\n", " 'T',\n", " '.',\n", " '.',\n", " '.',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#',\n", " '#']" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "[376, 455]" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "play_game(seed=2)" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "That was an exciting high-scoring game that ranged over the whole board.\n", "\n", "But that was just one game; Let's get statistics for both players over, say, 20 games (40 game scores):" ] }, { "cell_type": "code", "execution_count": 58, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPU times: user 27.8 s, sys: 101 ms, total: 27.9 s\n", "Wall time: 28 s\n" ] }, { "data": { "text/plain": [ "'min: 254, median: 364, max: 480'" ] }, "execution_count": 58, "metadata": {}, "output_type": "execute_result" } ], "source": [ "%%time\n", "\n", "Ngames = 20\n", "results = [play_game(verbose=False, seed=None) for _ in range(Ngames)]\n", "scores = sorted(score for pair in results for score in pair)\n", "\n", "f'min: {min(scores)}, median: {scores[Ngames]}, max: {max(scores)}'" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Tests\n", "\n", "I *should* have a complete test suite. Instead, all I have this minimal suite, plus the confidence I gained from seeing the game play." ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "outputs": [ { "data": { "text/plain": [ "'ok'" ] }, "execution_count": 59, "metadata": {}, "output_type": "execute_result" } ], "source": [ "def sames(A, B): return sorted(A) == sorted(B)\n", "\n", "def test():\n", " \"Unit tests.\"\n", " assert is_word('WORD')\n", " assert is_word('LETTERs')\n", " assert is_word('ETHyLENEDIAMINETETRAACETATES')\n", " assert not is_word('ALFABET')\n", " \n", " rack = 'ABCHKNQ'\n", " \n", " assert sames(letters(rack), rack)\n", " assert sames(letters('ABAC_'), 'ABCabcdefghijklmnopqrstuvwxyz')\n", " \n", " assert dict_prefixes({'HELLO', 'HELP', 'HELPER'}) == {\n", " '', 'H', 'HE', 'HEL', 'HELL', 'HELP', 'HELPE'}\n", " \n", " assert rack_prefixes('ABC') == {'', 'A', 'AB', 'AC', 'B', 'BA', 'BAC', 'C', 'CA', 'CAB'}\n", " assert len(rack_prefixes('LETTERS')) == 155\n", " assert len(rack_prefixes('LETTER_')) == 1590\n", " \n", " DOWN = WWF.down\n", " plays = {\n", " Play(145, DOWN, 'ENTER', ''),\n", " Play(144, ACROSS, 'BE', ''),\n", " Play(138, DOWN, 'GAVE', ''),\n", " Play(158, DOWN, 'MUSES', ''),\n", " Play(172, ACROSS, 'VIRULeNT', ''),\n", " Play(213, ACROSS, 'RED', ''),\n", " Play(198, ACROSS, 'LYTHE', ''),\n", " Play(147, DOWN, 'CHILDREN', ''),\n", " Play(164, ACROSS, 'HEARD', ''),\n", " Play(117, DOWN, 'BRIDLES', ''),\n", " Play(131, ACROSS, 'TOUR', '')}\n", "\n", " board = Board(WWF)\n", " for play in plays:\n", " board = make_play(board, play)\n", " \n", " assert len(WWF) == len(board) == 17 * 17\n", " assert all_anchors(WWF) == [144]\n", " assert all_anchors(board) == [\n", " 100, 114, 115, 116, 121, 127, 128, 130, 137, 139, 141, 143, 146, 148, 149, 150, 154, 156, 157, 159, 160, \n", " 161, 163, 171, 180, 182, 183, 184, 188, 190, 191, 193, 194, 195, 197, 206, 208, 210, 212, 216, 217, 218, \n", " 225, 227, 230, 231, 233, 236, 243, 248, 250, 265, 267]\n", " \n", " assert crossword(board, 141, ACROSS) == '.MUSES'\n", " assert crossword(board, 148, ACROSS) == 'T.E'\n", " assert valid_crossword('.MUSES', 'A')\n", " assert not valid_crossword('.MUSES', 'B')\n", " \n", " assert sames(prefix_plays(rack_prefixes(rack), board, 141, 1, rack),\n", " [Play(start=141, dir=1, letters='', rack='ABCHKNQ'),\n", " Play(start=140, dir=1, letters='C', rack='ABHKNQ'),\n", " Play(start=140, dir=1, letters='K', rack='ABCHNQ'),\n", " Play(start=140, dir=1, letters='B', rack='ACHKNQ'),\n", " Play(start=140, dir=1, letters='A', rack='BCHKNQ'),\n", " Play(start=140, dir=1, letters='H', rack='ABCKNQ'),\n", " Play(start=140, dir=1, letters='N', rack='ABCHKQ'),\n", " Play(start=140, dir=1, letters='Q', rack='ABCHKN')])\n", " \n", " assert sames(extend_play(board, Play(start=140, dir=1, letters='B', rack='ACHKNQ')),\n", " {Play(start=140, dir=1, letters='BA', rack='CHKNQ'),\n", " Play(start=140, dir=1, letters='BACKBENCH', rack='Q'),\n", " Play(start=140, dir=1, letters='BAH', rack='CKNQ'),\n", " Play(start=140, dir=1, letters='BAN', rack='CHKQ')})\n", "\n", " assert len(BAG) == 100\n", " \n", " assert replenish('RACK', ['X', 'B', 'A', 'G']) == 'RACKGAB'\n", " assert replenish('RACK', []) == 'RACK'\n", " assert replenish('RACK', ['A', 'B']) == 'RACKBA'\n", " \n", " assert score(WWF, Play(144, ACROSS, 'BE', '')) == (3 + 1)\n", " assert score(board, Play(140, ACROSS, 'BACKBENCH', 'Q')) == 116\n", " \n", " return 'ok'\n", "\n", "test()" ] }, { "cell_type": "markdown", "metadata": { "button": false, "new_sheet": false, "run_control": { "read_only": false } }, "source": [ "# Conclusion: How Did We Do?\n", "\n", "We can break that into three questions:\n", " \n", "- **Is the code easy to follow?**
I'm biased, but I think this code is fairly easy to understand, test, and modify.\n", "- **Does the strategy score well?**
Yes: the mean and median are both well over 350, which is enough for [the elite club](https://www.facebook.com/WWF350Club) of high scorers. \n", "
No: this is not quite world-champion caliber.\n", "- **Is the code fast enough?**
It takes less than 4 seconds to play a complete game for both players; that's fast enough for me. If desired, the code could be made about 100 times faster, by using multiprocessing, by caching more information, by not building explicit lists for intermediate results (although those results make the code easier to test), by using PyPy or Cython, or by porting to another language.\n", "\n", "We can also ask: What's left to do?\n", "\n", " - We could modify the program to play on a Scrabble® board. \n", " - We could give players the option of trading in tiles.\n", " - We could explore better strategies. The current strategy is weak for three reasons: it is **greedy**, trying to optimize the score for the current play, not for the whole game; it has the **wrong metric**, trying to optimize score, when it should be optimizing the probability of winning the game; and it is **not strategic** in that it does not consider the opponent's possible moves. A better strategy might:\n", " - Plan ahead to use high-scoring letters only with bonuses.\n", " - Manage letters to increase the chance of a bingo.\n", " - Use blank tiles strategically.\n", " - Play defensively to avoid giving the opponent good chances at bonus squares or open letters.\n", " - In the end game, plan to go out before the opponent (or at least avoid being stuck with high-scoring letters in the rack).\n", " - In the end game, know which tiles have not been played and thus which ones the opponent could have.\n", " - The display could be prettier.\n", " - The game could be interfaced to an online game server.\n", " - The game could be made interactive to play with a human player(s).\n", " - More complete unit tests would be appreciated.\n", " - We could compare this program to those of the [giants](https://www.cs.cmu.edu/afs/cs/academic/class/15451-s06/www/lectures/scrabble.pdf) whose [shoulders](http://ericsink.com/downloads/faster-scrabble-gordon.pdf) we [stood](http://web.archive.org/web/20040116175427/http://www.math-info.univ-paris5.fr/~bouzy/ProjetUE3/Scrabble.pdf) [upon](http://www.gtoal.com/wordgames/scrabble.html).\n", " \n", "Thanks to Markus Dobler for correcting one bug and making another useful suggestion.\n", "\n" ] } ], "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.7.7" } }, "nbformat": 4, "nbformat_minor": 1 }