Snapshot permission updates.

This commit is contained in:
dongar committed 2024-03-07 09:46:05 -06:00
1 parent 414380740f
commit d570b16b60
15 files changed
+540 -502

No files matched your search

+3 -3
View File
@@ -1,3 +1,3 @@
*.pyc *.pyc
.venv .venv
__pycache__ __pycache__
+24 -24
View File
@@ -1,24 +1,24 @@
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any binary, for any purpose, commercial or non-commercial, and by any
means. means.
In jurisdictions that recognize copyright laws, the author or authors In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this relinquishment in perpetuity of all present and future rights to this
software under copyright law. software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org> For more information, please refer to <http://unlicense.org>
+68 -68
View File
@@ -1,68 +1,68 @@
#!/usr/bin/python #!/usr/bin/python
from collections import defaultdict from collections import defaultdict
import dictionary import dictionary
from game import LetterResult from game import LetterResult
class Constraints: class Constraints:
def __init__(self): def __init__(self):
# Array of known letters in result with None for unknown. # Array of known letters in result with None for unknown.
self.correct = [None] * dictionary.WORDLE_LENGTH self.correct = [None] * dictionary.WORDLE_LENGTH
# Array with per-letter sets of known bad letters. # Array with per-letter sets of known bad letters.
self.incorrect = [set() for _ in range(dictionary.WORDLE_LENGTH)] self.incorrect = [set() for _ in range(dictionary.WORDLE_LENGTH)]
# Dict of letter -> int with minimum required count of letter in word. # Dict of letter -> int with minimum required count of letter in word.
self.count = defaultdict(int) self.count = defaultdict(int)
# If letter is present in set, value in min is both min and max. # If letter is present in set, value in min is both min and max.
self.exact = set() self.exact = set()
# List of LetterResult values. # List of LetterResult values.
def update_graded(self, guess, grade): def update_graded(self, guess, grade):
guess = guess.lower() guess = guess.lower()
new_count = defaultdict(int) new_count = defaultdict(int)
for i, letter in enumerate(guess): for i, letter in enumerate(guess):
match grade[i]: match grade[i]:
case LetterResult.CORRECT: case LetterResult.CORRECT:
self.correct[i] = letter self.correct[i] = letter
new_count[letter] += 1 new_count[letter] += 1
case LetterResult.MOVE: case LetterResult.MOVE:
self.incorrect[i].add(letter) self.incorrect[i].add(letter)
new_count[letter] += 1 new_count[letter] += 1
case LetterResult.INCORRECT: case LetterResult.INCORRECT:
self.incorrect[i].add(letter) self.incorrect[i].add(letter)
self.exact.add(letter) self.exact.add(letter)
new_count[letter] += 0 # Ensure letter is in dict new_count[letter] += 0 # Ensure letter is in dict
for letter, c in new_count.items(): for letter, c in new_count.items():
self.count[letter] = max(c, self.count[letter]) self.count[letter] = max(c, self.count[letter])
def matches(self, guess): def matches(self, guess):
counts = defaultdict(int) counts = defaultdict(int)
# All known correct letters in place. # All known correct letters in place.
for i, letter in enumerate(guess): for i, letter in enumerate(guess):
# If we have a known letter, and don't match... # If we have a known letter, and don't match...
if self.correct[i] and self.correct[i] != letter: if self.correct[i] and self.correct[i] != letter:
return False return False
# If we have a letter that's known to be incorrect in the current location... # If we have a letter that's known to be incorrect in the current location...
if letter in self.incorrect[i]: if letter in self.incorrect[i]:
return False return False
counts[letter] += 1 counts[letter] += 1
for letter, c in self.count.items(): for letter, c in self.count.items():
if letter in self.exact: if letter in self.exact:
if counts[letter] != c: if counts[letter] != c:
return False return False
else: else:
if counts[letter] < c: if counts[letter] < c:
return False return False
return True return True
def filter_words(self, words=dictionary.words()): def filter_words(self, words=dictionary.words()):
return set(filter(lambda w: self.matches(w), words)) return set(filter(lambda w: self.matches(w), words))
+64 -64
View File
@@ -1,64 +1,64 @@
#!/usr/bin/python #!/usr/bin/python
import dictionary import dictionary
import game import game
def display_instructions(): def display_instructions():
"""Print out instuctions before starting play.""" """Print out instuctions before starting play."""
print( print(
f"""Welcome to Wordle! f"""Welcome to Wordle!
Wordle has a hidden word of five letters, and you get to Wordle has a hidden word of five letters, and you get to
make up to six guesses to find out what it is. make up to six guesses to find out what it is.
After each guess, you get feedback on each letter of your guess. After each guess, you get feedback on each letter of your guess.
* {game.display_result(game.LetterResult.CORRECT, "Correct!")} * {game.display_result(game.LetterResult.CORRECT, "Correct!")}
* {game.display_result(game.LetterResult.MOVE, "Correct, in a different location.")} * {game.display_result(game.LetterResult.MOVE, "Correct, in a different location.")}
* {game.display_result(game.LetterResult.INCORRECT, "Not in the word.")} * {game.display_result(game.LetterResult.INCORRECT, "Not in the word.")}
""" """
) )
def read_valid_guess(guess_number): def read_valid_guess(guess_number):
while True: while True:
print(f"Guess {guess_number}: ", end="") print(f"Guess {guess_number}: ", end="")
guess = input() guess = input()
if guess in dictionary.words(): if guess in dictionary.words():
return guess return guess
print(f"{guess} is not a valid Wordle word. Please try again.") print(f"{guess} is not a valid Wordle word. Please try again.")
def display_results(guess, results): def display_results(guess, results):
print(" ", end="") print(" ", end="")
for i in range(dictionary.WORDLE_LENGTH): for i in range(dictionary.WORDLE_LENGTH):
print(game.display_result(results[i], guess[i]), end="") print(game.display_result(results[i], guess[i]), end="")
print("") print("")
def play_game(): def play_game():
display_instructions() display_instructions()
target = game.select_word() target = game.select_word()
# To help with debugging # To help with debugging
# print(f"The target is: {target}") # print(f"The target is: {target}")
for guess_number in range(1, 6): for guess_number in range(1, 6):
guess = read_valid_guess(guess_number) guess = read_valid_guess(guess_number)
results = game.grade_word(target, guess) results = game.grade_word(target, guess)
if game.success_result(results): if game.success_result(results):
print(f"You won! It took {guess_number} guesses.") print(f"You won! It took {guess_number} guesses.")
return return
display_results(guess, results) display_results(guess, results)
print(f"Sorry, no guesses remaining. The word was: {target}") print(f"Sorry, no guesses remaining. The word was: {target}")
if __name__ == "__main__": if __name__ == "__main__":
play_game() play_game()
+22 -3
View File
@@ -61,10 +61,29 @@ class SimilaritySolver(object):
for word in wordle_dictionary: for word in wordle_dictionary:
scored_words[word] = self._score_word(position_matches, word_matches, word) scored_words[word] = self._score_word(position_matches, word_matches, word)
result = list(wordle_dictionary) # Return as list of (word, score) sorted by high-score, word.
result.sort(key=lambda word: scored_words[word], reverse=True) result = sorted(scored_words.items(), key=lambda kv: kv[0])
result = sorted(result, key=lambda kv: kv[1], reverse=True)
return result
return [(word, scored_words[word]) for word in result]
class LimitsSolver(object):
def scored_words(self, words=dictionary.words()):
# word: score
scored_words = dict()
for word in words:
reduced = const.filter_words(words)
# Our score is how many words did we remove from consideration.
score = len(words) - len(reduced)
scored_words[word] = score
# Return as list of (word, score) sorted by high-score, word.
result = sorted(scored_words.items(), key=lambda kv: kv[0])
result = sorted(result, key=lambda kv: kv[1], reverse=True)
return result
if __name__ == "__main__": if __name__ == "__main__":
+26 -26
View File
@@ -1,27 +1,27 @@
.navbar { .navbar {
background-color: lightslategray; background-color: lightslategray;
font-size: 1em; font-size: 1em;
font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
color: white; color: white;
padding: 8px 5px 8px 5px; padding: 8px 5px 8px 5px;
} }
.navbar a { .navbar a {
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
} }
.navbar-brand { .navbar-brand {
font-size: 1.2em; font-size: 1.2em;
font-weight: 600; font-weight: 600;
} }
.navbar-item { .navbar-item {
font-variant: small-caps; font-variant: small-caps;
margin-left: 30px; margin-left: 30px;
} }
.body-content { .body-content {
padding: 5px; padding: 5px;
font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
} }
+23 -23
View File
@@ -1,23 +1,23 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %} {% block title %}
Dictionary Dictionary
{% endblock %} {% endblock %}
{% block content %} {% block content %}
{% if page > 0 %}<a href="{{ url_for('dictionary', page=page-1) }}">Prev</a>{% endif %} {% if page > 0 %}<a href="{{ url_for('dictionary', page=page-1) }}">Prev</a>{% endif %}
Page {{ page }} / {{ max_pages }} Page {{ page }} / {{ max_pages }}
{% if page < max_pages %}<a href="{{ url_for('dictionary', page=page+1) }}">Next</a>{% endif %} {% if page < max_pages %}<a href="{{ url_for('dictionary', page=page+1) }}">Next</a>{% endif %}
<ul> <ul>
{% for word in words %} {% for word in words %}
<li>{{ word }}</li> <li>{{ word }}</li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endblock %} {% endblock %}
+26 -26
View File
@@ -1,27 +1,27 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<title>{% block title %}{% endblock %}</title> <title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='site.css')}}" /> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='site.css')}}" />
</head> </head>
<body> <body>
<div class="navbar"> <div class="navbar">
<a href="{{ url_for('solver') }}" class="navbar-item">Home</a> <a href="{{ url_for('solver') }}" class="navbar-item">Home</a>
<a href="{{ url_for('dictionary') }}" class="navbar-item">Dictionary</a> <a href="{{ url_for('dictionary') }}" class="navbar-item">Dictionary</a>
</div> </div>
<div class="body-content"> <div class="body-content">
{% block content %} {% block content %}
{% endblock %} {% endblock %}
<hr /> <hr />
<footer> <footer>
This is not associated with the New York Times or the offical version of This is not associated with the New York Times or the offical version of
Wordle in any way. Wordle in any way.
</footer> </footer>
</div> </div>
</body> </body>
</html> </html>
+29 -29
View File
@@ -1,30 +1,30 @@
{% extends "layout.html" %} {% extends "layout.html" %}
{% block title %} {% block title %}
Solver! Solver!
{% endblock %} {% endblock %}
{% block content %} {% block content %}
<ul> <ul>
{% for guess in guesses %} {% for guess in guesses %}
<li>{{ guess }} <li>{{ guess }}
{% for i in range(5) %} {% for i in range(5) %}
<select name="g{{i}}" id="g{{i}}"> <select name="g{{i}}" id="g{{i}}">
<option value="U">Unknown</option> <option value="U">Unknown</option>
<option value="I">Incorrect</option> <option value="I">Incorrect</option>
<option value="M">Move</option> <option value="M">Move</option>
<option value="C">Correct</option> <option value="C">Correct</option>
</select> </select>
{% endfor %} {% endfor %}
</li> </li>
{% endfor %} {% endfor %}
</ul> </ul>
{%if solution %} {%if solution %}
The proposed solution is <b>{{ solution }}</b>. The proposed solution is <b>{{ solution }}</b>.
{% else %} {% else %}
No solution found. No solution found.
{% endif %} {% endif %}
{% endblock %} {% endblock %}
+81 -81
View File
@@ -1,81 +1,81 @@
#!/usr/bin/python #!/usr/bin/python
import unittest import unittest
import constraints import constraints
from game import LetterResult from game import LetterResult
class TestConstraints(unittest.TestCase): class TestConstraints(unittest.TestCase):
def test_empty(self): def test_empty(self):
consts = constraints.Constraints() consts = constraints.Constraints()
self.assertTrue(consts.matches("abcde")) self.assertTrue(consts.matches("abcde"))
self.assertTrue(consts.matches("bcdef")) self.assertTrue(consts.matches("bcdef"))
def test_correct(self): def test_correct(self):
consts = constraints.Constraints() consts = constraints.Constraints()
consts.update_graded( consts.update_graded(
"abcde", "abcde",
[ [
LetterResult.CORRECT, LetterResult.CORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
], ],
) )
self.assertTrue(consts.matches("amnop")) self.assertTrue(consts.matches("amnop"))
self.assertTrue(consts.matches("aaaaa")) self.assertTrue(consts.matches("aaaaa"))
self.assertFalse(consts.matches("abcde")) self.assertFalse(consts.matches("abcde"))
self.assertFalse(consts.matches("lmnop")) self.assertFalse(consts.matches("lmnop"))
self.assertFalse(consts.matches("aedcb")) self.assertFalse(consts.matches("aedcb"))
self.assertFalse(consts.matches("amnob")) self.assertFalse(consts.matches("amnob"))
def test_correct_count_limit(self): def test_correct_count_limit(self):
consts = constraints.Constraints() consts = constraints.Constraints()
consts.update_graded( consts.update_graded(
"aazzz", "aazzz",
[ [
LetterResult.CORRECT, LetterResult.CORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
], ],
) )
self.assertTrue(consts.matches("abcde")) self.assertTrue(consts.matches("abcde"))
self.assertTrue(consts.matches("abbbb")) self.assertTrue(consts.matches("abbbb"))
self.assertFalse(consts.matches("aabbb")) self.assertFalse(consts.matches("aabbb"))
self.assertFalse(consts.matches("abbba")) self.assertFalse(consts.matches("abbba"))
self.assertFalse(consts.matches("bbbbb")) self.assertFalse(consts.matches("bbbbb"))
self.assertFalse(consts.matches("bbbba")) self.assertFalse(consts.matches("bbbba"))
self.assertFalse(consts.matches("babbb")) self.assertFalse(consts.matches("babbb"))
def test_move(self): def test_move(self):
consts = constraints.Constraints() consts = constraints.Constraints()
consts.update_graded( consts.update_graded(
"abcde", "abcde",
[ [
LetterResult.MOVE, LetterResult.MOVE,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
LetterResult.INCORRECT, LetterResult.INCORRECT,
], ],
) )
self.assertTrue(consts.matches("zzzza")) self.assertTrue(consts.matches("zzzza"))
self.assertTrue(consts.matches("zzzaa")) self.assertTrue(consts.matches("zzzaa"))
self.assertTrue(consts.matches("zaaaa")) self.assertTrue(consts.matches("zaaaa"))
self.assertFalse(consts.matches("azzzz")) self.assertFalse(consts.matches("azzzz"))
self.assertFalse(consts.matches("zzzzz")) self.assertFalse(consts.matches("zzzzz"))
self.assertFalse(consts.matches("zzzba")) self.assertFalse(consts.matches("zzzba"))
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+34 -34
View File
@@ -1,34 +1,34 @@
#!/usr/bin/python #!/usr/bin/python
import unittest import unittest
import dictionary import dictionary
class TestDictionary(unittest.TestCase): class TestDictionary(unittest.TestCase):
def test_empty(self): def test_empty(self):
"""Verify we can get the default words.""" """Verify we can get the default words."""
words = dictionary.words() words = dictionary.words()
def test_expected(self): def test_expected(self):
"""Verify we have a few expected words.""" """Verify we have a few expected words."""
words = dictionary.words() words = dictionary.words()
self.assertIn("cares", words) self.assertIn("cares", words)
self.assertIn("fudge", words) self.assertIn("fudge", words)
def test_unexpected(self): def test_unexpected(self):
"""Verify we have a few expected words.""" """Verify we have a few expected words."""
words = dictionary.words() words = dictionary.words()
self.assertNotIn("doray", words) self.assertNotIn("doray", words)
self.assertNotIn("xxxxx", words) self.assertNotIn("xxxxx", words)
def test_size(self): def test_size(self):
"""Verify all words are the expected length.""" """Verify all words are the expected length."""
words = dictionary.words() words = dictionary.words()
for word in words: for word in words:
self.assertEqual(len(word), dictionary.WORDLE_LENGTH) self.assertEqual(len(word), dictionary.WORDLE_LENGTH)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+79 -79
View File
@@ -1,79 +1,79 @@
#!/usr/bin/python #!/usr/bin/python
import unittest import unittest
import dictionary import dictionary
import game import game
class TestGame(unittest.TestCase): class TestGame(unittest.TestCase):
test_words = ( test_words = (
"aaaaa", "aaaaa",
"aabbb", "aabbb",
"aaccc", "aaccc",
"bbbaa", "bbbaa",
"bbbbb", "bbbbb",
"ccaaa", "ccaaa",
"cccaa", "cccaa",
"ccccc", "ccccc",
"abcde", "abcde",
) )
def test_select_word(self): def test_select_word(self):
word = game.select_word(self.test_words) word = game.select_word(self.test_words)
self.assertIn(word, self.test_words) self.assertIn(word, self.test_words)
word = game.select_word() word = game.select_word()
self.assertIn(word, dictionary.words()) self.assertIn(word, dictionary.words())
def test_grade_word_correct(self): def test_grade_word_correct(self):
target = "aaaaa" target = "aaaaa"
guess = "aaaaa" guess = "aaaaa"
result = game.grade_word(target, guess, self.test_words) result = game.grade_word(target, guess, self.test_words)
expected = [ expected = [
game.LetterResult.CORRECT, game.LetterResult.CORRECT,
game.LetterResult.CORRECT, game.LetterResult.CORRECT,
game.LetterResult.CORRECT, game.LetterResult.CORRECT,
game.LetterResult.CORRECT, game.LetterResult.CORRECT,
game.LetterResult.CORRECT, game.LetterResult.CORRECT,
] ]
self.assertEqual(expected, result) self.assertEqual(expected, result)
self.assertTrue(game.success_result(result)) self.assertTrue(game.success_result(result))
def test_grade_word_mixed(self): def test_grade_word_mixed(self):
C = game.LetterResult.CORRECT C = game.LetterResult.CORRECT
M = game.LetterResult.MOVE M = game.LetterResult.MOVE
I = game.LetterResult.INCORRECT I = game.LetterResult.INCORRECT
test_cases = ( test_cases = (
("aabbb", "aabbb", [C, C, C, C, C]), ("aabbb", "aabbb", [C, C, C, C, C]),
("aabbb", "aaccc", [C, C, I, I, I]), ("aabbb", "aaccc", [C, C, I, I, I]),
("bbbaa", "cccaa", [I, I, I, C, C]), ("bbbaa", "cccaa", [I, I, I, C, C]),
("aabbb", "cccaa", [I, I, I, M, M]), ("aabbb", "cccaa", [I, I, I, M, M]),
("aabbb", "bbbaa", [M, M, C, M, M]), ("aabbb", "bbbaa", [M, M, C, M, M]),
("aabbb", "ccaaa", [I, I, M, M, I]), ("aabbb", "ccaaa", [I, I, M, M, I]),
("aabbb", "abcde", [C, M, I, I, I]), ("aabbb", "abcde", [C, M, I, I, I]),
("aabbb", "ccccc", [I, I, I, I, I]), ("aabbb", "ccccc", [I, I, I, I, I]),
) )
for target, guess, expected in test_cases: for target, guess, expected in test_cases:
result = game.grade_word(target, guess, self.test_words) result = game.grade_word(target, guess, self.test_words)
self.assertEqual(expected, result) self.assertEqual(expected, result)
def test_grade_word_invalid(self): def test_grade_word_invalid(self):
target = "aaaaa" target = "aaaaa"
guess = "inval" guess = "inval"
with self.assertRaises(Exception): with self.assertRaises(Exception):
game.grade_word(target, guess, self.test_words) game.grade_word(target, guess, self.test_words)
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+14 -14
View File
@@ -1,14 +1,14 @@
#!/usr/bin/python #!/usr/bin/python
import unittest import unittest
import play import play
class TestPlay(unittest.TestCase): class TestPlay(unittest.TestCase):
def test_noop(self): def test_noop(self):
"""Currently no tests for this code.""" """Currently no tests for this code."""
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()
+46 -27
View File
@@ -1,27 +1,46 @@
#!/usr/bin/python #!/usr/bin/python
import unittest import unittest
import solver import dictionary
import solver
class TestSolver(unittest.TestCase): test_dictionary = dictionary.words()
def test_SimilaritySolver(self):
"""Minimal end to end test."""
class TestSolver(unittest.TestCase):
solve = solver.SimilaritySolver() def test_SimilaritySolver(self):
result = solve.scored_words() """Minimal end to end test."""
expected = [ solve = solver.SimilaritySolver()
("cares", 139631), result = solve.scored_words(test_dictionary)
("sanes", 139129),
("tares", 138755), expected = [
("bares", 138375), ("cares", 139631),
("sales", 137491), ("sanes", 139129),
] ("tares", 138755),
("bares", 138375),
self.assertListEqual(result[:5], expected) ("sales", 137491),
]
if __name__ == "__main__": self.assertListEqual(result[:5], expected)
unittest.main()
def test_LimitsSolver(self):
"""Minimal end to end test."""
solve = solver.LimitsSolver()
result = solve.scored_words(test_dictionary)
expected = [
("aahed", 5),
("aalii", 5),
("aargh", 5),
("aaron", 5),
("abaca", 5),
]
self.assertListEqual(result[:5], expected)
if __name__ == "__main__":
unittest.main()
+1 -1
View File
@@ -9,7 +9,7 @@
"editor.defaultFormatter": "ms-python.black-formatter", "editor.defaultFormatter": "ms-python.black-formatter",
"editor.formatOnSave": true, "editor.formatOnSave": true,
"editor.codeActionsOnSave": { "editor.codeActionsOnSave": {
"source.organizeImports": true "source.organizeImports": "explicit"
}, },
}, },
"python.formatting.provider": "none", "python.formatting.provider": "none",