19th Aug 2014 4 minutes read Can Python Help You Win Scrabble? Patrycja Dybka PostgreSQL It is hard to find someone who doesn’t know how to play Scrabble. In case someone isn’t familiar with the game, here’s a quick explanation: Scrabble is played by two to four players on a square board with a 15×15 grid of cells, each of which accommodates a single letter tile. The board is marked with “premium” squares, which multiply the number of points awarded; each letter tile has its own assigned numeric score. At the start of a Scrabble game, every player chooses 7 letter tiles. In this article I will try to present simple examples of how the Python programming language could help you play (and win) the game. Certainty, these examples won’t make a huge impression on those who are familiar with and have experience in programming, but they are definitely simple enough to encourage those with less experience to learn more. When you start playing Scrabble, what words can you create given the available letters? Obviously, there are many ways to quickly gain some answers. We can try to do it in SQL: Create a table with words in a database and a table with permuted strings or we can try some other, smarter way. However, every solution in SQL becomes more complex compared to solutions derived from different programming languages. So instead of using SQL, let’s try Python: Suppose that we have a rack with letters [‘f’, ‘g’, ‘f’, ‘i’, ‘r’, ‘a’, ‘e’] and we want to put all letters on the Scrabble board. Is there a 7-letter word being a permutation of those letters on the rack? In the category with the dictionary file, run the Python console. >>> import itertools >>> with open('sowpods.txt') as f: >>> words = set(word.strip().lower() for word in f) >>> perms = set(''.join(letters) for letters in itertools.permutations(['f', 'g', 'f', 'i', 'r', 'a', 'e'])) >>> res = [word for word in perms if word in words] However, this is not enough. It is possible to check all combinations and score points for each correct word. Let’s try to do it in two ways: 1) with a connection to a database and 2) using Python only. To connect to database, use Psycopg2, which is the most popular PostgreSQL adapter for Python. We’ll store a list of words in the database. You can download it from dictionary. The following perl one-liner will take care of convertion to INSERT INTO dict VALUES ('word'); perl -pe "s/'/''/g;s/.*/INSERT INTO dict VALUES ('$&');/" words.txt > words.sql Combinations of words will be created on the Python side as well as scores for each word. You can run the following code in your shell by typing: python scrabble.py your_letters. import sys import itertools import psycopg2 rack = sys.argv[1] scores = {"A": 1, "C": 3, "B": 3, "E": 1, "D": 2, "G": 2, "F": 4, "I": 1, "H": 4, "K": 5, "J": 8, "M": 3, "L": 1, "O": 1, "N": 1, "Q": 10, "P": 3, "S": 1, "R": 1, "U": 1, "T": 1, "W": 4, "V": 4, "Y": 4, "X": 8, "Z": 10} def compute_score(word): return sum([scores[letter.upper()] for letter in word]) candidates = set() for i in range(1, len(rack) + 1): for combination in itertools.combinations(rack, i): candidates |= {''.join(perm) for perm in itertools.permutations(combination)} conn = psycopg2.connect("dbname=scrabble user=patrycja") cur = conn.cursor() correct_words = [] for word in candidates: cur.execute("select count(*) from words where word='{}'".format(word)) if cur.fetchone()[0] == 1: correct_words.append((word, compute_score(word))) for word, score in correct_words: print(str(score) + " " + word) cur.close() conn.close() With the Python-only solution, words from the dictionary will be read from a file. import sys import itertools rack = sys.argv[1] scores = {"A": 1, "C": 3, "B": 3, "E": 1, "D": 2, "G": 2, "F": 4, "I": 1, "H": 4, "K": 5, "J": 8, "M": 3, "L": 1, "O": 1, "N": 1, "Q": 10, "P": 3, "S": 1, "R": 1, "U": 1, "T": 1, "W": 4, "V": 4, "Y": 4, "X": 8, "Z": 10} def compute_score(word): return sum([scores[letter.upper()] for letter in word]) candidates = set() for i in range(1, len(rack) + 1): for combination in itertools.combinations(rack, i): candidates |= {''.join(perm) for perm in itertools.permutations(combination)} with open('sowpods.txt') as f: dictionary = {word.strip().lower() for word in f} correct_words = dictionary & candidates correct_words = [(word, compute_score(word)) for word in correct_words] correct_words.sort(key=lambda word: word[1], reverse=True) for word, score in correct_words: print(str(score) + " " + word) At first look, the Python-only solution looks better. In the first approach, you need to manage a database. On the other hand, a database may be helpful when we have large amount of data that we can’t store locally. It’s also possible to do it via web services, but that’s a topic for another article. Knowing the possibilities, you can start to write your own more advanced Scrabble cheater. For the Python newbie I recommend this step by step tutorial which provides the essential Python constructs required to develop such a program: Scrabble challenge Tags: PostgreSQL