Skip to content

Instantly share code, notes, and snippets.

@sillyfellow
Created March 27, 2022 00:33
Show Gist options
  • Save sillyfellow/3b4ffdff10e2d16d797395650038c3da to your computer and use it in GitHub Desktop.
Save sillyfellow/3b4ffdff10e2d16d797395650038c3da to your computer and use it in GitHub Desktop.
import operator
import re
import sys
import urllib.request
banner_read_sofar = """Type what you know so far.
Keep the Green ones where they are, and leave '.' for unknown: """
banner_grey_letters = """Type in the grey letters
All, or the new ones you learned in previous step: """
banner_green_pale_green = """Type in the green, and pale green letters
All, or the new ones you learned in previous step: """
def read_word_list(url, length=5, isalpha=True):
words = urllib.request.urlopen(url).read().decode("utf-8").split("\n")
def f(word):
if length and len(word) != length:
return False
if isalpha and not word.isalpha():
return False
return True
return list(filter(f, [word.lower() for word in words]))
def letter_frequency_map(words):
map: dict = dict([(chr(c), 0) for c in range(ord("a"), ord("z") + 1)])
for word in words:
for letter in word:
map[letter] += 1
return map
def calc_word_score_based_on_letter_frequency(word, l_frequencies):
s = 0
seen: set = set()
for letter in word:
if letter in seen:
continue
s += l_frequencies[letter]
seen.add(letter)
return s
def order_words_by_score(words):
word_score_pairs = [(word, calc_word_score_based_on_letter_frequency(word, letter_frequencies)) for word in words]
word_score_pairs.sort(key=operator.itemgetter(1), reverse=True)
return word_score_pairs
def short_list_word(word: str, sofar: str, has: set, has_not: set):
regex = re.compile(sofar)
matches = regex.match(word)
if not matches:
return False
word_set = set(word)
return word_set.intersection(has) == has and word_set.intersection(has_not) == set()
def read_letters(banner):
letters = str(input(banner))
letters = letters.lower()
if not letters.isalpha():
print("only letters can be input")
return None
return set(letters)
five_letter_words = read_word_list("https://raw.githubusercontent.com/dwyl/english-words/master/words.txt")
letter_frequencies = letter_frequency_map(five_letter_words)
words_ordered_by_score = order_words_by_score(five_letter_words)
set_of_all_words = set(five_letter_words)
has: set = set()
has_not: set = set()
sofar = "....."
while True:
sys.stdout.flush()
_sofar = str(input(banner_read_sofar))
# if we received something, that's the new one. Otherwise, continue with the old one.
if _sofar:
sofar = _sofar
if len(sofar) != 5:
print("Not a valid input. Length is not 5")
continue
if sofar.isalpha():
if sofar.lower() in set_of_all_words:
print("you have it already")
break
print("that's not even a real word. Try again")
continue
if not sofar.replace(".", "").isalpha():
print("input has to be just letters")
continue
sofar = sofar.lower()
new_has = read_letters(banner_green_pale_green)
if not new_has:
continue
has = new_has.union(has).union(set(sofar.replace(".", "")))
new_has_not = read_letters(banner_grey_letters)
if not new_has_not:
continue
has_not = set(new_has_not).union(has_not)
if len(has.intersection(has_not)) != 0:
print(f"you cannot add a letter in both sets {has.intersection(has_not)}. Restart")
print("==========================")
has = set()
has_not = set()
continue
print(f"going to look for {sofar}, with {has}, without {has_not}")
candidates: list = list(
filter(lambda word_pair: short_list_word(word_pair[0], sofar, has, has_not), words_ordered_by_score,)
)[:10]
c_string = "\n" + "\n".join([str(pair) for pair in candidates])
print(f"The best candidates are: {c_string}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment