Skip to content

Instantly share code, notes, and snippets.

@klkuhlm
Last active November 14, 2022 15:35
Show Gist options
  • Save klkuhlm/4b313fa0b7ba75e7f1eb59b6fe39714f to your computer and use it in GitHub Desktop.
Save klkuhlm/4b313fa0b7ba75e7f1eb59b6fe39714f to your computer and use it in GitHub Desktop.
# 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