-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwordle.py
More file actions
139 lines (86 loc) · 3.45 KB
/
wordle.py
File metadata and controls
139 lines (86 loc) · 3.45 KB
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
from __future__ import annotations
import enum
import random
class WordleInvalidWordException(Exception):
pass
class WordleFullException(Exception):
pass
def load_word_list(filename: str) -> list[str]:
out = []
with open(filename, 'r', encoding='utf-8') as file:
raw = file.read()
for line in raw.split('\n'):
if line:
out.append(line)
return out
ANSI_RESET = '\033[0m'
class LetterState(enum.StrEnum):
NONE = '\033[100m'
INCLUDE = '\033[43m'
CORRECT = '\033[42m'
class Wordle:
def __init__(self, correct: None | str = None):
self._valid_guesses = set(load_word_list('valid-wordle-list.txt'))
self.guesses_left = 20 # 6
self.guesses = []
if correct is None:
self._correct = random.choice(load_word_list('todays-wordle-candidate.txt'))
else:
self._correct = correct
print('wordle correct answer:', self._correct)
def guess(self, guess: str) -> list[LetterState]:
if self.guesses_left <= 0:
raise WordleFullException()
if len(guess) != 5 or guess not in self._valid_guesses:
raise WordleInvalidWordException(f"Invalid guess: {guess}")
if guess in self.guesses:
raise WordleInvalidWordException(f"Word {guess} has already been guessed in guess {self.guesses.index(guess) + 1}!")
try:
self.guesses.append(guess)
out = self._rate_guess(guess)
self.guesses_left -= 1
for i, l in enumerate(out):
print(l + guess[i] + ANSI_RESET, end='')
print()
except WordleFullException:
for c in self._correct:
print(LetterState.CORRECT + c + ANSI_RESET, end='')
print()
raise
return out
def _rate_guess(self, guess: str) -> list[LetterState]:
if len(guess) != 5:
raise WordleInvalidWordException('Guess length should always be 5')
out = [LetterState.NONE] * 5
included_letters = {letter: self._correct.count(letter) for letter in set(self._correct)}
# correct
for i in range(5):
if self._correct[i] == guess[i].lower():
out[i] = LetterState.CORRECT
included_letters[guess[i].lower()] -= 1
# include
for i in range(5):
if (guess[i].lower() in self._correct) and (guess[i].lower() != self._correct[i].lower()):
if included_letters[guess[i].lower()] > 0:
out[i] = LetterState.INCLUDE
included_letters[guess[i].lower()] -= 1
if guess.lower() == self._correct:
print(f"You've cleared the wordle with {self.guesses_left} guesses remaining!")
raise WordleFullException()
return out
if __name__ == '__main__':
# print(LetterState.INCLUDE + 'B' + ANSI_RESET, end='')
# print(LetterState.CORRECT + 'O' + ANSI_RESET, end='')
# print(LetterState.NONE + 'R' + ANSI_RESET, end='')
# print(LetterState.INCLUDE + 'I' + ANSI_RESET, end='')
# print(LetterState.NONE + 'S' + ANSI_RESET, end='')
# print('\n')
wordle = Wordle(correct=None)
try:
while True:
try:
wordle.guess(input("Guess a word: "))
except WordleInvalidWordException:
print('Invalid word!')
except WordleFullException:
print('The answer was: ' + wordle._correct)