[Tutor] Scrabble Help
Steven D'Aprano
steve at pearwood.info
Sun Sep 5 18:56:07 CEST 2010
On Mon, 6 Sep 2010 01:45:30 am William Allison wrote:
> I'd like to write a program to help find words for Scrabble but I've
> been having trouble
> right from the beginning.
>
> tiles = 'aeirstw'
>
> dictionary = ['aardvark', 'cat', 'dog', 'taste', 'stare', 'wrist']
>
> for word in range(len(dictionary)):
That's misleading -- "word" isn't a word at all, it's a number.
> for letter in range(len(dictionary[word])):
And likewise for letter.
> if dictionary[word][letter] in tiles:
> nothing here quite works
Better to write that loop as:
for word in dictionary:
for letter in word:
if letter in tiles:
nothing here quite works either...
> I guess what I'm trying to do is step through every letter of every
> word in my dictionary
> and if that letter is in my tiles set it aside and compare it back to
> the dictionary.
The approach I think you're trying to take is to find out if each letter
in the tiles matches a word in the dictionary. Let's separate that
functionality into a function of its own:
def match(word, tiles):
"""Return true if every letter in word matches a tile."""
for letter in word:
if letter not in tiles:
# Mismatch, so fail.
return False
# if we get to the end, all the letters must have matched
return True
Let's test it:
>>> match("ape", "axdeps")
True
>>> match("cat", "axdeps")
False
So far so good! But we can simplify it, because there's a built-in
function that does the same thing:
def match(word, tiles):
"""Return true if every letter in word matches a tile."""
return all(letter in tiles for letter in word)
Don't worry too much about this though, because unfortunately this
function, and my first version, have a logic bug: they fail to take
into account repeated letters.
>>> match("moon", "monabc") # Should give false.
True
Oops. Okay, let's think about the problem a bit more... it's not enough
for each letter to be in the tiles, but that there must be at least as
many copies as in the word. So, let's do another version:
def match(word, tiles):
"""Return true if every letter in word matches a tile."""
for letter in word:
if word.count(letter) > tiles.count(letter):
return False
return True
>>> match("man", "monabc")
True
>>> match("moon", "monabc")
False
That looks better! It's not the most efficient code in the word, but for
comparing small words and a small set of tiles, it's good enough --
there's no need to optimize the code at this early stage. Get it
working first, then make it fast.
So, putting it back together:
for word in dictionary:
if match(word, tiles):
play_word() # whatever...
--
Steven D'Aprano
More information about the Tutor
mailing list