Python 3 permutations Scrabble
<p>I'm struggling a bit with an effective way of debugging Python, and the consequent lack of understanding and optimization.</p>

<p>I'm in the process of writing a Scrabble game in Python as an experiment, and I suspect I'm going about it all wrong. Namely, I'm failing to understand how to handle the blank tiles (represented by question marks below). I've bungled the code as follows:</p>

<pre><code>import itertools
import string

  rack = 'rstlena??'
  blank_count = rack.count('?')
  letters = rack.split(',')
  word_set = set()

  if blank_count &gt; 0:
    rack = rack.replace('?', '')
    if blank_count == 1:
      for l in string.ascii_lowercase:
        letters.append(rack + l)
    elif blank_count == 2:
      for l in string.ascii_lowercase:
        letters.append(rack + l + l)

    for l_combo in rack:
      for i in range(3, 9):
        for permutation in itertools.permutations(l_combo, i):
          word_to_check = ''.join(permutation)
          if word_to_check in word_list: # word_list is some dictionary
            word_set.add(word_to_check)
</code></pre>

<p>...</p>

<p>It works when there's one blank, but with two it just adds the same letter and produces undesired results (obviously).</p>

<p>I apologize in advance for the ugly code I've subjected you to cringe at.</p>

<p>This should work, and be acceptably fast. I tried to comment the tricky parts, do not hesitate to ask if there are some bits of the code you do not understand. </p>

<pre><code>import itertools
import string
import numpy as np

#takes a list of words as input ['door', 'chair', 'wall'], and returns the words alphabetically sorted [['door', 'door'], ['achir', 'chair'], ['allw', 'wall']]
def sortWordList(word_list):
    return np.array([["".join(sorted(word)), word] for word in word_list])

#recursive function to get all unordered n-letter subsets of `letters`, without repetition. NLetterSubsets(2, "fly") == ["fl", "fy", "ly"]; NLetterSubsets(2, "foo") == ["fo", "fo", "oo"]
def NLetterSubsets(n, letters):
    if n == len(letters):
        return [letters]
    if n &gt; len(letters) or len(letters) == 0:
        return []
    return [letters[0] + x for x in NLetterSubsets(n-1, letters[1:])] + NLetterSubsets(n, letters[1:])

#loads word_list from a newline-separated file
def loadWordList(filename):
    with open(filename, 'r') as f:
        return [line.rstrip('\n') for line in f]

word_list = loadWordList('words.txt')
word_list = sortWordList(word_list)
print(word_list)

rack = 'trackable'
blank_count = rack.count('?')
if blank_count:
    rack = rack.replace('?','')
word_set = set()

#possible letters is the list of all possible values taken by the blank(s)
possibleLetters = ['']
if blank_count &gt;= 1:
    possibleLetters += [l for l in string.ascii_lowercase]
if blank_count == 2:
    possibleLetters += [l+m for l in string.ascii_lowercase for m in string.ascii_lowercase]

for blanks in possibleLetters:
    for i in range(3-len(blanks), 9-len(blanks)):
        #gets a subset of letters from rack, to which we will add the blank values to form a word of length in range(3,9)
        for setOfLetter in NLetterSubsets(i-blank_count, rack):
            sortedWordToSearchFor = ''.join(sorted(setOfLetter + blanks))
            #if the sorted list of letters we have is also present in the word_set, then take the associated word
            for index in np.where(word_list[:,0] == sortedWordToSearchFor)[0]:
                word_set.add(word_list[index][1])

print(word_set)
</code></pre>

python python-3.x