Last active
January 23, 2022 04:10
-
-
Save tyler-8/80281bea0489b991d97fdc10dcabfc6e to your computer and use it in GitHub Desktop.
A stupid script to help you cheat. Don't do it, this was just an experiment.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Uses the `words_alpha.txt` file from | |
https://github.com/dwyl/english-words/ | |
""" | |
import random | |
from collections import Counter | |
from typing import Iterable, Tuple | |
def has_no_repeat_letters(word: str) -> bool: | |
"""Determine if any letter is used more than once in the word. | |
Args: | |
word (str): Input word to check. | |
Returns: | |
bool: True if there are no repeating letters. | |
""" | |
occurences = Counter() | |
for letter in word: | |
occurences[letter] += 1 | |
return all(count == 1 for count in occurences.values()) | |
def has_letter(letter: str, word: str) -> bool: | |
return letter.upper() in word.upper() | |
def letter_matches_position(letter: str, position: int, word: str) -> bool: | |
return letter.upper() == word.upper()[position] | |
def build_word_list() -> Tuple: | |
with open("words_alpha.txt", "r") as infile: | |
word_list = (word.strip().upper() for word in infile if len(word.strip()) == 5) | |
return tuple(word_list) | |
def does_not_have_letters(letters: str, word: str) -> bool: | |
return all(letter.upper() not in word.upper() for letter in letters) | |
def has_all_letters(letters: str, word: str) -> bool: | |
return all(letter.upper() in word.upper() for letter in letters) | |
def has_letters_not_in_position(letter_positions: Iterable[Tuple], word: str) -> bool: | |
for letter, position in letter_positions: | |
if letter_matches_position(letter, position, word): | |
return False | |
return True | |
def has_letters_in_position(letter_positions: Iterable[Tuple], word: str) -> bool: | |
for letter, position in letter_positions: | |
if not letter_matches_position(letter, position, word): | |
return False | |
return True | |
def print_guesses(word_list: Iterable) -> None: | |
if len(word_list) <= 40: | |
guesses = word_list[:] | |
else: | |
guesses = list(set(random.choices(word_list, k=30))) | |
guesses.sort() | |
print("\n".join(guesses)) | |
def find_matching_words( | |
missing_letters: str, | |
has_letters: str, | |
good_positions: Iterable[Tuple], | |
bad_positions: Iterable[Tuple], | |
word_list: Iterable[str], | |
): | |
return list( | |
set( | |
word | |
for word in word_list | |
if does_not_have_letters(missing_letters, word) | |
and has_all_letters(has_letters, word) | |
and has_letters_in_position(good_positions, word) | |
and has_letters_not_in_position(bad_positions, word) | |
) | |
) | |
def main(): | |
missing_letters = set() # letters | |
has_letters = set() # letters | |
yellow_letter_positions = set() # set of 2-item tuples (letter, position) | |
green_letter_positions = set() # set of 2-item tuples (letter, position) | |
words = build_word_list() | |
# Use a diverse-letter word as the first guess to increase chance of letter matching. | |
first_guess = random.choice(list(filter(has_no_repeat_letters, words))) | |
prompt_guess = True | |
matching_words = [] | |
while True: | |
if prompt_guess: | |
print("First guess:", first_guess) | |
if input("Want to randomly pick another word? (y/n)").lower() == "y": | |
first_guess = random.choice(list(filter(has_no_repeat_letters, words))) | |
continue | |
prompt_guess = False | |
while True: | |
yellow_letters = input( | |
"Yellow letters? Use 'Letter,Position' format." | |
" Position starts at 1. One per line." | |
) | |
if not yellow_letters: | |
break | |
if "," not in yellow_letters: | |
print("Invalid input, must be in 'Letter,Position' format.") | |
continue | |
yellow_letter, yellow_position = yellow_letters.split(",") | |
yellow_position = int(yellow_position) - 1 | |
yellow_letter_positions.add((yellow_letter, yellow_position)) | |
has_letters.add(yellow_letter.upper()) | |
gray_letters = input("Gray letters?") | |
list(map(missing_letters.add, gray_letters.upper())) | |
while True: | |
green_letters = input( | |
"Green letters? Use 'Letter,Position' format." | |
" Position starts at 1. One per line." | |
) | |
if not green_letters: | |
break | |
if "," not in green_letters: | |
print("Invalid input, must be in 'Letter,Position' format.") | |
continue | |
green_letter, green_position = green_letters.split(",") | |
green_position = int(green_position) - 1 | |
green_letter_positions.add((green_letter, green_position)) | |
has_letters.add(green_letter.upper()) | |
matching_words = find_matching_words( | |
missing_letters, | |
has_letters, | |
green_letter_positions, | |
yellow_letter_positions, | |
words, | |
) | |
# Make sure we don't accidentally add desired letters to the missing list | |
missing_letters = missing_letters.difference(has_letters) | |
print(f"Possible answers: {len(matching_words)}") | |
print_guesses(matching_words) | |
more_prompt = input("Show more guesses? (y/n) (Ctrl+C to quit)").lower() | |
while more_prompt == "y": | |
print_guesses(matching_words) | |
if __name__ == "__main__": | |
try: | |
main() | |
except KeyboardInterrupt: | |
print("") | |
pass |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment