Last active
November 14, 2022 15:35
-
-
Save klkuhlm/4b313fa0b7ba75e7f1eb59b6fe39714f to your computer and use it in GitHub Desktop.
This file contains 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
# already stripped out 2-letter words (too short by game rules) | |
# words originally sorted by length and then alphabetically | |
fh = open("wordlist.txt", "r") | |
words = [x.strip() for x in fh.readlines()] | |
fh.close() | |
sides = ["CSV", "EPO", "IFN", "RAD"] # all uppercase (like wordlist) | |
print(f" {sides[0]}") | |
print(f"{sides[3]} {sides[1]}") | |
print(f" {sides[2]}") | |
letterset = set() | |
for side in sides: | |
for letter in side: | |
letterset.add(letter) | |
print(letterset) | |
print(f"\nread in {len(words):,d} words from dictionary") | |
# 1) throw out words that use letters not in letterset | |
step_one = [] | |
for word in words: | |
for letter in word: | |
if letter not in letterset: | |
break | |
else: | |
step_one.append(word) | |
print( | |
f"{len(step_one):,d} words from 12-letter set " | |
f"({len(step_one)/len(words)*100:.1f}%)" | |
) | |
# 2) throw out words with letters repeated from a given side | |
step_two = [] | |
for word in step_one: | |
prev_side, fail = (-1, False) | |
for letter in word: | |
for idx, side in enumerate(sides): | |
if letter in side: | |
if idx == prev_side: | |
fail = True | |
break | |
else: | |
prev_side = idx | |
if fail: | |
break | |
else: | |
step_two.append(word) | |
print( | |
f"{len(step_two):,d} words with no repeated sides " | |
f"({len(step_two)/len(step_one)*100:.1f}%)\n" | |
) | |
matches = {} | |
# only searching for one and two-word solutions (start from long end) | |
for lword in reversed(step_two): | |
longwordset = set(lword) | |
# option A: longer word gets all letters | |
if len(longwordset) == 12: | |
matches[lword.lower()] = len(lword) | |
break | |
remain = letterset - longwordset | |
# starting on short end to find shortest word that uses remaining letters | |
for sword in step_two: | |
shortwordset = set(sword) | |
# option B: longer word comes first | |
# last letter of longer word is first of shorter | |
if sword[0] == lword[-1]: | |
if len(remain - shortwordset) == 0: | |
matches[f"{lword.lower()}->{sword.lower()}"] = len(lword) + len(sword) | |
break | |
# option C: shorter word comes first | |
# last letter of shorter word is first of longer | |
if sword[-1] == lword[0]: | |
if len(remain - shortwordset) == 0: | |
matches[f"{sword.lower()}->{lword.lower()}"] = len(lword) + len(sword) | |
break | |
sorted_matches = [k for k, v in sorted(matches.items(), key=lambda item: item[1])] | |
print("shortest 25 or fewer 1 & 2-word matches") | |
for i, val in enumerate(sorted_matches): | |
if i > 24: | |
break | |
print(i + 1, len(val.replace("->", "")), val.replace("->", " -> ")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment