Skip to content

Instantly share code, notes, and snippets.

@tyler-8
Last active January 23, 2022 04:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tyler-8/80281bea0489b991d97fdc10dcabfc6e to your computer and use it in GitHub Desktop.
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.
"""
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