843. Guess the Word - cocoder39/coco39_LC GitHub Wiki
Problem breakdown
- Step 1: find a candidate word to guess
- Step 2: guess the word and then use the match count to narrow down search space
best candidate deep dive
- Option 1: select first element in candidate list
- Option 2: randomly select an element from candidate list
- Option 3: heuristic
- least 0: To reduce the chance of selecting a word that has too many 0 match with other words, we heuristically select a word that can minimize the number of 0 match with other words
- max overlap: matchScorep[i][j]: number of words of which the value at index i is ord('a') + j
class Solution:
def findSecretWord(self, wordlist: List[str], master: 'Master') -> None:
def countMatch(word1, word2):
cnt = 0
for ch1, ch2 in zip(word1, word2):
if ch1 == ch2:
cnt += 1
return cnt
def getOverlapScore(word):
score = 0
for i, ch in enumerate(word):
idx = ord(ch) - ord('a')
score += matchScore[i][idx]
return score
matchScore = [[0] * 26 for i in range(6)]
for word in wordlist:
for i, ch in enumerate(word):
idx = ord(ch) - ord('a')
matchScore[i][idx] += 1
n = len(wordlist)
matchCount = [[-1] * n for i in range(n)]
for i in range(n):
for j in range(i):
cnt = countMatch(wordlist[i], wordlist[j])
matchCount[i][j] = cnt
matchCount[j][i] = cnt
candidates = wordlist[:]
candidateMap = {word: i for i, word in enumerate(wordlist)}
for i in range(10):
candidates.sort(key=lambda c: getOverlapScore(c), reverse=True)
cur = candidates[0]
curIdx = candidateMap.get(cur)
match = master.guess(cur)
if match == 6:
break
temp = []
for j in range(n):
if matchCount[curIdx][j] == match:
temp.append(wordlist[j])
candidates = list(set(temp) & set(candidates))