Initial commit - play and solve
This commit is contained in:
commit
ff737bdb67
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
venv
|
||||
.idea
|
||||
__pycache__
|
16
lib.py
Normal file
16
lib.py
Normal file
@ -0,0 +1,16 @@
|
||||
DEBUG = False
|
||||
WORD_LENGTH = 5
|
||||
ROUNDS = 6
|
||||
INSTRUCTIONS = "Positional letters (green) are CAPITAL, non-positional (yellow) are small, others are blanks e.g. SHe-r"
|
||||
BLANK = "-"
|
||||
|
||||
|
||||
def cat_words():
|
||||
with open('/usr/share/dict/words') as f:
|
||||
for word in f.readlines():
|
||||
# remove end of line
|
||||
word = word[:-1]
|
||||
# filter out five letter words
|
||||
if len(word) == WORD_LENGTH and "'" not in word and not word[0].isupper():
|
||||
yield word
|
||||
|
64
play.py
Normal file
64
play.py
Normal file
@ -0,0 +1,64 @@
|
||||
import random
|
||||
|
||||
from lib import cat_words, INSTRUCTIONS, BLANK, ROUNDS, WORD_LENGTH
|
||||
|
||||
PLAY_INSTRUCTIONS = "Guess a 5-letter word, all lowercase. Hints will be given after the guess. " + INSTRUCTIONS
|
||||
|
||||
|
||||
def build_letter_hint(guess, word):
|
||||
guess_break = [letter for letter in guess]
|
||||
word_break = [letter for letter in word]
|
||||
letters_hints = [BLANK] * WORD_LENGTH
|
||||
for guess_pos, guess_letter in enumerate(guess):
|
||||
if word[guess_pos] == guess_letter:
|
||||
letters_hints[guess_pos] = guess_letter.upper()
|
||||
word_break[guess_pos] = BLANK
|
||||
guess_break[guess_pos] = BLANK
|
||||
# see test() - need to be more careful with repeating words
|
||||
for guess_pos, guess_letter in enumerate(guess_break):
|
||||
if guess_letter != BLANK and guess_letter in word_break:
|
||||
letters_hints[guess_pos] = guess_letter
|
||||
first_index = word_break.index(guess_letter)
|
||||
word_break[first_index] = BLANK
|
||||
return ''.join(letters_hints)
|
||||
|
||||
|
||||
def main_loop():
|
||||
word = random.choice([w for w in cat_words()])
|
||||
print(PLAY_INSTRUCTIONS)
|
||||
for round_number in range(ROUNDS):
|
||||
print("ROUND {}".format(round_number + 1))
|
||||
guess = input("Guess: ")
|
||||
if len(guess) != 5 and not all([x.islower() for x in guess]):
|
||||
print("ERROR: {}".format(PLAY_INSTRUCTIONS))
|
||||
non_letters_hints = ''
|
||||
for letter in guess:
|
||||
if letter not in word and letter not in non_letters_hints:
|
||||
non_letters_hints += letter
|
||||
letters_hints = build_letter_hint(guess, word)
|
||||
print("Non-letters: {}".format(non_letters_hints))
|
||||
print("Letters: {}".format(letters_hints))
|
||||
print("-" * 10)
|
||||
if all([x.isupper() for x in letters_hints]):
|
||||
print('WIN')
|
||||
break
|
||||
else:
|
||||
print("LOSE")
|
||||
print("Word was: {}".format(word))
|
||||
|
||||
|
||||
def main():
|
||||
main_loop()
|
||||
|
||||
|
||||
def test():
|
||||
assert build_letter_hint('yummy', 'slily') == '----Y'
|
||||
assert build_letter_hint('yummy', 'slyly') == 'y---Y'
|
||||
assert build_letter_hint('yymyy', 'slyyy') == 'y--YY'
|
||||
assert build_letter_hint('ymmyy', 'slyyy') == 'y--YY'
|
||||
assert build_letter_hint('mmmyy', 'slyyy') == '---YY'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test()
|
||||
main()
|
149
solve.py
Normal file
149
solve.py
Normal file
@ -0,0 +1,149 @@
|
||||
import random
|
||||
|
||||
from lib import cat_words, INSTRUCTIONS, BLANK, ROUNDS, DEBUG
|
||||
|
||||
|
||||
def remove_non_letters(word, non_letters):
|
||||
for non_letter in non_letters:
|
||||
if non_letter in word:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def remove_positional_letters(word, positional_letters):
|
||||
for pos_idx, positional_letter in enumerate(positional_letters):
|
||||
if positional_letter == BLANK:
|
||||
continue
|
||||
if positional_letter not in word:
|
||||
return True
|
||||
if word[pos_idx] != positional_letter:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def remove_non_positional_letters(word, non_positional_letters):
|
||||
for non_pos_idx, non_positional_letter in enumerate(non_positional_letters):
|
||||
if non_positional_letter == BLANK:
|
||||
continue
|
||||
if non_positional_letter not in word:
|
||||
return True
|
||||
if word[non_pos_idx] == non_positional_letter:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def round_words(non_letters, all_positional_letters, all_non_positional_letters):
|
||||
for word in cat_words():
|
||||
skip = remove_non_letters(word, non_letters)
|
||||
if skip:
|
||||
continue
|
||||
# Find positional letters, e.g. a----
|
||||
for positional_letters in all_positional_letters:
|
||||
skip = remove_positional_letters(word, positional_letters)
|
||||
if skip:
|
||||
break
|
||||
if skip:
|
||||
continue
|
||||
# Find non-positional letters, e.g. h-s--
|
||||
for non_positional_letters in all_non_positional_letters:
|
||||
skip = remove_non_positional_letters(word, non_positional_letters)
|
||||
if skip:
|
||||
break
|
||||
if skip:
|
||||
continue
|
||||
if not skip:
|
||||
yield word
|
||||
|
||||
|
||||
def first_round_words():
|
||||
for word in cat_words():
|
||||
word_break = [letter for letter in word]
|
||||
skip = False
|
||||
for letter in word_break:
|
||||
if word_break.count(letter) > 1:
|
||||
skip = True
|
||||
break
|
||||
if skip:
|
||||
continue
|
||||
yield word
|
||||
|
||||
|
||||
def resolve_positions(letters):
|
||||
positional_letters, non_positional_letters, is_good = '', '', True
|
||||
for letter in letters:
|
||||
if letter == BLANK:
|
||||
positional_letters += BLANK
|
||||
non_positional_letters += BLANK
|
||||
elif letter.isupper():
|
||||
positional_letters += letter.lower()
|
||||
non_positional_letters += BLANK
|
||||
elif letter.islower():
|
||||
positional_letters += BLANK
|
||||
non_positional_letters += letter
|
||||
else:
|
||||
print("ERROR: {}".format(INSTRUCTIONS))
|
||||
is_good = False
|
||||
return positional_letters, non_positional_letters, is_good
|
||||
|
||||
|
||||
def main_loop():
|
||||
all_non_letters = ''
|
||||
all_positional_letters = []
|
||||
all_non_positional_letters = []
|
||||
print(INSTRUCTIONS)
|
||||
for round_number in range(ROUNDS):
|
||||
if round_number == 0:
|
||||
this_round_words = [w for w in first_round_words()]
|
||||
else:
|
||||
this_round_words = [w for w in
|
||||
round_words(all_non_letters, all_positional_letters, all_non_positional_letters)]
|
||||
if DEBUG:
|
||||
for word in this_round_words:
|
||||
print(word)
|
||||
print("This round words: {}".format(len(this_round_words)))
|
||||
print("=" * 10)
|
||||
if len(this_round_words) == 0:
|
||||
print("ERROR: No known words left.")
|
||||
break
|
||||
if DEBUG:
|
||||
print("ALL Non-letters: {}".format(','.join(all_non_letters)))
|
||||
print("ALL Positional letters: {}".format(','.join(all_positional_letters)))
|
||||
print("ALL Non-Positional letters: {}".format(','.join(all_non_positional_letters)))
|
||||
print("Random word: {}".format(random.choice(this_round_words)))
|
||||
if len(this_round_words) == 1:
|
||||
print("That's all I got.")
|
||||
break
|
||||
print("=" * 10)
|
||||
print("ROUND {}".format(round_number + 1))
|
||||
print("-" * 10)
|
||||
while True:
|
||||
non_letters = input("Non letters: ")
|
||||
if not all([x.islower() for x in non_letters]):
|
||||
print("ERROR: {}".format(INSTRUCTIONS))
|
||||
continue
|
||||
break
|
||||
all_non_letters += non_letters
|
||||
while True:
|
||||
letters = input("Letters: ")
|
||||
if len(letters) != 5:
|
||||
print("ERROR: {}".format(INSTRUCTIONS))
|
||||
continue
|
||||
positional_letters, non_positional_letters, is_good = resolve_positions(letters)
|
||||
if is_good:
|
||||
all_positional_letters.append(positional_letters)
|
||||
all_non_positional_letters.append(non_positional_letters)
|
||||
break
|
||||
if all([letter.isupper for letter in letters]):
|
||||
print("WIN")
|
||||
else:
|
||||
print("Sorry. Remaining words: {}".format(len(this_round_words)))
|
||||
for word in this_round_words:
|
||||
print(word)
|
||||
|
||||
|
||||
def main():
|
||||
main_loop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user