web and fix some solve issues
This commit is contained in:
parent
74e5365a2c
commit
4648a39c13
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
venv
|
venv
|
||||||
.idea
|
.idea
|
||||||
__pycache__
|
__pycache__
|
||||||
|
sensitive.py
|
||||||
|
*.pyc
|
8
lib.py
8
lib.py
@ -1,3 +1,5 @@
|
|||||||
|
import string
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
WORD_LENGTH = 5
|
WORD_LENGTH = 5
|
||||||
ROUNDS = 6
|
ROUNDS = 6
|
||||||
@ -16,5 +18,9 @@ def cat_words(dictionary=DICTIONARY):
|
|||||||
# remove end of line
|
# remove end of line
|
||||||
word = word[:-1]
|
word = word[:-1]
|
||||||
# filter out five letter words
|
# filter out five letter words
|
||||||
if len(word) == WORD_LENGTH and all([letter.isalpha() and letter.islower() for letter in word]):
|
if len(word) == WORD_LENGTH and all([letter in string.ascii_lowercase for letter in word]):
|
||||||
yield word
|
yield word
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(len(list(cat_words())))
|
2
play.py
2
play.py
@ -22,6 +22,7 @@ def build_letter_hint(guess, word):
|
|||||||
word_break[first_index] = BLANK
|
word_break[first_index] = BLANK
|
||||||
return ''.join(letters_hints)
|
return ''.join(letters_hints)
|
||||||
|
|
||||||
|
|
||||||
def build_non_letter_hint(guess, word):
|
def build_non_letter_hint(guess, word):
|
||||||
non_letters_hints = ''
|
non_letters_hints = ''
|
||||||
for letter in guess:
|
for letter in guess:
|
||||||
@ -29,6 +30,7 @@ def build_non_letter_hint(guess, word):
|
|||||||
non_letters_hints += letter
|
non_letters_hints += letter
|
||||||
return non_letters_hints
|
return non_letters_hints
|
||||||
|
|
||||||
|
|
||||||
def main_loop():
|
def main_loop():
|
||||||
word = random.choice([w for w in cat_words()])
|
word = random.choice([w for w in cat_words()])
|
||||||
print(PLAY_INSTRUCTIONS)
|
print(PLAY_INSTRUCTIONS)
|
||||||
|
6
requirements.txt
Normal file
6
requirements.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
click==8.0.3
|
||||||
|
Flask==2.0.2
|
||||||
|
itsdangerous==2.0.1
|
||||||
|
Jinja2==3.0.3
|
||||||
|
MarkupSafe==2.0.1
|
||||||
|
Werkzeug==2.0.2
|
37
solve.py
37
solve.py
@ -3,22 +3,24 @@ import random
|
|||||||
from lib import cat_words, INSTRUCTIONS, BLANK, ROUNDS, DEBUG, DICTIONARY
|
from lib import cat_words, INSTRUCTIONS, BLANK, ROUNDS, DEBUG, DICTIONARY
|
||||||
|
|
||||||
|
|
||||||
def remove_non_letters(word, non_letters):
|
def remove_non_letters(word, non_letters, unconsumed_letters):
|
||||||
for non_letter in non_letters:
|
for non_letter in non_letters:
|
||||||
if non_letter in word:
|
if non_letter in word and non_letter in unconsumed_letters:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def remove_positional_letters(word, positional_letters):
|
def remove_positional_letters(word, positional_letters, ):
|
||||||
|
rv, unconsumed_letters = False, ''
|
||||||
for pos_idx, positional_letter in enumerate(positional_letters):
|
for pos_idx, positional_letter in enumerate(positional_letters):
|
||||||
if positional_letter == BLANK:
|
if positional_letter == BLANK:
|
||||||
|
unconsumed_letters += word[pos_idx]
|
||||||
continue
|
continue
|
||||||
if positional_letter not in word:
|
if positional_letter not in word:
|
||||||
return True
|
rv = True
|
||||||
if word[pos_idx] != positional_letter:
|
elif word[pos_idx] != positional_letter:
|
||||||
return True
|
rv = True
|
||||||
return False
|
return rv, unconsumed_letters
|
||||||
|
|
||||||
|
|
||||||
def remove_non_positional_letters(word, non_positional_letters):
|
def remove_non_positional_letters(word, non_positional_letters):
|
||||||
@ -34,12 +36,10 @@ def remove_non_positional_letters(word, non_positional_letters):
|
|||||||
|
|
||||||
def round_words(non_letters, all_positional_letters, all_non_positional_letters, dictionary=DICTIONARY):
|
def round_words(non_letters, all_positional_letters, all_non_positional_letters, dictionary=DICTIONARY):
|
||||||
for word in cat_words(dictionary):
|
for word in cat_words(dictionary):
|
||||||
skip = remove_non_letters(word, non_letters)
|
skip = False
|
||||||
if skip:
|
|
||||||
continue
|
|
||||||
# Find positional letters, e.g. a----
|
# Find positional letters, e.g. a----
|
||||||
for positional_letters in all_positional_letters:
|
for positional_letters in all_positional_letters:
|
||||||
skip = remove_positional_letters(word, positional_letters)
|
skip, unconsumed_letters = remove_positional_letters(word, positional_letters)
|
||||||
if skip:
|
if skip:
|
||||||
break
|
break
|
||||||
if skip:
|
if skip:
|
||||||
@ -49,6 +49,9 @@ def round_words(non_letters, all_positional_letters, all_non_positional_letters,
|
|||||||
skip = remove_non_positional_letters(word, non_positional_letters)
|
skip = remove_non_positional_letters(word, non_positional_letters)
|
||||||
if skip:
|
if skip:
|
||||||
break
|
break
|
||||||
|
if skip:
|
||||||
|
continue
|
||||||
|
skip = remove_non_letters(word, non_letters, unconsumed_letters)
|
||||||
if skip:
|
if skip:
|
||||||
continue
|
continue
|
||||||
if not skip:
|
if not skip:
|
||||||
@ -142,18 +145,26 @@ def main_loop():
|
|||||||
print(word)
|
print(word)
|
||||||
|
|
||||||
|
|
||||||
def test():
|
def find_word(search):
|
||||||
|
for i, word in enumerate(cat_words()):
|
||||||
|
if word == search:
|
||||||
|
print(i)
|
||||||
|
|
||||||
|
|
||||||
|
def do_test():
|
||||||
assert [w for w in round_words('', ['----y'], ['-----'], dictionary=['slily'])] == ['slily']
|
assert [w for w in round_words('', ['----y'], ['-----'], dictionary=['slily'])] == ['slily']
|
||||||
assert [w for w in round_words('', ['----y'], ['y----'], dictionary=['slyly'])] == ['slyly']
|
assert [w for w in round_words('', ['----y'], ['y----'], dictionary=['slyly'])] == ['slyly']
|
||||||
assert [w for w in round_words('', ['---yy'], ['y----'], dictionary=['slyyy'])] == ['slyyy']
|
assert [w for w in round_words('', ['---yy'], ['y----'], dictionary=['slyyy'])] == ['slyyy']
|
||||||
assert [w for w in round_words('', ['---yy'], ['-----'], dictionary=['slyyy'])] == ['slyyy']
|
assert [w for w in round_words('', ['---yy'], ['-----'], dictionary=['slyyy'])] == ['slyyy']
|
||||||
assert [w for w in round_words('', ['-y---'], ['--y--'], dictionary=['sysys'])] == ['sysys']
|
assert [w for w in round_words('', ['-y---'], ['--y--'], dictionary=['sysys'])] == ['sysys']
|
||||||
|
assert [w for w in round_words('nu', ['-o-ns'], ['-----'], dictionary=['towns'])] == ['towns']
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
test()
|
do_test()
|
||||||
main_loop()
|
main_loop()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
# find_word('towns')
|
||||||
main()
|
main()
|
||||||
|
22
templates/game.html
Normal file
22
templates/game.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
{% include "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<a href="{{ url_for('home') }}">home</a>
|
||||||
|
<hr>
|
||||||
|
<ul>
|
||||||
|
{% for guess in guesses %}
|
||||||
|
<li>
|
||||||
|
{% for letter, color in guess %}
|
||||||
|
<span class="letter" style="color:{{ color }};">{{ letter|upper }}</span>
|
||||||
|
{% endfor %}
|
||||||
|
</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% if state_playing %}
|
||||||
|
<form method="post" action="{{ url_for('make_guess') }}">
|
||||||
|
<input maxlength="5" minlength="5" size="5" name="guess" autofocus autocomplete="off"/>
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
{% else %}
|
||||||
|
<p>{{ state }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
9
templates/home.html
Normal file
9
templates/home.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% include "layout.html" %}
|
||||||
|
{% block body %}
|
||||||
|
<a href="{{url_for('init_random_game')}}">Random game</a>
|
||||||
|
<form method="post" action="{{url_for('init_deterministic_game')}}">
|
||||||
|
<label>Predefined (0 to {{ num_games }})</label>
|
||||||
|
<input type="number" min="0" max="{{ num_games }}" name="game_id" autofocus/>
|
||||||
|
<input type="submit">
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
47
templates/layout.html
Normal file
47
templates/layout.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>pi2-wordle</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: monospace;
|
||||||
|
background-color: black;
|
||||||
|
font-size: 26px;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
ul li {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.letter {
|
||||||
|
background-color: black;
|
||||||
|
border: 1px solid grey;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
font-family: monospace;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 26px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{% with messages = get_flashed_messages() %}
|
||||||
|
{% if messages %}
|
||||||
|
<ul>
|
||||||
|
{% for message in messages %}
|
||||||
|
<li style="color:red;">{{ message }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
|
{% endif %}
|
||||||
|
{% endwith %}
|
||||||
|
{% block body %}{% endblock %}
|
||||||
|
</body>
|
||||||
|
</html>
|
133
web.py
Normal file
133
web.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import random
|
||||||
|
from string import ascii_lowercase
|
||||||
|
|
||||||
|
from flask import Flask, render_template, session, request, redirect, url_for, flash
|
||||||
|
|
||||||
|
import sensitive
|
||||||
|
from lib import cat_words, ROUNDS
|
||||||
|
from play import build_non_letter_hint, build_letter_hint
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['SECRET_KEY'] = sensitive.SECRET_KEY
|
||||||
|
NUM_GAMES = 4593
|
||||||
|
GUESS_SPLITTER = '|'
|
||||||
|
STATE_PLAYING = 'PLAYING'
|
||||||
|
STATE_WIN = 'WIN'
|
||||||
|
STATE_LOSE = 'LOSE'
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def home():
|
||||||
|
num_games = NUM_GAMES # len(list(cat_words())) - 1
|
||||||
|
return render_template('home.html', num_games=num_games)
|
||||||
|
|
||||||
|
|
||||||
|
def init_game(word):
|
||||||
|
session['word'] = word
|
||||||
|
session['guesses'] = ''
|
||||||
|
session['state'] = STATE_PLAYING
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/init/random')
|
||||||
|
def init_random_game():
|
||||||
|
word = random.choice([w for w in cat_words()])
|
||||||
|
session['game_id'] = -1
|
||||||
|
init_game(word)
|
||||||
|
return redirect(url_for('random_game'))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/init/deterministic', methods=['post'])
|
||||||
|
def init_deterministic_game():
|
||||||
|
game_id = request.form.get('game_id')
|
||||||
|
if not game_id.isdigit() or not 0 < int(game_id) < NUM_GAMES:
|
||||||
|
flash("game_id must be between 0 and {}".format(NUM_GAMES))
|
||||||
|
return redirect(url_for('home'))
|
||||||
|
return redirect(url_for('init_deterministic_game_id', game_id=game_id))
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/init/deterministic/<int:game_id>')
|
||||||
|
def init_deterministic_game_id(game_id):
|
||||||
|
word = [w for w in cat_words()][int(game_id)]
|
||||||
|
session['game_id'] = game_id
|
||||||
|
init_game(word)
|
||||||
|
return redirect(url_for('deterministic_game_id', game_id=game_id))
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_guesses():
|
||||||
|
word = session['word']
|
||||||
|
guesses = session.get('guesses', '').split(GUESS_SPLITTER)
|
||||||
|
guesses_colored = []
|
||||||
|
for guess in guesses:
|
||||||
|
non_letters_hints = build_non_letter_hint(guess, word)
|
||||||
|
letters_hints = build_letter_hint(guess, word)
|
||||||
|
colored_guess = []
|
||||||
|
for pos, letter in enumerate(guess):
|
||||||
|
if letter in non_letters_hints:
|
||||||
|
color = 'grey'
|
||||||
|
elif letters_hints[pos] == letter.upper():
|
||||||
|
color = 'green'
|
||||||
|
elif letters_hints[pos] == letter:
|
||||||
|
color = 'yellow'
|
||||||
|
else:
|
||||||
|
color = 'grey'
|
||||||
|
colored_guess.append((letter, color))
|
||||||
|
guesses_colored.append(colored_guess)
|
||||||
|
return guesses_colored
|
||||||
|
|
||||||
|
|
||||||
|
def build_game_state():
|
||||||
|
guesses_colored = resolve_guesses()
|
||||||
|
return render_template('game.html',
|
||||||
|
guesses=guesses_colored,
|
||||||
|
state_playing=session['state'] == STATE_PLAYING,
|
||||||
|
state=session['state'])
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/random')
|
||||||
|
def random_game():
|
||||||
|
if 'word' not in session or 'state' not in session:
|
||||||
|
return redirect(url_for('init_random_game'))
|
||||||
|
return build_game_state()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/deterministic/<int:game_id>')
|
||||||
|
def deterministic_game_id(game_id):
|
||||||
|
if 'word' not in session or 'state' not in session:
|
||||||
|
return redirect(url_for('init_deterministic_game_id', game_id=game_id))
|
||||||
|
return build_game_state()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/guess', methods=['post'])
|
||||||
|
def make_guess():
|
||||||
|
if 'word' not in session or 'guesses' not in session:
|
||||||
|
flash('need a word')
|
||||||
|
return redirect(url_for('home'))
|
||||||
|
guess = request.form.get('guess')
|
||||||
|
if len(guess) != 5 and not all([x in ascii_lowercase for x in guess]):
|
||||||
|
flash("Make a 5 letter guess.")
|
||||||
|
return build_game_state()
|
||||||
|
if guess not in cat_words():
|
||||||
|
flash('Not in word list')
|
||||||
|
return build_game_state()
|
||||||
|
word = session['word']
|
||||||
|
round = len(session['guesses'].split(GUESS_SPLITTER))
|
||||||
|
if round >= ROUNDS:
|
||||||
|
session['state'] = STATE_LOSE
|
||||||
|
if guess == word:
|
||||||
|
session['state'] = STATE_WIN
|
||||||
|
session['guesses'] += '{}{}'.format(guess, GUESS_SPLITTER)
|
||||||
|
if 'game_id' not in session:
|
||||||
|
flash('no game_id')
|
||||||
|
return redirect(url_for('home'))
|
||||||
|
game_id = session['game_id']
|
||||||
|
if game_id == -1:
|
||||||
|
return redirect(url_for('random_game'))
|
||||||
|
return redirect(url_for('deterministic_game_id', game_id=game_id))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
app.run(debug=True)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
Loading…
Reference in New Issue
Block a user