gaurav8936
gaurav8936

Reputation: 43

Python: Scrabble with 2 wildcards: finding word combinations and scores: function returning incorrect result

I am trying to write a scrabble application with two functions (the main word-matching one, and the second for scoring). Implemented this as two .py files, but can't seem to get the query working. We use the sowpods file as the reference for valid scrabble words.

As a secondary objective, I would also like to make this work for 2 (and max 2) wildcards (out of 7) letters in total.

This is the scoring function that takes in a word and returns the score (as total)

def score_word(word_low):
    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}
    total = 0
    for letter in word_low:
        total = total + scores[letter]
    return total
    #valid_words.append([total, word_low])

This is the main function that takes in a rack of letters as input and returns the descending list of valid word combinations (ordered by score). Also the total combinations

from wordscore import *

def run_scrabble(rack):
    rack_low = rack.lower()
    rack_letters = list(rack_low)
    valid_words = []
    
    with open("sowpods.txt","r") as infile:
        raw_input = infile.readlines()#[0:1000]
        data = [datum.strip('\n') for datum in raw_input]
    
    for word in data:
        word_low = word.lower()
        for letter in word_low:
            if letter in rack_letters:
                rack_letters.remove(letter)
            elif '*' in rack_letters:
                rack_letters.remove('*') 
            elif '?' in rack_letters:
                rack_letters.remove('?')
            else:
                pass 
        else:
            valid_words.append([score_word(word_low), word_low])  
    
    valid_words.sort(reverse = True)
    
    for entry in valid_words:
        score = entry[0]
        word_low = entry[1]
        print((score, word_low))

    print("Total number of words:", len(valid_words))

I am stuck in the word matching section which is where I believe the problem is.

Test Sample Rack: 'hare'

Expected Output

(7, 'rhea')
(7, 'hear')
(7, 'hare')
(6, 'reh')
(6, 'rah')
(6, 'her')
(6, 'hae')
(5, 'he')
(5, 'ha')
(5, 'eh')
(5, 'ah')
(3, 'era')
(3, 'ear')
(3, 'are')
(2, 're')
(2, 'er')
(2, 'ea')
(2, 'ar')
(2, 'ae')
Total number of words: 19

Actual Output: looks like the ordered list of max scores from the full dictionary

(51, 'razzamatazzes')
(50, 'razzmatazzes')
(49, 'razzamatazz')
(49, 'pizzazzy')
(48, 'razzmatazz')
(47, 'quizzifications')
(47, 'pizzazzes')
(47, 'pazzazzes')
(47, 'bezzazzes')
...
...

Before tackling the problem with wildcards, I need to resolve the issue with the word-matching query. Any help would be awesome

Upvotes: 0

Views: 411

Answers (1)

Batmates
Batmates

Reputation: 64

I think the problem can be that you are using for ... else wrong way.

The code after else get executed always, because you always leave the for loop normal way. I think you wanted to type break instead of pass. And also you are removing letter permanently. So do something like this.

...

for word in data:
    word_low = word.lower()
    temp_rack_letters = rack_letters.copy() # keep the original
    for letter in word_low:
        if letter in temp_rack_letters :
            temp_rack_letters .remove(letter)
        elif '*' in temp_rack_letters :
            temp_rack_letters .remove('*') 
        elif '?' in temp_rack_letters :
            temp_rack_letters .remove('?')
        else:
            break # You want to exit the loop if letter dont match
    else:
        valid_words.append([score_word(word_low), word_low])

...

Also this for ... else syntax is not very readable, and as you can see I is easy to make mistakes and bugs, so be careful using it.

HTH

Upvotes: 1

Related Questions