-
Notifications
You must be signed in to change notification settings - Fork 0
/
guess_history.py
122 lines (112 loc) · 5.29 KB
/
guess_history.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import string
from collections import defaultdict
from word_utils import letter_counts, letter_indices
class GuessHistory:
def __init__(self):
self.history = defaultdict(lambda: defaultdict(list))
self.history["guesses"] = []
def append(self, word, results):
self.history["guesses"].append(word)
guessed_letters = letter_indices(word)
for letter, indices in guessed_letters.items():
guesses = [(idx, results[idx]) for idx in indices]
correct_indices = [guess[0] for guess in guesses if guess[1] == "correct"]
incorrect_indices = [
guess[0] for guess in guesses if guess[1] == "incorrect"
]
missing_indices = [guess[0] for guess in guesses if guess[1] == "missing"]
if len(correct_indices) > 0:
self.set_correct(letter=letter, indices=correct_indices)
self.set_letter_min_count(letter=letter, count=len(correct_indices))
# if we have correct and incorrect, we know there are more instances
# of the letter not guessed, so we know a minimum letter count > 1
if len(incorrect_indices) > 0:
self.set_incorrect(letter=letter, indices=incorrect_indices)
calculated_min = len(correct_indices) + len(incorrect_indices)
self.set_letter_min_count(letter=letter, count=calculated_min)
# if we have correct and missing, we know that there are no other
# instances of the letter
if len(missing_indices) > 0:
calculated_max = len(correct_indices) + len(incorrect_indices)
self.set_letter_max_count(letter=letter, count=calculated_max)
elif len(incorrect_indices) > 0:
self.set_incorrect(letter=letter, indices=incorrect_indices)
self.set_letter_min_count(letter=letter, count=len(incorrect_indices))
if len(missing_indices) > 0:
calculated_max = len(incorrect_indices)
if self.history[letter]["max_count"]:
calculated_max = min(
self.history[letter]["max_count"], calculated_max
)
self.history[letter]["max_count"] == calculated_max
elif len(missing_indices) > 0:
self.set_letter_max_count(letter=letter, count=0)
def is_word_possible(self, word):
word_letter_counts = letter_counts(word)
word_letter_indices = letter_indices(word)
for letter in string.ascii_lowercase:
if (
type(self.history[letter]["max_count"]) == int
and self.history[letter]["max_count"] < word_letter_counts[letter]
):
return False
elif (
type(self.history[letter]["min_count"]) == int
and self.history[letter]["min_count"] > word_letter_counts[letter]
):
return False
elif any(
correct_index not in word_letter_indices[letter]
for correct_index in self.history[letter]["correct"]
):
return False
elif any(
incorrect_index in word_letter_indices[letter]
for incorrect_index in self.history[letter]["incorrect"]
):
return False
return True
def set_letter_max_count(self, letter, count):
if (
type(self.history[letter]["max_count"]) == int
and self.history[letter]["max_count"] <= count
):
return
self.history[letter]["max_count"] = count
return count
def set_letter_min_count(self, letter, count):
if (
type(self.history[letter]["min_count"]) == int
and self.history[letter]["min_count"] >= count
):
return
self.history[letter]["min_count"] = count
return count
def set_correct(self, letter, indices):
self.history[letter]["correct"].extend(indices)
self.history[letter]["correct"] = list(set(self.history[letter]["correct"]))
return self.history[letter]["correct"]
def set_incorrect(self, letter, indices):
self.history[letter]["incorrect"].extend(indices)
self.history[letter]["incorrect"] = list(set(self.history[letter]["incorrect"]))
return self.history[letter]["incorrect"]
def letter_status(self, letter):
if self.history[letter]["max_count"] == 0:
return "missing"
elif self.history[letter]["max_count"] == len(self.history[letter]["correct"]):
return "all_known"
elif self.history[letter]["min_count"] and self.history[letter][
"min_count"
] == len(self.history[letter]["correct"]):
return "known_position"
elif self.history[letter]["min_count"] and self.history[letter][
"min_count"
] > len(self.history[letter]["correct"]):
return "unknown_position"
elif not (
type(self.history[letter]["min_count"]) == int
or type(self.history[letter]["max_count"]) == int
):
return "unknown"
def guess_count(self):
return len(self.history["guesses"])