mirror of
https://codeberg.org/cblanken/boggler.git
synced 2026-07-26 11:35:10 -04:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a611f4a7e7 | ||
|
|
e183ce07c0 | ||
|
|
09e6f4a672 | ||
|
|
9036848168 | ||
|
|
a78b277516 | ||
|
|
a2630ed82e | ||
|
|
ab2869b858 | ||
|
|
d282cd3676 | ||
|
|
995a7f42c1 | ||
|
|
b4d7237c1f | ||
|
|
3b79ca7519 | ||
|
|
9e2cd55741 | ||
|
|
c0fe222832 | ||
|
|
6771ec9205 | ||
|
|
e1981c44de | ||
|
|
02bb7c4262 | ||
|
|
da00afb395 | ||
|
|
afaa378131 | ||
|
|
daebee948a | ||
|
|
2bc9d9fb9e | ||
|
|
7500720992 | ||
|
|
d81f5e28cc | ||
|
|
a0d60d280c | ||
|
|
ac58828521 | ||
|
|
59c5beb491 | ||
|
|
49cf552cc1 | ||
|
|
f0cee00bef | ||
|
|
843e167bf4 | ||
|
|
1a1f5acb17 | ||
|
|
2f795be626 | ||
|
|
6f4d4a69a0 | ||
|
|
82991e96e7 | ||
|
|
1386e1cace | ||
|
|
8c9ed00826 | ||
|
|
c09dce4bd6 | ||
|
|
a37548a4ee | ||
|
|
1dc118e953 | ||
|
|
6d3a58595c | ||
|
|
8b9dc89420 | ||
|
|
a80111072f | ||
|
|
fa01d442a5 | ||
|
|
733c1474b0 | ||
|
|
54f79c0afe | ||
|
|
9f364ee90e | ||
|
|
e219954ba6 | ||
|
|
f4accfe959 |
@@ -0,0 +1,12 @@
|
|||||||
|
exclude: '^.*\.board$'
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v2.3.0
|
||||||
|
hooks:
|
||||||
|
- id: check-yaml
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- repo: https://github.com/psf/black
|
||||||
|
rev: 22.10.0
|
||||||
|
hooks:
|
||||||
|
- id: black
|
||||||
@@ -5,12 +5,9 @@ A solver for the popular word game Boggle.
|
|||||||
```console
|
```console
|
||||||
pip install boggler
|
pip install boggler
|
||||||
```
|
```
|
||||||
OR
|
|
||||||
```console
|
|
||||||
git clone https://github.com/cblanken/boggler.git
|
|
||||||
```
|
|
||||||
|
|
||||||
To use the script to solve a particular Boggle board configuration, you'll need to do a few things
|
# Setup
|
||||||
|
To use the script to solve a Boggle board, you'll need to do a few things first.
|
||||||
1. Create `.csv` of the board state like so:
|
1. Create `.csv` of the board state like so:
|
||||||
|
|
||||||
Here is an example `board.csv`. Note the orientation of the board does not matter.
|
Here is an example `board.csv`. Note the orientation of the board does not matter.
|
||||||
@@ -21,7 +18,7 @@ To use the script to solve a particular Boggle board configuration, you'll need
|
|||||||
d,f,e,y
|
d,f,e,y
|
||||||
n,m,e,qu
|
n,m,e,qu
|
||||||
```
|
```
|
||||||
2. Find a dictionary wordlist file or create your own
|
2. Find or create a dictionary wordlist file
|
||||||
|
|
||||||
The dictionary wordlist should have each word on a single line like so
|
The dictionary wordlist should have each word on a single line like so
|
||||||
```console
|
```console
|
||||||
@@ -47,7 +44,7 @@ To use the script to solve a particular Boggle board configuration, you'll need
|
|||||||
|
|
||||||
3. Split the dictionary wordlist into separate files based on the first letter of each word.
|
3. Split the dictionary wordlist into separate files based on the first letter of each word.
|
||||||
|
|
||||||
To split an English wordlist the `split_wordlist_alpha.sh` script can be used like so:
|
To split an English wordlist, use the `split_wordlist_alpha.sh` script like so:
|
||||||
```console
|
```console
|
||||||
$ split_wordlist_alpha.sh my_wordlist.txt .
|
$ split_wordlist_alpha.sh my_wordlist.txt .
|
||||||
```
|
```
|
||||||
@@ -61,343 +58,334 @@ To use the script to solve a particular Boggle board configuration, you'll need
|
|||||||
```
|
```
|
||||||
|
|
||||||
# Usage
|
# Usage
|
||||||
```console
|
<details>
|
||||||
$ python boggler.py
|
<summary><h3 style="display: inline">CLI usage</h3></summary>
|
||||||
Usage: python3 boggler.py <BOARD_FILE> <WORDLISTS_DIR> [MAX_WORD_LENGTH]
|
<pre><code>$ poetry run boggler --help
|
||||||
$ python boggler.py board.csv wordlists/ 15
|
usage: boggler [-h] [-f FORMAT] [-p] [-s] [-d] board wordlists [max_word_length]
|
||||||
Reading in wordlists...
|
|
||||||
>> d: words_d.txt
|
Boggle board game solver
|
||||||
>> e: words_e.txt
|
|
||||||
>> f: words_f.txt
|
positional arguments:
|
||||||
>> m: words_m.txt
|
board Path to board CSV file
|
||||||
>> n: words_n.txt
|
wordlists Path to directory of wordlist files. The directory must contain text files of the form words_X.txt where "X" is a character of the
|
||||||
>> o: words_o.txt
|
alphabet
|
||||||
>> qu: words_q.txt
|
max_word_length Maximum length of words searched for on provided board
|
||||||
>> r: words_r.txt
|
|
||||||
>> s: words_s.txt
|
options:
|
||||||
>> v: words_v.txt
|
-h, --help show this help message and exit
|
||||||
>> y: words_y.txt
|
-f FORMAT, --format FORMAT
|
||||||
Generating WordTrees...
|
Specify alternative output format including [txt, json]
|
||||||
>> (0, 0): y
|
-p, --include-path Include full paths for each word in output
|
||||||
>> (0, 1): e
|
-s, --sort Sort output alphabetically. By default the results are sorted by the starting block position on the board from top-to-bottom, left-
|
||||||
>> (0, 2): o
|
to-right as given in the board file.
|
||||||
>> (0, 3): s
|
-d, --dedup Remove duplicates from word-only output. Note that de-duplication does not preserve the original order of the output, so it is
|
||||||
>> (1, 0): r
|
recommended to also use the sort option when de-duplicating.
|
||||||
>> (1, 1): e
|
</code></pre>
|
||||||
>> (1, 2): o
|
</details>
|
||||||
>> (1, 3): v
|
|
||||||
>> (2, 0): d
|
<details>
|
||||||
>> (2, 1): f
|
<summary><h3 style="display: inline">Example board solve</h3></summary>
|
||||||
>> (2, 2): e
|
<pre><code>$ poetry run boggler ./boggler/boards/b1.csv boggler/wordlists/scrabble_2019/
|
||||||
>> (2, 3): y
|
|
||||||
>> (3, 0): n
|
|
||||||
>> (3, 1): m
|
|
||||||
>> (3, 2): e
|
|
||||||
>> (3, 3): qu
|
|
||||||
|
|
||||||
BOARD
|
BOARD
|
||||||
+---------------+
|
+---------------+
|
||||||
| Y | E | O | S |
|
| S | A | I | P |
|
||||||
+---------------+
|
+---------------+
|
||||||
| R | E | O | V |
|
| L |QU | A | Y |
|
||||||
+---------------+
|
+---------------+
|
||||||
| D | F | E | Y |
|
| U | L | L | S |
|
||||||
+---------------+
|
+---------------+
|
||||||
| N | M | E |QU |
|
| O | W | H | A |
|
||||||
+---------------+
|
+---------------+
|
||||||
|
Starting @ (0, 0)
|
||||||
|
╭──────────┬──────────────────────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├──────────┼──────────────────────────────────────────────────────────────────┤
|
||||||
|
│ squall │ [(0, 0), (1, 1), (0, 1), (1, 0), (2, 1)] │
|
||||||
|
│ squall │ [(0, 0), (1, 1), (1, 2), (2, 2), (2, 1)] │
|
||||||
|
│ squall │ [(0, 0), (1, 1), (1, 2), (2, 1), (1, 0)] │
|
||||||
|
│ squall │ [(0, 0), (1, 1), (1, 2), (2, 1), (2, 2)] │
|
||||||
|
│ squally │ [(0, 0), (1, 1), (1, 2), (2, 1), (2, 2), (1, 3)] │
|
||||||
|
│ squalls │ [(0, 0), (1, 1), (1, 2), (2, 1), (2, 2), (2, 3)] │
|
||||||
|
│ squash │ [(0, 0), (1, 1), (1, 2), (2, 3), (3, 2)] │
|
||||||
|
│ sal │ [(0, 0), (0, 1), (1, 0)] │
|
||||||
|
│ sall │ [(0, 0), (0, 1), (1, 0), (2, 1)] │
|
||||||
|
│ sallal │ [(0, 0), (0, 1), (1, 0), (2, 1), (1, 2), (2, 2)] │
|
||||||
|
│ sallals │ [(0, 0), (0, 1), (1, 0), (2, 1), (1, 2), (2, 2), (2, 3)] │
|
||||||
|
│ sallow │ [(0, 0), (0, 1), (1, 0), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ sallowly │ [(0, 0), (0, 1), (1, 0), (2, 1), (3, 0), (3, 1), (2, 2), (1, 3)] │
|
||||||
|
│ sai │ [(0, 0), (0, 1), (0, 2)] │
|
||||||
|
╰──────────┴──────────────────────────────────────────────────────────────────╯
|
||||||
|
Starting @ (0, 1)
|
||||||
|
╭────────┬──────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├────────┼──────────────────────────────────────────────────┤
|
||||||
|
│ aqua │ [(0, 1), (1, 1), (1, 2)] │
|
||||||
|
│ aquas │ [(0, 1), (1, 1), (1, 2), (2, 3)] │
|
||||||
|
│ al │ [(0, 1), (1, 0)] │
|
||||||
|
│ als │ [(0, 1), (1, 0), (0, 0)] │
|
||||||
|
│ alu │ [(0, 1), (1, 0), (2, 0)] │
|
||||||
|
│ alula │ [(0, 1), (1, 0), (2, 0), (2, 1), (1, 2)] │
|
||||||
|
│ alulas │ [(0, 1), (1, 0), (2, 0), (2, 1), (1, 2), (2, 3)] │
|
||||||
|
│ all │ [(0, 1), (1, 0), (2, 1)] │
|
||||||
|
│ allay │ [(0, 1), (1, 0), (2, 1), (1, 2), (1, 3)] │
|
||||||
|
│ allays │ [(0, 1), (1, 0), (2, 1), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
│ allow │ [(0, 1), (1, 0), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ aa │ [(0, 1), (1, 2)] │
|
||||||
|
│ aal │ [(0, 1), (1, 2), (2, 2)] │
|
||||||
|
│ aals │ [(0, 1), (1, 2), (2, 2), (2, 3)] │
|
||||||
|
│ aal │ [(0, 1), (1, 2), (2, 1)] │
|
||||||
|
│ aas │ [(0, 1), (1, 2), (2, 3)] │
|
||||||
|
│ as │ [(0, 1), (0, 0)] │
|
||||||
|
│ ai │ [(0, 1), (0, 2)] │
|
||||||
|
│ aia │ [(0, 1), (0, 2), (1, 2)] │
|
||||||
|
│ aias │ [(0, 1), (0, 2), (1, 2), (2, 3)] │
|
||||||
|
╰────────┴──────────────────────────────────────────────────╯
|
||||||
|
Starting @ (0,2)
|
||||||
|
╭──────┬──────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├──────┼──────┤
|
||||||
|
╰──────┴──────╯
|
||||||
|
Starting @ (0, 3)
|
||||||
|
╭─────────┬──────────────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├─────────┼──────────────────────────────────────────────────────────┤
|
||||||
|
│ pya │ [(0, 3), (1, 3), (1, 2)] │
|
||||||
|
│ pyas │ [(0, 3), (1, 3), (1, 2), (2, 3)] │
|
||||||
|
│ pa │ [(0, 3), (1, 2)] │
|
||||||
|
│ paal │ [(0, 3), (1, 2), (0, 1), (1, 0)] │
|
||||||
|
│ paals │ [(0, 3), (1, 2), (0, 1), (1, 0), (0, 0)] │
|
||||||
|
│ pal │ [(0, 3), (1, 2), (2, 2)] │
|
||||||
|
│ paly │ [(0, 3), (1, 2), (2, 2), (1, 3)] │
|
||||||
|
│ palas │ [(0, 3), (1, 2), (2, 2), (3, 3), (2, 3)] │
|
||||||
|
│ pall │ [(0, 3), (1, 2), (2, 2), (2, 1)] │
|
||||||
|
│ pals │ [(0, 3), (1, 2), (2, 2), (2, 3)] │
|
||||||
|
│ palsy │ [(0, 3), (1, 2), (2, 2), (2, 3), (1, 3)] │
|
||||||
|
│ palsa │ [(0, 3), (1, 2), (2, 2), (2, 3), (3, 3)] │
|
||||||
|
│ pal │ [(0, 3), (1, 2), (2, 1)] │
|
||||||
|
│ pall │ [(0, 3), (1, 2), (2, 1), (1, 0)] │
|
||||||
|
│ palls │ [(0, 3), (1, 2), (2, 1), (1, 0), (0, 0)] │
|
||||||
|
│ palla │ [(0, 3), (1, 2), (2, 1), (1, 0), (0, 1)] │
|
||||||
|
│ pall │ [(0, 3), (1, 2), (2, 1), (2, 2)] │
|
||||||
|
│ pally │ [(0, 3), (1, 2), (2, 1), (2, 2), (1, 3)] │
|
||||||
|
│ palla │ [(0, 3), (1, 2), (2, 1), (2, 2), (3, 3)] │
|
||||||
|
│ pallah │ [(0, 3), (1, 2), (2, 1), (2, 2), (3, 3), (3, 2)] │
|
||||||
|
│ pallahs │ [(0, 3), (1, 2), (2, 1), (2, 2), (3, 3), (3, 2), (2, 3)] │
|
||||||
|
│ palls │ [(0, 3), (1, 2), (2, 1), (2, 2), (2, 3)] │
|
||||||
|
│ pas │ [(0, 3), (1, 2), (2, 3)] │
|
||||||
|
│ pash │ [(0, 3), (1, 2), (2, 3), (3, 2)] │
|
||||||
|
│ pasha │ [(0, 3), (1, 2), (2, 3), (3, 2), (3, 3)] │
|
||||||
|
│ pay │ [(0, 3), (1, 2), (1, 3)] │
|
||||||
|
│ pays │ [(0, 3), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
│ pi │ [(0, 3), (0, 2)] │
|
||||||
|
│ pia │ [(0, 3), (0, 2), (1, 2)] │
|
||||||
|
│ pial │ [(0, 3), (0, 2), (1, 2), (2, 2)] │
|
||||||
|
│ pial │ [(0, 3), (0, 2), (1, 2), (2, 1)] │
|
||||||
|
│ pias │ [(0, 3), (0, 2), (1, 2), (2, 3)] │
|
||||||
|
│ pia │ [(0, 3), (0, 2), (0, 1)] │
|
||||||
|
│ pial │ [(0, 3), (0, 2), (0, 1), (1, 0)] │
|
||||||
|
│ pias │ [(0, 3), (0, 2), (0, 1), (0, 0)] │
|
||||||
|
╰─────────┴──────────────────────────────────────────────────────────╯
|
||||||
|
Starting @ (1, 0)
|
||||||
|
╭───────┬──────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├───────┼──────────────────────────────────────────┤
|
||||||
|
│ la │ [(1, 0), (0, 1)] │
|
||||||
|
│ las │ [(1, 0), (0, 1), (0, 0)] │
|
||||||
|
│ lull │ [(1, 0), (2, 0), (2, 1), (2, 2)] │
|
||||||
|
│ lulls │ [(1, 0), (2, 0), (2, 1), (2, 2), (2, 3)] │
|
||||||
|
╰───────┴──────────────────────────────────────────╯
|
||||||
|
Starting @ (1, 1)
|
||||||
|
╭───────┬──────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├───────┼──────────────────────────────────┤
|
||||||
|
│ qua │ [(1, 1), (0, 1)] │
|
||||||
|
│ quai │ [(1, 1), (0, 1), (0, 2)] │
|
||||||
|
│ quip │ [(1, 1), (0, 2), (0, 3)] │
|
||||||
|
│ qua │ [(1, 1), (1, 2)] │
|
||||||
|
│ quai │ [(1, 1), (1, 2), (0, 2)] │
|
||||||
|
│ quash │ [(1, 1), (1, 2), (2, 3), (3, 2)] │
|
||||||
|
│ quay │ [(1, 1), (1, 2), (1, 3)] │
|
||||||
|
│ quays │ [(1, 1), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
╰───────┴──────────────────────────────────╯
|
||||||
|
Starting @ (1, 2)
|
||||||
|
╭────────┬──────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├────────┼──────────────────────────────────────────────────┤
|
||||||
|
│ ai │ [(1, 2), (0, 2)] │
|
||||||
|
│ aia │ [(1, 2), (0, 2), (0, 1)] │
|
||||||
|
│ aias │ [(1, 2), (0, 2), (0, 1), (0, 0)] │
|
||||||
|
│ aa │ [(1, 2), (0, 1)] │
|
||||||
|
│ aal │ [(1, 2), (0, 1), (1, 0)] │
|
||||||
|
│ aals │ [(1, 2), (0, 1), (1, 0), (0, 0)] │
|
||||||
|
│ aas │ [(1, 2), (0, 1), (0, 0)] │
|
||||||
|
│ al │ [(1, 2), (2, 2)] │
|
||||||
|
│ ala │ [(1, 2), (2, 2), (3, 3)] │
|
||||||
|
│ alas │ [(1, 2), (2, 2), (3, 3), (2, 3)] │
|
||||||
|
│ all │ [(1, 2), (2, 2), (2, 1)] │
|
||||||
|
│ allow │ [(1, 2), (2, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ als │ [(1, 2), (2, 2), (2, 3)] │
|
||||||
|
│ al │ [(1, 2), (2, 1)] │
|
||||||
|
│ all │ [(1, 2), (2, 1), (1, 0)] │
|
||||||
|
│ alls │ [(1, 2), (2, 1), (1, 0), (0, 0)] │
|
||||||
|
│ alow │ [(1, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ alu │ [(1, 2), (2, 1), (2, 0)] │
|
||||||
|
│ alula │ [(1, 2), (2, 1), (2, 0), (1, 0), (0, 1)] │
|
||||||
|
│ alulas │ [(1, 2), (2, 1), (2, 0), (1, 0), (0, 1), (0, 0)] │
|
||||||
|
│ all │ [(1, 2), (2, 1), (2, 2)] │
|
||||||
|
│ ally │ [(1, 2), (2, 1), (2, 2), (1, 3)] │
|
||||||
|
│ alls │ [(1, 2), (2, 1), (2, 2), (2, 3)] │
|
||||||
|
│ as │ [(1, 2), (2, 3)] │
|
||||||
|
│ asyla │ [(1, 2), (2, 3), (1, 3), (2, 2), (3, 3)] │
|
||||||
|
│ ash │ [(1, 2), (2, 3), (3, 2)] │
|
||||||
|
│ aqua │ [(1, 2), (1, 1), (0, 1)] │
|
||||||
|
│ aquas │ [(1, 2), (1, 1), (0, 1), (0, 0)] │
|
||||||
|
│ ay │ [(1, 2), (1, 3)] │
|
||||||
|
│ ays │ [(1, 2), (1, 3), (2, 3)] │
|
||||||
|
╰────────┴──────────────────────────────────────────────────╯
|
||||||
|
Starting @ (1, 3)
|
||||||
|
╭──────┬──────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├──────┼──────────────────────────┤
|
||||||
|
│ yip │ [(1, 3), (0, 2), (0, 3)] │
|
||||||
|
│ ya │ [(1, 3), (1, 2)] │
|
||||||
|
│ yap │ [(1, 3), (1, 2), (0, 3)] │
|
||||||
|
│ yas │ [(1, 3), (1, 2), (2, 3)] │
|
||||||
|
╰──────┴──────────────────────────╯
|
||||||
|
Starting @ (2, 0)
|
||||||
|
╭──────┬──────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├──────┼──────┤
|
||||||
|
╰──────┴──────╯
|
||||||
|
Starting @ (2, 1)
|
||||||
|
╭───────┬──────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├───────┼──────────────────────────────────────────┤
|
||||||
|
│ la │ [(2, 1), (1, 2)] │
|
||||||
|
│ lap │ [(2, 1), (1, 2), (0, 3)] │
|
||||||
|
│ las │ [(2, 1), (1, 2), (2, 3)] │
|
||||||
|
│ lash │ [(2, 1), (1, 2), (2, 3), (3, 2)] │
|
||||||
|
│ lay │ [(2, 1), (1, 2), (1, 3)] │
|
||||||
|
│ lays │ [(2, 1), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
│ lo │ [(2, 1), (3, 0)] │
|
||||||
|
│ lou │ [(2, 1), (3, 0), (2, 0)] │
|
||||||
|
│ low │ [(2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ lowly │ [(2, 1), (3, 0), (3, 1), (2, 2), (1, 3)] │
|
||||||
|
╰───────┴──────────────────────────────────────────╯
|
||||||
|
Starting @ (2, 2)
|
||||||
|
╭───────┬──────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├───────┼──────────────────────────────────────────┤
|
||||||
|
│ la │ [(2, 2), (1, 2)] │
|
||||||
|
│ lap │ [(2, 2), (1, 2), (0, 3)] │
|
||||||
|
│ lall │ [(2, 2), (1, 2), (2, 1), (1, 0)] │
|
||||||
|
│ lalls │ [(2, 2), (1, 2), (2, 1), (1, 0), (0, 0)] │
|
||||||
|
│ las │ [(2, 2), (1, 2), (2, 3)] │
|
||||||
|
│ lash │ [(2, 2), (1, 2), (2, 3), (3, 2)] │
|
||||||
|
│ lay │ [(2, 2), (1, 2), (1, 3)] │
|
||||||
|
│ lays │ [(2, 2), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
│ la │ [(2, 2), (3, 3)] │
|
||||||
|
│ las │ [(2, 2), (3, 3), (2, 3)] │
|
||||||
|
│ lash │ [(2, 2), (3, 3), (2, 3), (3, 2)] │
|
||||||
|
│ lah │ [(2, 2), (3, 3), (3, 2)] │
|
||||||
|
│ lahs │ [(2, 2), (3, 3), (3, 2), (2, 3)] │
|
||||||
|
╰───────┴──────────────────────────────────────────╯
|
||||||
|
Starting @ (2, 3)
|
||||||
|
╭─────────┬──────────────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├─────────┼──────────────────────────────────────────────────────────┤
|
||||||
|
│ sai │ [(2, 3), (1, 2), (0, 2)] │
|
||||||
|
│ sap │ [(2, 3), (1, 2), (0, 3)] │
|
||||||
|
│ sal │ [(2, 3), (1, 2), (2, 2)] │
|
||||||
|
│ sall │ [(2, 3), (1, 2), (2, 2), (2, 1)] │
|
||||||
|
│ sallow │ [(2, 3), (1, 2), (2, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ sal │ [(2, 3), (1, 2), (2, 1)] │
|
||||||
|
│ sall │ [(2, 3), (1, 2), (2, 1), (1, 0)] │
|
||||||
|
│ sall │ [(2, 3), (1, 2), (2, 1), (2, 2)] │
|
||||||
|
│ sally │ [(2, 3), (1, 2), (2, 1), (2, 2), (1, 3)] │
|
||||||
|
│ say │ [(2, 3), (1, 2), (1, 3)] │
|
||||||
|
│ sal │ [(2, 3), (3, 3), (2, 2)] │
|
||||||
|
│ salal │ [(2, 3), (3, 3), (2, 2), (1, 2), (2, 1)] │
|
||||||
|
│ sall │ [(2, 3), (3, 3), (2, 2), (2, 1)] │
|
||||||
|
│ sallow │ [(2, 3), (3, 3), (2, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ sh │ [(2, 3), (3, 2)] │
|
||||||
|
│ sha │ [(2, 3), (3, 2), (3, 3)] │
|
||||||
|
│ shaly │ [(2, 3), (3, 2), (3, 3), (2, 2), (1, 3)] │
|
||||||
|
│ shall │ [(2, 3), (3, 2), (3, 3), (2, 2), (2, 1)] │
|
||||||
|
│ shallow │ [(2, 3), (3, 2), (3, 3), (2, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ slap │ [(2, 3), (2, 2), (1, 2), (0, 3)] │
|
||||||
|
│ slay │ [(2, 3), (2, 2), (1, 2), (1, 3)] │
|
||||||
|
│ sly │ [(2, 3), (2, 2), (1, 3)] │
|
||||||
|
╰─────────┴──────────────────────────────────────────────────────────╯
|
||||||
|
Starting @ (3, 0)
|
||||||
|
╭───────┬──────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├───────┼──────────────────────────────────────────┤
|
||||||
|
│ ou │ [(3, 0), (2, 0)] │
|
||||||
|
│ olla │ [(3, 0), (2, 1), (1, 0), (0, 1)] │
|
||||||
|
│ ollas │ [(3, 0), (2, 1), (1, 0), (0, 1), (0, 0)] │
|
||||||
|
│ olla │ [(3, 0), (2, 1), (2, 2), (1, 2)] │
|
||||||
|
│ ollas │ [(3, 0), (2, 1), (2, 2), (1, 2), (2, 3)] │
|
||||||
|
│ olla │ [(3, 0), (2, 1), (2, 2), (3, 3)] │
|
||||||
|
│ ollas │ [(3, 0), (2, 1), (2, 2), (3, 3), (2, 3)] │
|
||||||
|
│ ow │ [(3, 0), (3, 1)] │
|
||||||
|
│ owl │ [(3, 0), (3, 1), (2, 1)] │
|
||||||
|
│ owl │ [(3, 0), (3, 1), (2, 2)] │
|
||||||
|
│ owly │ [(3, 0), (3, 1), (2, 2), (1, 3)] │
|
||||||
|
│ owls │ [(3, 0), (3, 1), (2, 2), (2, 3)] │
|
||||||
|
╰───────┴──────────────────────────────────────────╯
|
||||||
|
Starting @ (3, 1)
|
||||||
|
╭───────┬──────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├───────┼──────────────────────────────────────────┤
|
||||||
|
│ wull │ [(3, 1), (2, 0), (1, 0), (2, 1)] │
|
||||||
|
│ wull │ [(3, 1), (2, 0), (2, 1), (1, 0)] │
|
||||||
|
│ wulls │ [(3, 1), (2, 0), (2, 1), (1, 0), (0, 0)] │
|
||||||
|
│ wull │ [(3, 1), (2, 0), (2, 1), (2, 2)] │
|
||||||
|
│ wulls │ [(3, 1), (2, 0), (2, 1), (2, 2), (2, 3)] │
|
||||||
|
│ wo │ [(3, 1), (3, 0)] │
|
||||||
|
│ wolly │ [(3, 1), (3, 0), (2, 1), (2, 2), (1, 3)] │
|
||||||
|
│ wha │ [(3, 1), (3, 2), (3, 3)] │
|
||||||
|
╰───────┴──────────────────────────────────────────╯
|
||||||
|
Starting @ (3, 2)
|
||||||
|
╭────────┬──────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├────────┼──────────────────────────────────────────────────┤
|
||||||
|
│ ha │ [(3, 2), (3, 3)] │
|
||||||
|
│ has │ [(3, 2), (3, 3), (2, 3)] │
|
||||||
|
│ halal │ [(3, 2), (3, 3), (2, 2), (1, 2), (2, 1)] │
|
||||||
|
│ hall │ [(3, 2), (3, 3), (2, 2), (2, 1)] │
|
||||||
|
│ hallo │ [(3, 2), (3, 3), (2, 2), (2, 1), (3, 0)] │
|
||||||
|
│ hallow │ [(3, 2), (3, 3), (2, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
╰────────┴──────────────────────────────────────────────────╯
|
||||||
|
Starting @ (3, 3)
|
||||||
|
╭────────┬──────────────────────────────────────────────────╮
|
||||||
|
│ Word │ Path │
|
||||||
|
├────────┼──────────────────────────────────────────────────┤
|
||||||
|
│ as │ [(3, 3), (2, 3)] │
|
||||||
|
│ asyla │ [(3, 3), (2, 3), (1, 3), (2, 2), (1, 2)] │
|
||||||
|
│ ash │ [(3, 3), (2, 3), (3, 2)] │
|
||||||
|
│ al │ [(3, 3), (2, 2)] │
|
||||||
|
│ ala │ [(3, 3), (2, 2), (1, 2)] │
|
||||||
|
│ alap │ [(3, 3), (2, 2), (1, 2), (0, 3)] │
|
||||||
|
│ alas │ [(3, 3), (2, 2), (1, 2), (2, 3)] │
|
||||||
|
│ alay │ [(3, 3), (2, 2), (1, 2), (1, 3)] │
|
||||||
|
│ alays │ [(3, 3), (2, 2), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
│ all │ [(3, 3), (2, 2), (2, 1)] │
|
||||||
|
│ allay │ [(3, 3), (2, 2), (2, 1), (1, 2), (1, 3)] │
|
||||||
|
│ allays │ [(3, 3), (2, 2), (2, 1), (1, 2), (1, 3), (2, 3)] │
|
||||||
|
│ allow │ [(3, 3), (2, 2), (2, 1), (3, 0), (3, 1)] │
|
||||||
|
│ als │ [(3, 3), (2, 2), (2, 3)] │
|
||||||
|
│ ah │ [(3, 3), (3, 2)] │
|
||||||
|
│ ahs │ [(3, 3), (3, 2), (2, 3)] │
|
||||||
|
╰────────┴──────────────────────────────────────────────────╯
|
||||||
|
</code></pre>
|
||||||
|
</details>
|
||||||
|
<br>
|
||||||
|
|
||||||
|
# Build
|
||||||
Starting @ (0, 0)...
|
Navigate to the project root folder and run the following.
|
||||||
y : [(0, 0)]
|
Run `poetry build`
|
||||||
yr : [(0, 0), (1, 0)]
|
|
||||||
ye : [(0, 0), (1, 1)]
|
|
||||||
yee : [(0, 0), (1, 1), (0, 1)]
|
|
||||||
yeo : [(0, 0), (1, 1), (0, 2)]
|
|
||||||
yed : [(0, 0), (1, 1), (2, 0)]
|
|
||||||
yee : [(0, 0), (1, 1), (2, 2)]
|
|
||||||
yer : [(0, 0), (1, 1), (1, 0)]
|
|
||||||
yere : [(0, 0), (1, 1), (1, 0), (0, 1)]
|
|
||||||
yerd : [(0, 0), (1, 1), (1, 0), (2, 0)]
|
|
||||||
yeo : [(0, 0), (1, 1), (1, 2)]
|
|
||||||
ye : [(0, 0), (0, 1)]
|
|
||||||
yee : [(0, 0), (0, 1), (1, 1)]
|
|
||||||
yer : [(0, 0), (0, 1), (1, 0)]
|
|
||||||
yerd : [(0, 0), (0, 1), (1, 0), (2, 0)]
|
|
||||||
yere : [(0, 0), (0, 1), (1, 0), (1, 1)]
|
|
||||||
yeo : [(0, 0), (0, 1), (1, 2)]
|
|
||||||
yeo : [(0, 0), (0, 1), (0, 2)]
|
|
||||||
|
|
||||||
Starting @ (0, 1)...
|
|
||||||
e : [(0, 1)]
|
|
||||||
ee : [(0, 1), (1, 1)]
|
|
||||||
eer : [(0, 1), (1, 1), (1, 0)]
|
|
||||||
eery : [(0, 1), (1, 1), (1, 0), (0, 0)]
|
|
||||||
er : [(0, 1), (1, 0)]
|
|
||||||
erd : [(0, 1), (1, 0), (2, 0)]
|
|
||||||
erf : [(0, 1), (1, 0), (2, 1)]
|
|
||||||
ere : [(0, 1), (1, 0), (1, 1)]
|
|
||||||
eo : [(0, 1), (1, 2)]
|
|
||||||
eos : [(0, 1), (1, 2), (0, 3)]
|
|
||||||
eof : [(0, 1), (1, 2), (2, 1)]
|
|
||||||
ey : [(0, 1), (0, 0)]
|
|
||||||
eyr : [(0, 1), (0, 0), (1, 0)]
|
|
||||||
eyre : [(0, 1), (0, 0), (1, 0), (1, 1)]
|
|
||||||
eye : [(0, 1), (0, 0), (1, 1)]
|
|
||||||
eyed : [(0, 1), (0, 0), (1, 1), (2, 0)]
|
|
||||||
eyer : [(0, 1), (0, 0), (1, 1), (1, 0)]
|
|
||||||
eo : [(0, 1), (0, 2)]
|
|
||||||
eos : [(0, 1), (0, 2), (0, 3)]
|
|
||||||
|
|
||||||
Starting @ (0, 2)...
|
|
||||||
o : [(0, 2)]
|
|
||||||
oos : [(0, 2), (1, 2), (0, 3)]
|
|
||||||
oof : [(0, 2), (1, 2), (2, 1)]
|
|
||||||
oe : [(0, 2), (1, 1)]
|
|
||||||
oer : [(0, 2), (1, 1), (1, 0)]
|
|
||||||
ovey : [(0, 2), (1, 3), (2, 2), (2, 3)]
|
|
||||||
oe : [(0, 2), (0, 1)]
|
|
||||||
oer : [(0, 2), (0, 1), (1, 0)]
|
|
||||||
os : [(0, 2), (0, 3)]
|
|
||||||
|
|
||||||
Starting @ (0, 3)...
|
|
||||||
s : [(0, 3)]
|
|
||||||
sv : [(0, 3), (1, 3)]
|
|
||||||
so : [(0, 3), (1, 2)]
|
|
||||||
sooey : [(0, 3), (1, 2), (0, 2), (1, 1), (0, 0)]
|
|
||||||
sooey : [(0, 3), (1, 2), (0, 2), (0, 1), (0, 0)]
|
|
||||||
soe : [(0, 3), (1, 2), (0, 1)]
|
|
||||||
soe : [(0, 3), (1, 2), (2, 2)]
|
|
||||||
sofer : [(0, 3), (1, 2), (2, 1), (1, 1), (1, 0)]
|
|
||||||
soy : [(0, 3), (1, 2), (2, 3)]
|
|
||||||
soe : [(0, 3), (1, 2), (1, 1)]
|
|
||||||
sov : [(0, 3), (1, 2), (1, 3)]
|
|
||||||
so : [(0, 3), (0, 2)]
|
|
||||||
sooey : [(0, 3), (0, 2), (1, 2), (0, 1), (0, 0)]
|
|
||||||
sooey : [(0, 3), (0, 2), (1, 2), (2, 2), (2, 3)]
|
|
||||||
sooey : [(0, 3), (0, 2), (1, 2), (1, 1), (0, 0)]
|
|
||||||
soe : [(0, 3), (0, 2), (1, 1)]
|
|
||||||
sov : [(0, 3), (0, 2), (1, 3)]
|
|
||||||
soe : [(0, 3), (0, 2), (0, 1)]
|
|
||||||
|
|
||||||
Starting @ (1, 0)...
|
|
||||||
r : [(1, 0)]
|
|
||||||
rye : [(1, 0), (0, 0), (1, 1)]
|
|
||||||
rye : [(1, 0), (0, 0), (0, 1)]
|
|
||||||
re : [(1, 0), (0, 1)]
|
|
||||||
ree : [(1, 0), (0, 1), (1, 1)]
|
|
||||||
reef : [(1, 0), (0, 1), (1, 1), (2, 1)]
|
|
||||||
reed : [(1, 0), (0, 1), (1, 1), (2, 0)]
|
|
||||||
rd : [(1, 0), (2, 0)]
|
|
||||||
rf : [(1, 0), (2, 1)]
|
|
||||||
re : [(1, 0), (1, 1)]
|
|
||||||
ree : [(1, 0), (1, 1), (0, 1)]
|
|
||||||
ref : [(1, 0), (1, 1), (2, 1)]
|
|
||||||
red : [(1, 0), (1, 1), (2, 0)]
|
|
||||||
ree : [(1, 0), (1, 1), (2, 2)]
|
|
||||||
reem : [(1, 0), (1, 1), (2, 2), (3, 1)]
|
|
||||||
reef : [(1, 0), (1, 1), (2, 2), (2, 1)]
|
|
||||||
|
|
||||||
Starting @ (1, 1)...
|
|
||||||
e : [(1, 1)]
|
|
||||||
ee : [(1, 1), (0, 1)]
|
|
||||||
eer : [(1, 1), (0, 1), (1, 0)]
|
|
||||||
eery : [(1, 1), (0, 1), (1, 0), (0, 0)]
|
|
||||||
ey : [(1, 1), (0, 0)]
|
|
||||||
eyr : [(1, 1), (0, 0), (1, 0)]
|
|
||||||
eyre : [(1, 1), (0, 0), (1, 0), (0, 1)]
|
|
||||||
eye : [(1, 1), (0, 0), (0, 1)]
|
|
||||||
eyer : [(1, 1), (0, 0), (0, 1), (1, 0)]
|
|
||||||
eo : [(1, 1), (0, 2)]
|
|
||||||
eos : [(1, 1), (0, 2), (0, 3)]
|
|
||||||
ef : [(1, 1), (2, 1)]
|
|
||||||
ed : [(1, 1), (2, 0)]
|
|
||||||
ee : [(1, 1), (2, 2)]
|
|
||||||
er : [(1, 1), (1, 0)]
|
|
||||||
ere : [(1, 1), (1, 0), (0, 1)]
|
|
||||||
erd : [(1, 1), (1, 0), (2, 0)]
|
|
||||||
erf : [(1, 1), (1, 0), (2, 1)]
|
|
||||||
eo : [(1, 1), (1, 2)]
|
|
||||||
eos : [(1, 1), (1, 2), (0, 3)]
|
|
||||||
eof : [(1, 1), (1, 2), (2, 1)]
|
|
||||||
|
|
||||||
Starting @ (1, 2)...
|
|
||||||
o : [(1, 2)]
|
|
||||||
oos : [(1, 2), (0, 2), (0, 3)]
|
|
||||||
oe : [(1, 2), (0, 1)]
|
|
||||||
oer : [(1, 2), (0, 1), (1, 0)]
|
|
||||||
os : [(1, 2), (0, 3)]
|
|
||||||
oe : [(1, 2), (2, 2)]
|
|
||||||
of : [(1, 2), (2, 1)]
|
|
||||||
ofer : [(1, 2), (2, 1), (1, 1), (1, 0)]
|
|
||||||
oy : [(1, 2), (2, 3)]
|
|
||||||
oe : [(1, 2), (1, 1)]
|
|
||||||
oer : [(1, 2), (1, 1), (1, 0)]
|
|
||||||
ovey : [(1, 2), (1, 3), (2, 2), (2, 3)]
|
|
||||||
|
|
||||||
Starting @ (1, 3)...
|
|
||||||
v : [(1, 3)]
|
|
||||||
vs : [(1, 3), (0, 3)]
|
|
||||||
vo : [(1, 3), (0, 2)]
|
|
||||||
voe : [(1, 3), (0, 2), (1, 1)]
|
|
||||||
voe : [(1, 3), (0, 2), (0, 1)]
|
|
||||||
vee : [(1, 3), (2, 2), (1, 1)]
|
|
||||||
veer : [(1, 3), (2, 2), (1, 1), (1, 0)]
|
|
||||||
veery : [(1, 3), (2, 2), (1, 1), (1, 0), (0, 0)]
|
|
||||||
vee : [(1, 3), (2, 2), (3, 2)]
|
|
||||||
vefry : [(1, 3), (2, 2), (2, 1), (1, 0), (0, 0)]
|
|
||||||
vo : [(1, 3), (1, 2)]
|
|
||||||
voe : [(1, 3), (1, 2), (0, 1)]
|
|
||||||
voe : [(1, 3), (1, 2), (2, 2)]
|
|
||||||
voe : [(1, 3), (1, 2), (1, 1)]
|
|
||||||
|
|
||||||
Starting @ (2, 0)...
|
|
||||||
d : [(2, 0)]
|
|
||||||
dr : [(2, 0), (1, 0)]
|
|
||||||
dry : [(2, 0), (1, 0), (0, 0)]
|
|
||||||
dree : [(2, 0), (1, 0), (0, 1), (1, 1)]
|
|
||||||
drey : [(2, 0), (1, 0), (0, 1), (0, 0)]
|
|
||||||
dree : [(2, 0), (1, 0), (1, 1), (0, 1)]
|
|
||||||
drey : [(2, 0), (1, 0), (1, 1), (0, 0)]
|
|
||||||
dree : [(2, 0), (1, 0), (1, 1), (2, 2)]
|
|
||||||
de : [(2, 0), (1, 1)]
|
|
||||||
dee : [(2, 0), (1, 1), (0, 1)]
|
|
||||||
deer : [(2, 0), (1, 1), (0, 1), (1, 0)]
|
|
||||||
dey : [(2, 0), (1, 1), (0, 0)]
|
|
||||||
def : [(2, 0), (1, 1), (2, 1)]
|
|
||||||
dee : [(2, 0), (1, 1), (2, 2)]
|
|
||||||
deem : [(2, 0), (1, 1), (2, 2), (3, 1)]
|
|
||||||
der : [(2, 0), (1, 1), (1, 0)]
|
|
||||||
dere : [(2, 0), (1, 1), (1, 0), (0, 1)]
|
|
||||||
derf : [(2, 0), (1, 1), (1, 0), (2, 1)]
|
|
||||||
dn : [(2, 0), (3, 0)]
|
|
||||||
dm : [(2, 0), (3, 1)]
|
|
||||||
|
|
||||||
Starting @ (2, 1)...
|
|
||||||
f : [(2, 1)]
|
|
||||||
fe : [(2, 1), (1, 1)]
|
|
||||||
fee : [(2, 1), (1, 1), (0, 1)]
|
|
||||||
feer : [(2, 1), (1, 1), (0, 1), (1, 0)]
|
|
||||||
fey : [(2, 1), (1, 1), (0, 0)]
|
|
||||||
feyer : [(2, 1), (1, 1), (0, 0), (0, 1), (1, 0)]
|
|
||||||
fed : [(2, 1), (1, 1), (2, 0)]
|
|
||||||
fedn : [(2, 1), (1, 1), (2, 0), (3, 0)]
|
|
||||||
fee : [(2, 1), (1, 1), (2, 2)]
|
|
||||||
fer : [(2, 1), (1, 1), (1, 0)]
|
|
||||||
fere : [(2, 1), (1, 1), (1, 0), (0, 1)]
|
|
||||||
ferd : [(2, 1), (1, 1), (1, 0), (2, 0)]
|
|
||||||
fr : [(2, 1), (1, 0)]
|
|
||||||
fry : [(2, 1), (1, 0), (0, 0)]
|
|
||||||
free : [(2, 1), (1, 0), (0, 1), (1, 1)]
|
|
||||||
freed : [(2, 1), (1, 0), (0, 1), (1, 1), (2, 0)]
|
|
||||||
frey : [(2, 1), (1, 0), (0, 1), (0, 0)]
|
|
||||||
free : [(2, 1), (1, 0), (1, 1), (0, 1)]
|
|
||||||
frey : [(2, 1), (1, 0), (1, 1), (0, 0)]
|
|
||||||
fred : [(2, 1), (1, 0), (1, 1), (2, 0)]
|
|
||||||
free : [(2, 1), (1, 0), (1, 1), (2, 2)]
|
|
||||||
fo : [(2, 1), (1, 2)]
|
|
||||||
foo : [(2, 1), (1, 2), (0, 2)]
|
|
||||||
foe : [(2, 1), (1, 2), (0, 1)]
|
|
||||||
foe : [(2, 1), (1, 2), (2, 2)]
|
|
||||||
foy : [(2, 1), (1, 2), (2, 3)]
|
|
||||||
foe : [(2, 1), (1, 2), (1, 1)]
|
|
||||||
fm : [(2, 1), (3, 1)]
|
|
||||||
fn : [(2, 1), (3, 0)]
|
|
||||||
fe : [(2, 1), (3, 2)]
|
|
||||||
fee : [(2, 1), (3, 2), (2, 2)]
|
|
||||||
fey : [(2, 1), (3, 2), (2, 3)]
|
|
||||||
fem : [(2, 1), (3, 2), (3, 1)]
|
|
||||||
feme : [(2, 1), (3, 2), (3, 1), (2, 2)]
|
|
||||||
fe : [(2, 1), (2, 2)]
|
|
||||||
fee : [(2, 1), (2, 2), (1, 1)]
|
|
||||||
feed : [(2, 1), (2, 2), (1, 1), (2, 0)]
|
|
||||||
feer : [(2, 1), (2, 2), (1, 1), (1, 0)]
|
|
||||||
feere : [(2, 1), (2, 2), (1, 1), (1, 0), (0, 1)]
|
|
||||||
fee : [(2, 1), (2, 2), (3, 2)]
|
|
||||||
fem : [(2, 1), (2, 2), (3, 1)]
|
|
||||||
feme : [(2, 1), (2, 2), (3, 1), (3, 2)]
|
|
||||||
fey : [(2, 1), (2, 2), (2, 3)]
|
|
||||||
|
|
||||||
Starting @ (2, 2)...
|
|
||||||
e : [(2, 2)]
|
|
||||||
eo : [(2, 2), (1, 2)]
|
|
||||||
eos : [(2, 2), (1, 2), (0, 3)]
|
|
||||||
eof : [(2, 2), (1, 2), (2, 1)]
|
|
||||||
ee : [(2, 2), (1, 1)]
|
|
||||||
eer : [(2, 2), (1, 1), (1, 0)]
|
|
||||||
eery : [(2, 2), (1, 1), (1, 0), (0, 0)]
|
|
||||||
evoe : [(2, 2), (1, 3), (0, 2), (1, 1)]
|
|
||||||
evoe : [(2, 2), (1, 3), (0, 2), (0, 1)]
|
|
||||||
evoe : [(2, 2), (1, 3), (1, 2), (0, 1)]
|
|
||||||
evoe : [(2, 2), (1, 3), (1, 2), (1, 1)]
|
|
||||||
ee : [(2, 2), (3, 2)]
|
|
||||||
em : [(2, 2), (3, 1)]
|
|
||||||
emf : [(2, 2), (3, 1), (2, 1)]
|
|
||||||
eme : [(2, 2), (3, 1), (3, 2)]
|
|
||||||
ef : [(2, 2), (2, 1)]
|
|
||||||
ey : [(2, 2), (2, 3)]
|
|
||||||
eye : [(2, 2), (2, 3), (3, 2)]
|
|
||||||
|
|
||||||
Starting @ (2, 3)...
|
|
||||||
y : [(2, 3)]
|
|
||||||
yo : [(2, 3), (1, 2)]
|
|
||||||
yoe : [(2, 3), (1, 2), (0, 1)]
|
|
||||||
yoe : [(2, 3), (1, 2), (2, 2)]
|
|
||||||
yoe : [(2, 3), (1, 2), (1, 1)]
|
|
||||||
yquem : [(2, 3), (3, 3), (2, 2), (3, 1)]
|
|
||||||
yquem : [(2, 3), (3, 3), (3, 2), (3, 1)]
|
|
||||||
ye : [(2, 3), (3, 2)]
|
|
||||||
yee : [(2, 3), (3, 2), (2, 2)]
|
|
||||||
ye : [(2, 3), (2, 2)]
|
|
||||||
yeo : [(2, 3), (2, 2), (1, 2)]
|
|
||||||
yee : [(2, 3), (2, 2), (1, 1)]
|
|
||||||
yee : [(2, 3), (2, 2), (3, 2)]
|
|
||||||
|
|
||||||
Starting @ (3, 0)...
|
|
||||||
n : [(3, 0)]
|
|
||||||
nd : [(3, 0), (2, 0)]
|
|
||||||
nm : [(3, 0), (3, 1)]
|
|
||||||
|
|
||||||
Starting @ (3, 1)...
|
|
||||||
m : [(3, 1)]
|
|
||||||
mf : [(3, 1), (2, 1)]
|
|
||||||
mfr : [(3, 1), (2, 1), (1, 0)]
|
|
||||||
mfd : [(3, 1), (2, 1), (2, 0)]
|
|
||||||
md : [(3, 1), (2, 0)]
|
|
||||||
me : [(3, 1), (2, 2)]
|
|
||||||
meo : [(3, 1), (2, 2), (1, 2)]
|
|
||||||
mee : [(3, 1), (2, 2), (1, 1)]
|
|
||||||
meed : [(3, 1), (2, 2), (1, 1), (2, 0)]
|
|
||||||
meer : [(3, 1), (2, 2), (1, 1), (1, 0)]
|
|
||||||
mev : [(3, 1), (2, 2), (1, 3)]
|
|
||||||
mee : [(3, 1), (2, 2), (3, 2)]
|
|
||||||
mn : [(3, 1), (3, 0)]
|
|
||||||
me : [(3, 1), (3, 2)]
|
|
||||||
mee : [(3, 1), (3, 2), (2, 2)]
|
|
||||||
|
|
||||||
Starting @ (3, 2)...
|
|
||||||
e : [(3, 2)]
|
|
||||||
ee : [(3, 2), (2, 2)]
|
|
||||||
ef : [(3, 2), (2, 1)]
|
|
||||||
ey : [(3, 2), (2, 3)]
|
|
||||||
eye : [(3, 2), (2, 3), (2, 2)]
|
|
||||||
em : [(3, 2), (3, 1)]
|
|
||||||
emf : [(3, 2), (3, 1), (2, 1)]
|
|
||||||
eme : [(3, 2), (3, 1), (2, 2)]
|
|
||||||
emeer : [(3, 2), (3, 1), (2, 2), (1, 1), (1, 0)]
|
|
||||||
|
|
||||||
Starting @ (3, 3)...
|
|
||||||
qu : [(3, 3)]
|
|
||||||
que : [(3, 3), (2, 2)]
|
|
||||||
queer : [(3, 3), (2, 2), (1, 1), (1, 0)]
|
|
||||||
queery : [(3, 3), (2, 2), (1, 1), (1, 0), (0, 0)]
|
|
||||||
quem : [(3, 3), (2, 2), (3, 1)]
|
|
||||||
queme : [(3, 3), (2, 2), (3, 1), (3, 2)]
|
|
||||||
quey : [(3, 3), (2, 2), (2, 3)]
|
|
||||||
que : [(3, 3), (3, 2)]
|
|
||||||
quey : [(3, 3), (3, 2), (2, 3)]
|
|
||||||
quem : [(3, 3), (3, 2), (3, 1)]
|
|
||||||
queme : [(3, 3), (3, 2), (3, 1), (2, 2)]
|
|
||||||
```
|
|
||||||
|
|
||||||
# License
|
# License
|
||||||
The included [wordlists](src/boggler/wordlists) are covered by their respective licenses. All other files MIT © Cameron Blankenbuehler
|
The included [wordlists](boggler/wordlists) are covered by their respective licenses. All other files [MIT](LICENSE) © Cameron Blankenbuehler
|
||||||
|
|||||||
Executable
+125
@@ -0,0 +1,125 @@
|
|||||||
|
"""Boggler Demo"""
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from itertools import chain
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.table import Table
|
||||||
|
from rich import box
|
||||||
|
from .boggler_utils import BoggleBoard, build_full_boggle_tree, read_boggle_file
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(prog="boggler", description="Boggle board game solver")
|
||||||
|
|
||||||
|
parser.add_argument("board", type=Path, help="Path to board CSV file")
|
||||||
|
parser.add_argument(
|
||||||
|
"wordlists",
|
||||||
|
type=Path,
|
||||||
|
help='Path to directory of wordlist files. The directory must contain \
|
||||||
|
text files of the form words_X.txt where "X" is a character of \
|
||||||
|
the alphabet',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"max_word_length",
|
||||||
|
nargs="?",
|
||||||
|
type=int,
|
||||||
|
default=16,
|
||||||
|
help="Maximum length of words searched for on provided board",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-f",
|
||||||
|
"--format",
|
||||||
|
type=str,
|
||||||
|
help="Specify alternative output format including [txt, json]",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-p",
|
||||||
|
"--include-path",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Include full paths for each word in output",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-s",
|
||||||
|
"--sort",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Sort output alphabetically. By default the results are sorted by the starting \
|
||||||
|
block position on the board from top-to-bottom, left-to-right as given in the \
|
||||||
|
board file.",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"-d",
|
||||||
|
"--dedup",
|
||||||
|
action="store_true",
|
||||||
|
default=False,
|
||||||
|
help="Remove duplicates from word-only output. Note that de-duplication does not preserve \
|
||||||
|
the original order of the output, so it is recommended to also use the sort option when \
|
||||||
|
de-duplicating.",
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Command line tool for sovling Boggle boards"""
|
||||||
|
board = read_boggle_file(args.board)
|
||||||
|
try:
|
||||||
|
boggle_board = BoggleBoard(board, args.max_word_length)
|
||||||
|
except ValueError:
|
||||||
|
print("Invalid MAX_WORD_LENGTH. Please try again with a valid integer.")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
boggle_tree = build_full_boggle_tree(boggle_board, Path(args.wordlists))
|
||||||
|
|
||||||
|
if args.format:
|
||||||
|
match args.format.lower():
|
||||||
|
case "txt":
|
||||||
|
word_paths = [
|
||||||
|
start_block.word_paths for start_block in boggle_tree.values()
|
||||||
|
]
|
||||||
|
data = list(chain(*word_paths))
|
||||||
|
if args.include_path:
|
||||||
|
data = [f"{line[0]} {line[1]}" for line in data]
|
||||||
|
else:
|
||||||
|
data = [x[0] for x in data]
|
||||||
|
if args.dedup:
|
||||||
|
data = list(set(data))
|
||||||
|
|
||||||
|
if args.sort:
|
||||||
|
data.sort()
|
||||||
|
|
||||||
|
for line in data:
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
case "json":
|
||||||
|
data = {str(k): v.word_paths for k, v in boggle_tree.items()}
|
||||||
|
print(json.dumps(data, indent=2, sort_keys=True))
|
||||||
|
case _:
|
||||||
|
print(f'Invalid format (-f) option provided: "{args.format}"')
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
else:
|
||||||
|
console = Console()
|
||||||
|
print("\nBOARD")
|
||||||
|
print(boggle_board)
|
||||||
|
|
||||||
|
for start_pos, tree in boggle_tree.items():
|
||||||
|
table = Table(
|
||||||
|
title=f"Starting @ {start_pos}",
|
||||||
|
show_header=True,
|
||||||
|
header_style="bold purple",
|
||||||
|
row_styles=["dim", ""],
|
||||||
|
box=box.ROUNDED,
|
||||||
|
)
|
||||||
|
table.add_column("Word")
|
||||||
|
table.add_column("Path")
|
||||||
|
for word in tree.word_paths:
|
||||||
|
# print(f"{word[0]: <{boggle_board.max_word_len}}: {word[1]}")
|
||||||
|
table.add_row(f"{word[0]}", f"{word[1]}")
|
||||||
|
|
||||||
|
console.print(table)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Executable
+58
@@ -0,0 +1,58 @@
|
|||||||
|
"""Module to generate random Boggle boards for testing"""
|
||||||
|
|
||||||
|
from sys import argv, stderr
|
||||||
|
from random import randint, shuffle
|
||||||
|
from math import sqrt, floor
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, TypeAlias
|
||||||
|
|
||||||
|
|
||||||
|
Die: TypeAlias = List[str]
|
||||||
|
Dice: TypeAlias = List[Die]
|
||||||
|
|
||||||
|
|
||||||
|
def read_dice_file(dice_path: Path):
|
||||||
|
"""Return list of die strings from file ignoring all comments (#)"""
|
||||||
|
with open(dice_path, "r+", encoding="utf-8") as file:
|
||||||
|
return [line.rstrip().split(",") for line in file.readlines() if line[0] != "#"]
|
||||||
|
|
||||||
|
|
||||||
|
def roll_die(die: Die):
|
||||||
|
"""Return a face of the given die string to simulate rolling a die"""
|
||||||
|
return str(die[randint(0, len(die) - 1)])
|
||||||
|
|
||||||
|
|
||||||
|
def roll_dice(dice: Dice):
|
||||||
|
"""Return a random roll for each die"""
|
||||||
|
return [roll_die(die) for die in dice]
|
||||||
|
|
||||||
|
|
||||||
|
def get_random_board(dice: Dice):
|
||||||
|
shuffle(dice)
|
||||||
|
rolls = roll_dice(dice)
|
||||||
|
|
||||||
|
# Format dice rolls for boards file
|
||||||
|
board_size = int(floor(sqrt(len(rolls))))
|
||||||
|
board = []
|
||||||
|
for i in range(0, len(dice), board_size):
|
||||||
|
board.append(rolls[i : i + board_size])
|
||||||
|
return board
|
||||||
|
|
||||||
|
|
||||||
|
def get_random_board_csv(dice: Dice):
|
||||||
|
board = get_random_board(dice)
|
||||||
|
board = [",".join(row) for row in board]
|
||||||
|
return board
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(argv) != 2:
|
||||||
|
print("Usage: python3 board_randomizer.py <dice_file>")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
dice = read_dice_file(Path(argv[1]))
|
||||||
|
board = get_random_board_csv(dice)
|
||||||
|
for r in range(0, int(floor(sqrt(len(dice))))):
|
||||||
|
print(board[r])
|
||||||
|
except Exception as e:
|
||||||
|
print("Argument must be a valid file path.", file=stderr)
|
||||||
@@ -1,41 +1,47 @@
|
|||||||
'''Boggler Utils'''
|
"""Boggler Utils"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
from os import path
|
from pathlib import Path
|
||||||
from multiprocessing import Pool
|
from multiprocessing import Pool
|
||||||
|
import logging as log
|
||||||
|
import functools
|
||||||
|
import operator
|
||||||
|
|
||||||
|
|
||||||
class BoardCell:
|
class BoardCell:
|
||||||
'''Boggle Board cell'''
|
"""Boggle Board cell"""
|
||||||
def __init__(self, row: int, col: int, letters: str,
|
|
||||||
adjacent_cells: list[BoardCell] = None) -> BoardCell:
|
def __init__(
|
||||||
|
self, row: int, col: int, letters: str, adjacent_cells: list[BoardCell] = None
|
||||||
|
) -> None:
|
||||||
self.__row: int = row
|
self.__row: int = row
|
||||||
self.__col: int = col
|
self.__col: int = col
|
||||||
self.__pos: (int, int) = (self.__row, self.__col)
|
self.__pos: tuple[int, int] = (self.__row, self.__col)
|
||||||
self.__letters: str = letters
|
self.__letters: str = letters
|
||||||
self.__adjacent_cells: list[BoardCell] = adjacent_cells
|
self.__adjacent_cells: list[BoardCell] = adjacent_cells
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def row(self) -> int:
|
def row(self) -> int:
|
||||||
'''Getter for row property'''
|
"""Getter for row property"""
|
||||||
return self.__row
|
return self.__row
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def col(self) -> int:
|
def col(self) -> int:
|
||||||
'''Getter for col property'''
|
"""Getter for col property"""
|
||||||
return self.__col
|
return self.__col
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def pos(self) -> (int, int):
|
def pos(self) -> tuple[int, int]:
|
||||||
'''Getter for pos property'''
|
"""Getter for pos property"""
|
||||||
return self.__pos
|
return self.__pos
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def letters(self) -> str:
|
def letters(self) -> str:
|
||||||
'''Getter for letter property'''
|
"""Getter for letter property"""
|
||||||
return self.__letters
|
return self.__letters
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def adjacent_cells(self) -> list[BoardCell]:
|
def adjacent_cells(self) -> list[BoardCell]:
|
||||||
'''Getter for adjacent_cells property'''
|
"""Getter for adjacent_cells property"""
|
||||||
return self.__adjacent_cells
|
return self.__adjacent_cells
|
||||||
|
|
||||||
@adjacent_cells.setter
|
@adjacent_cells.setter
|
||||||
@@ -48,13 +54,15 @@ class BoardCell:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"(BoardCell({self.__row}, {self.__col}): {self.__letters}"
|
return f"(BoardCell({self.__row}, {self.__col}): {self.__letters}"
|
||||||
|
|
||||||
|
|
||||||
class BoggleBoard:
|
class BoggleBoard:
|
||||||
'''Boggle board structure'''
|
"""Boggle board structure"""
|
||||||
def __init__(self, board: list[list[str]], max_word_len: int = 14) -> BoggleBoard:
|
|
||||||
|
def __init__(self, board: list[list[str]], max_word_len: int = 14) -> None:
|
||||||
self.__height: int = len(board)
|
self.__height: int = len(board)
|
||||||
self.__width: int = len(board[0]) if self.__height > 0 else 0
|
self.__width: int = len(board[0]) if self.__height > 0 else 0
|
||||||
self.__board_list = board
|
self.__board_list = board
|
||||||
self.__board: dict[(int, int), BoardCell] = {}
|
self.__board: dict[tuple[int, int], BoardCell] = {}
|
||||||
|
|
||||||
# Max word length is limited by size of the board
|
# Max word length is limited by size of the board
|
||||||
self.__max_word_len = min(max_word_len, self.__width * self.__height)
|
self.__max_word_len = min(max_word_len, self.__width * self.__height)
|
||||||
@@ -72,7 +80,9 @@ class BoggleBoard:
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
flattened_board_list = [y for x in self.__board_list for y in x]
|
flattened_board_list = [y for x in self.__board_list for y in x]
|
||||||
max_len = len(max(flattened_board_list, key=len))
|
max_len = len(max(flattened_board_list, key=len))
|
||||||
max_len = max_len + 1 if max_len % 2 == 0 else max_len + 2 # keep header_len odd
|
max_len = (
|
||||||
|
max_len + 1 if max_len % 2 == 0 else max_len + 2
|
||||||
|
) # keep header_len odd
|
||||||
header_len = self.__width * (max_len + 1) - 1
|
header_len = self.__width * (max_len + 1) - 1
|
||||||
head = "-" * header_len
|
head = "-" * header_len
|
||||||
header = f"+{head}+\n"
|
header = f"+{head}+\n"
|
||||||
@@ -87,53 +97,61 @@ class BoggleBoard:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def height(self) -> int:
|
def height(self) -> int:
|
||||||
'''Getter for height property'''
|
"""Getter for height property"""
|
||||||
return self.__height
|
return self.__height
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def width(self) -> int:
|
def width(self) -> int:
|
||||||
'''Getter for width property'''
|
"""Getter for width property"""
|
||||||
return self.__width
|
return self.__width
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_word_len(self) -> int:
|
def max_word_len(self) -> int:
|
||||||
'''Getter for maximum word length property'''
|
"""Getter for maximum word length property"""
|
||||||
return self.__max_word_len
|
return self.__max_word_len
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def board(self) -> dict[(int, int), BoardCell]:
|
def board(self) -> dict[tuple[int, int], BoardCell]:
|
||||||
'''Getter for board property'''
|
"""Getter for board property"""
|
||||||
return self.__board
|
return self.__board
|
||||||
|
|
||||||
def __get_adjacent_indexes(self, row, col):
|
def __get_adjacent_indexes(self, row, col):
|
||||||
'''Return adjecency list for board of size `row x col`'''
|
"""Return adjecency list for board of size `row x col`"""
|
||||||
indexes = []
|
indexes = []
|
||||||
if row > 0:
|
if row > 0:
|
||||||
indexes.append((row-1, col)) # up
|
indexes.append((row - 1, col)) # up
|
||||||
if col > 0:
|
if col > 0:
|
||||||
indexes.append((row-1, col-1)) # up-left
|
indexes.append((row - 1, col - 1)) # up-left
|
||||||
if col < self.width - 1:
|
if col < self.width - 1:
|
||||||
indexes.append((row-1, col+1)) # up-right
|
indexes.append((row - 1, col + 1)) # up-right
|
||||||
if row < self.height - 1:
|
if row < self.height - 1:
|
||||||
indexes.append((row+1, col)) # down
|
indexes.append((row + 1, col)) # down
|
||||||
if col > 0:
|
if col > 0:
|
||||||
indexes.append((row+1, col-1)) # down-left
|
indexes.append((row + 1, col - 1)) # down-left
|
||||||
if col < self.width - 1:
|
if col < self.width - 1:
|
||||||
indexes.append((row+1, col+1)) # down-right
|
indexes.append((row + 1, col + 1)) # down-right
|
||||||
if col > 0:
|
if col > 0:
|
||||||
indexes.append((row, col-1)) # left
|
indexes.append((row, col - 1)) # left
|
||||||
if col < self.width - 1:
|
if col < self.width - 1:
|
||||||
indexes.append((row, col+1)) # right
|
indexes.append((row, col + 1)) # right
|
||||||
return indexes
|
return indexes
|
||||||
|
|
||||||
def get_cell(self, row: int, col: int) -> str:
|
def get_cell(self, row: int, col: int) -> BoardCell:
|
||||||
'''Return the value at the specified row x column'''
|
"""Return the value at the specified row x column"""
|
||||||
return self.__board[(row, col)]
|
return self.__board[(row, col)]
|
||||||
|
|
||||||
|
|
||||||
class WordNode:
|
class WordNode:
|
||||||
'''A node describing a single letter in a WordTree.'''
|
"""A node describing a single letter in a WordTree."""
|
||||||
def __init__(self, letters: str, is_word: bool = False, parent: WordNode = None,
|
|
||||||
children: dict[str, WordNode] = None, board_pos = None) -> WordNode:
|
def __init__(
|
||||||
|
self,
|
||||||
|
letters: str,
|
||||||
|
is_word: bool = False,
|
||||||
|
parent: WordNode = None,
|
||||||
|
children: dict[str, WordNode] = None,
|
||||||
|
board_pos=(None, None),
|
||||||
|
) -> None:
|
||||||
self.__letters = letters
|
self.__letters = letters
|
||||||
self.__is_word = is_word
|
self.__is_word = is_word
|
||||||
self.__children = children if children is not None else {}
|
self.__children = children if children is not None else {}
|
||||||
@@ -142,12 +160,12 @@ class WordNode:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def letters(self) -> str:
|
def letters(self) -> str:
|
||||||
'''Getter for letter property'''
|
"""Getter for letter property"""
|
||||||
return self.__letters
|
return self.__letters
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_word(self) -> bool:
|
def is_word(self) -> bool:
|
||||||
'''Getter for is_word property'''
|
"""Getter for is_word property"""
|
||||||
return self.__is_word
|
return self.__is_word
|
||||||
|
|
||||||
@is_word.setter
|
@is_word.setter
|
||||||
@@ -156,26 +174,26 @@ class WordNode:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def children(self) -> dict[str, WordNode]:
|
def children(self) -> dict[str, WordNode]:
|
||||||
'''Getter for children property'''
|
"""Getter for children property"""
|
||||||
return self.__children
|
return self.__children
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def parent(self) -> WordNode:
|
def parent(self) -> WordNode:
|
||||||
'''Getter for parent property'''
|
"""Getter for parent property"""
|
||||||
return self.__parent
|
return self.__parent
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def board_pos(self) -> (int, int):
|
def board_pos(self) -> tuple[int, int]:
|
||||||
'''Getter for board_pos property'''
|
"""Getter for board_pos property"""
|
||||||
return self.__board_pos
|
return self.__board_pos
|
||||||
|
|
||||||
def add_child_node(self, node):
|
def add_child_node(self, node):
|
||||||
'''Add child node to `children` dictionary, indexed by the nodes' `letter`'''
|
"""Add child node to `children` dictionary, indexed by the nodes' `letter`"""
|
||||||
self.children[node.letters] = node
|
self.children[node.letters] = node
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def path(self) -> list[WordNode]:
|
def path(self) -> list[WordNode]:
|
||||||
'''Return list of nodes from current node to the root'''
|
"""Return list of nodes from current node to the root"""
|
||||||
curr_node = self
|
curr_node = self
|
||||||
path = []
|
path = []
|
||||||
path.append(curr_node.board_pos)
|
path.append(curr_node.board_pos)
|
||||||
@@ -186,7 +204,7 @@ class WordNode:
|
|||||||
return path
|
return path
|
||||||
|
|
||||||
def get_word(self, board: BoggleBoard) -> str:
|
def get_word(self, board: BoggleBoard) -> str:
|
||||||
'''Return word or word fragment based on the WordNode's path property'''
|
"""Return word or word fragment based on the WordNode's path property"""
|
||||||
return "".join([board.board[x].letters for x in self.path[::-1]])
|
return "".join([board.board[x].letters for x in self.path[::-1]])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@@ -195,16 +213,23 @@ class WordNode:
|
|||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f"WordNode: {self.letters}, {self.is_word}, {self.children}"
|
return f"WordNode: {self.letters}, {self.is_word}, {self.children}"
|
||||||
|
|
||||||
|
|
||||||
class WordTree:
|
class WordTree:
|
||||||
'''A tree populated by WordNode(s) to complete words from a given root letter and wordlist'''
|
"""A tree populated by WordNode(s) to complete words from a given root letter and wordlist"""
|
||||||
def __init__(self, alphabet: list, root: WordNode, words: list[str] = None,
|
|
||||||
max_word_len = 16) -> WordTree:
|
def __init__(
|
||||||
self.__alphabet: list = alphabet
|
self,
|
||||||
self.__wordlist: list[str] = words
|
alphabet: list[str],
|
||||||
self.__root: WordNode = root
|
root: WordNode,
|
||||||
self.__max_word_len: int = max_word_len
|
words: list[str] = None,
|
||||||
|
max_word_len=16,
|
||||||
|
) -> None:
|
||||||
|
self.__alphabet = alphabet
|
||||||
|
self.__wordlist = words
|
||||||
|
self.__root = root
|
||||||
|
self.__max_word_len = max_word_len
|
||||||
self.__tree: dict[str, WordNode] = {}
|
self.__tree: dict[str, WordNode] = {}
|
||||||
self.__word_paths: dict[str, list[WordNode]] = []
|
self.__word_paths: list[str, list[WordNode]] = []
|
||||||
|
|
||||||
# Generate root node
|
# Generate root node
|
||||||
self.__tree[root.letters] = root
|
self.__tree[root.letters] = root
|
||||||
@@ -217,32 +242,32 @@ class WordTree:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def alphabet(self) -> list:
|
def alphabet(self) -> list:
|
||||||
'''Getter for alphabet property'''
|
"""Getter for alphabet property"""
|
||||||
return self.__alphabet
|
return self.__alphabet
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def wordlist(self) -> list[str]:
|
def wordlist(self) -> list[str]:
|
||||||
'''Getter for wordlist property'''
|
"""Getter for wordlist property"""
|
||||||
return self.__wordlist
|
return self.__wordlist
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def root(self) -> WordNode:
|
def root(self) -> WordNode:
|
||||||
'''Getter for root property'''
|
"""Getter for root property"""
|
||||||
return self.__root
|
return self.__root
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_word_len(self) -> int:
|
def max_word_len(self) -> int:
|
||||||
'''Getter for max_word_len property'''
|
"""Getter for max_word_len property"""
|
||||||
return self.__max_word_len
|
return self.__max_word_len
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def tree(self) -> dict[str, WordNode]:
|
def tree(self) -> dict[str, WordNode]:
|
||||||
'''Getter for tree property'''
|
"""Getter for tree property"""
|
||||||
return self.__tree
|
return self.__tree
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def word_paths(self) -> dict[(int, int), WordNode]:
|
def word_paths(self) -> dict[(int, int), WordNode]:
|
||||||
'''Getter for leaf_nodes property'''
|
"""Getter for leaf_nodes property"""
|
||||||
return self.__word_paths
|
return self.__word_paths
|
||||||
|
|
||||||
@word_paths.setter
|
@word_paths.setter
|
||||||
@@ -250,138 +275,180 @@ class WordTree:
|
|||||||
self.__word_paths = value
|
self.__word_paths = value
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return ", ".join(self.wordlist)
|
return ", ".join([str(x) for x in self.word_paths])
|
||||||
|
|
||||||
def insert_node(self, letters: str, parent: WordNode, is_word: bool = False,
|
def __repr__(self):
|
||||||
children: dict[str, WordNode] = None, board_pos = None):
|
return self.__str__()
|
||||||
'''Create WordNode for `letters` and into WordTree under `parent`'''
|
|
||||||
|
def insert_node(
|
||||||
|
self,
|
||||||
|
letters: str,
|
||||||
|
parent: WordNode,
|
||||||
|
is_word: bool = False,
|
||||||
|
children: dict[str, WordNode] = None,
|
||||||
|
board_pos=None,
|
||||||
|
):
|
||||||
|
"""Create WordNode for `letters` and into WordTree under `parent`"""
|
||||||
|
log.debug("inserting node: %s", letters)
|
||||||
node = WordNode(letters, is_word, parent, children, board_pos)
|
node = WordNode(letters, is_word, parent, children, board_pos)
|
||||||
parent.add_child_node(node)
|
parent.add_child_node(node)
|
||||||
|
|
||||||
def __insert_word(self, word: str) -> bool:
|
def __insert_word(self, word: str) -> bool:
|
||||||
'''Returns True if the word could be inserted into the tree with the given alphabet,
|
"""Returns True if the word could be inserted into the tree with the given alphabet,
|
||||||
otherwise returns False'''
|
otherwise returns False"""
|
||||||
|
|
||||||
# Insert root node
|
# Insert root node
|
||||||
prefix = word[0:len(self.root.letters)] # prefix = first letter block
|
prefix = word[0 : len(self.root.letters)] # prefix = first letter block
|
||||||
if word is None or prefix != self.root.letters:
|
if word is None or prefix != self.root.letters:
|
||||||
return False
|
return False
|
||||||
curr_node = self.tree[prefix]
|
curr_node = self.tree[prefix]
|
||||||
word_len = len(word)
|
word_len = len(word)
|
||||||
|
|
||||||
# Insert remaining nodes as letter groups based on alphabet
|
i = len(prefix)
|
||||||
skip_cnt = 0
|
i_max = min(self.max_word_len, len(word))
|
||||||
for i, letter in enumerate(word[len(prefix):self.max_word_len]):
|
while i < i_max:
|
||||||
# Skip word letter iterations for length of a previously inserted letter group
|
letters = word[i]
|
||||||
if skip_cnt > 0:
|
log.debug(
|
||||||
skip_cnt -= 1
|
"1 letter seq: %s %s %s", word, letters, letters in curr_node.children
|
||||||
continue
|
)
|
||||||
|
if letters not in self.alphabet:
|
||||||
try:
|
# Check two letter sequences like ("Qu", "Th", etc.) at current index
|
||||||
alpha_index = self.alphabet.index(letter)
|
letters = word[i : i + 2]
|
||||||
except ValueError: # letters not in given alphabet
|
log.debug(
|
||||||
|
"2 letter seq: %s %s %s",
|
||||||
|
word,
|
||||||
|
letters,
|
||||||
|
letters in curr_node.children,
|
||||||
|
)
|
||||||
|
if letters not in self.alphabet:
|
||||||
return False
|
return False
|
||||||
|
# Insert node
|
||||||
|
if letters not in curr_node.children:
|
||||||
|
self.insert_node(letters, curr_node)
|
||||||
|
log.debug("3 letter seq: %s %s", word, letters)
|
||||||
|
|
||||||
# Insert letter (single)
|
curr_node = curr_node.children[letters]
|
||||||
if letter == self.alphabet[alpha_index] and letter not in curr_node.children:
|
|
||||||
self.insert_node(letter, curr_node)
|
|
||||||
curr_node = curr_node.children[letter]
|
|
||||||
# Letter already exists
|
|
||||||
elif letter == self.alphabet[alpha_index]:
|
|
||||||
curr_node = curr_node.children[letter]
|
|
||||||
# Check for letter groups (like "Qu") starting with `letter` in alphabet
|
|
||||||
else:
|
|
||||||
alpha = self.alphabet[alpha_index]
|
|
||||||
# Check that letter group is shorter than and matches in the word remainder
|
|
||||||
if len(alpha) < word_len - i and alpha == word[i+1:i+1+len(alpha)]:
|
|
||||||
if alpha not in curr_node.children:
|
|
||||||
self.insert_node(alpha, curr_node)
|
|
||||||
curr_node = curr_node.children[alpha]
|
|
||||||
else: # node already exist
|
|
||||||
curr_node = curr_node.children[alpha]
|
|
||||||
|
|
||||||
skip_cnt = len(alpha) - 1
|
i += len(letters)
|
||||||
#print(f"LONG GROUP: {alpha}; {word}")
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Mark the last node as a word
|
# Mark the last node as a word
|
||||||
curr_node.is_word = len(word) <= self.max_word_len
|
curr_node.is_word = len(word) <= self.max_word_len
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def search(self, word: str, curr_node = None) -> WordNode:
|
def search(self, word: str, curr_node=None) -> WordNode:
|
||||||
'''Return leaf (WordNode) if a given word is in the tree otherwise return None'''
|
"""Return leaf (WordNode) if a given word is in the tree otherwise return None"""
|
||||||
if len(word) == 0 or word is None:
|
if len(word) == 0 or word is None:
|
||||||
return curr_node
|
return curr_node
|
||||||
|
|
||||||
|
log.debug("Searching... %s %s", word, curr_node)
|
||||||
if curr_node is None:
|
if curr_node is None:
|
||||||
curr_node = self.root
|
curr_node = self.root
|
||||||
for letters in curr_node.children:
|
for letters in curr_node.children:
|
||||||
if letters == word[len(curr_node.letters):len(curr_node.letters) + len(letters)]:
|
if (
|
||||||
return self.search(word[len(curr_node.letters):], curr_node.children[letters])
|
letters
|
||||||
|
== word[len(curr_node.letters) : len(curr_node.letters) + len(letters)]
|
||||||
|
):
|
||||||
|
return self.search(
|
||||||
|
word[len(curr_node.letters) :], curr_node.children[letters]
|
||||||
|
)
|
||||||
|
|
||||||
# Currently only returns single path for word
|
# Currently only returns single path for word
|
||||||
# TODO: return all possible paths, maybe create minature WordTree? Or just of list of paths.
|
# TODO: return all possible paths, maybe create minature WordTree? Or just of list of paths.
|
||||||
return curr_node
|
return curr_node
|
||||||
|
|
||||||
def build_boggle_tree(self, board: BoggleBoard, board_cell: BoardCell, subtree: WordTree, word_len: int = 0) -> WordTree:
|
def build_boggle_tree(
|
||||||
'''Return subtree of board given a particular root (first letter).
|
self,
|
||||||
|
board: BoggleBoard,
|
||||||
|
board_cell: BoardCell,
|
||||||
|
subtree: WordTree,
|
||||||
|
word_len: int = 0,
|
||||||
|
) -> WordTree:
|
||||||
|
"""Return subtree of board given a particular root (first letter).
|
||||||
|
|
||||||
Keyword arguments:
|
Keyword arguments:
|
||||||
board -- the board the new tree is based on
|
board -- the board the new tree is based on
|
||||||
board_node -- a pointer on the board where new branch nodes can be inserted into the tree
|
board_node -- a pointer on the board where new branch nodes can be inserted into the tree
|
||||||
dict_node -- a pointer on the dictionary where nodes are read from for validation
|
dict_node -- a pointer on the dictionary where nodes are read from for validation
|
||||||
subtree -- the partial tree passed to the next recursive step for generating branches
|
subtree -- the partial tree passed to the next recursive step for generating branches
|
||||||
'''
|
"""
|
||||||
|
|
||||||
if word_len > self.max_word_len or word_len >= board.max_word_len:
|
if word_len > self.max_word_len or word_len >= board.max_word_len:
|
||||||
#print(f"MAX DEPTH REACHED! Depth = {depth}")
|
log.debug(f"MAX WORD LENGTH REACHED! len = {word_len}")
|
||||||
subtree.active_node = subtree.active_node.parent
|
subtree.active_node = subtree.active_node.parent
|
||||||
self.active_node = self.active_node.parent
|
self.active_node = self.active_node.parent
|
||||||
return
|
return subtree
|
||||||
|
|
||||||
# TODO rework active_node refs for recursion so don't have to be reset to parent at every point of return
|
# TODO rework active_node refs for recursion so don't have to be reset to parent at every point of return
|
||||||
if self.active_node.is_word and len(self.active_node.children) == 0:
|
if self.active_node.is_word and len(self.active_node.children) == 0:
|
||||||
word_path = subtree.active_node.path[::-1]
|
word_path = subtree.active_node.path[::-1]
|
||||||
subtree.word_paths.append((subtree.active_node.get_word(board), word_path))
|
subtree.word_paths.append((subtree.active_node.get_word(board), word_path))
|
||||||
#print("1: WORD FOUND:", "".join([board.board[x].letters for x in word_path]), word_path)
|
log.debug(
|
||||||
|
"1: WORD FOUND: %s %s",
|
||||||
|
"".join([board.board[x].letters for x in word_path]),
|
||||||
|
word_path,
|
||||||
|
)
|
||||||
self.active_node = self.active_node.parent
|
self.active_node = self.active_node.parent
|
||||||
subtree.active_node = subtree.active_node.parent
|
subtree.active_node = subtree.active_node.parent
|
||||||
return
|
return subtree
|
||||||
elif self.active_node.is_word:
|
elif self.active_node.is_word:
|
||||||
word_path = subtree.active_node.path[::-1]
|
word_path = subtree.active_node.path[::-1]
|
||||||
subtree.word_paths.append((subtree.active_node.get_word(board), word_path))
|
subtree.word_paths.append((subtree.active_node.get_word(board), word_path))
|
||||||
#print("2: WORD FOUND:", "".join([board.board[x].letters for x in word_path]), word_path)
|
log.debug(
|
||||||
|
"2: WORD FOUND: %s %s",
|
||||||
|
"".join([board.board[x].letters for x in word_path]),
|
||||||
|
word_path,
|
||||||
|
)
|
||||||
|
|
||||||
# Branch for each adjacent board cell
|
# Branch for each adjacent board cell
|
||||||
for cell in board_cell.adjacent_cells:
|
for cell in board_cell.adjacent_cells:
|
||||||
# Check dictionary and exclude nodes already in path
|
# Check dictionary and exclude nodes already in path
|
||||||
if cell.letters in self.active_node.children and cell.pos not in subtree.active_node.path:
|
if (
|
||||||
new_node = WordNode(cell.letters, self.active_node.is_word, subtree.active_node, board_pos = cell.pos)
|
cell.letters in self.active_node.children
|
||||||
|
and cell.pos not in subtree.active_node.path
|
||||||
|
):
|
||||||
|
new_node = WordNode(
|
||||||
|
cell.letters,
|
||||||
|
self.active_node.is_word,
|
||||||
|
subtree.active_node,
|
||||||
|
board_pos=cell.pos,
|
||||||
|
)
|
||||||
subtree.active_node.add_child_node(new_node)
|
subtree.active_node.add_child_node(new_node)
|
||||||
subtree.active_node = subtree.active_node.children[cell.letters] # update subtree pointer
|
subtree.active_node = subtree.active_node.children[
|
||||||
self.active_node = self.active_node.children[cell.letters] # update dictionary tree pointer
|
cell.letters
|
||||||
self.build_boggle_tree(board, board.board[cell.pos], subtree, word_len=word_len+len(board_cell.letters))
|
] # update subtree pointer
|
||||||
|
self.active_node = self.active_node.children[
|
||||||
|
cell.letters
|
||||||
|
] # update dictionary tree pointer
|
||||||
|
self.build_boggle_tree(
|
||||||
|
board,
|
||||||
|
board.board[cell.pos],
|
||||||
|
subtree,
|
||||||
|
word_len=word_len + len(board_cell.letters),
|
||||||
|
)
|
||||||
|
|
||||||
self.active_node = self.active_node.parent
|
self.active_node = self.active_node.parent
|
||||||
subtree.active_node = subtree.active_node.parent
|
subtree.active_node = subtree.active_node.parent
|
||||||
return subtree
|
return subtree
|
||||||
|
|
||||||
|
|
||||||
def build_boggle_tree(args):
|
def build_boggle_tree(args):
|
||||||
'''Build boggle tree from arguments for process Pool'''
|
"""Build boggle tree from arguments for process Pool"""
|
||||||
(alphabet, board, cell, wordlist) = args
|
(alphabet, board, cell, wordlist) = args
|
||||||
root_node = WordNode(cell.letters)
|
root_node = WordNode(cell.letters)
|
||||||
dict_tree = WordTree(alphabet, root_node, wordlist)
|
dict_tree = WordTree(alphabet, root_node, wordlist)
|
||||||
sub_tree = WordTree(alphabet, WordNode(cell.letters, False, board_pos=cell.pos))
|
sub_tree = WordTree(alphabet, WordNode(cell.letters, False, board_pos=cell.pos))
|
||||||
return dict_tree.build_boggle_tree(board, cell, sub_tree)
|
return dict_tree.build_boggle_tree(board, cell, sub_tree)
|
||||||
|
|
||||||
def build_full_boggle_tree(board: BoggleBoard, wordlist_path: str) -> dict[str, WordTree]:
|
|
||||||
'''Return dictionary of WordTree(s) for every letter on a BoggleBoard'''
|
def build_full_boggle_tree(
|
||||||
|
board: BoggleBoard, wordlist_path: Path
|
||||||
|
) -> dict[str, WordTree]:
|
||||||
|
"""Return dictionary of WordTree(s) for every letter on a BoggleBoard"""
|
||||||
alphabet = sorted(set([cell.letters for cell in board.board.values()]))
|
alphabet = sorted(set([cell.letters for cell in board.board.values()]))
|
||||||
board_tree = {}
|
board_tree = {}
|
||||||
index = {}
|
index: dict[str] = {}
|
||||||
|
|
||||||
print("Reading in wordlists...")
|
log.info("Reading in wordlists...")
|
||||||
for letters in alphabet:
|
for letters in alphabet:
|
||||||
if letters == "":
|
if letters == "":
|
||||||
# Skip wordlist read for blocks with empty string
|
# Skip wordlist read for blocks with empty string
|
||||||
@@ -393,28 +460,65 @@ def build_full_boggle_tree(board: BoggleBoard, wordlist_path: str) -> dict[str,
|
|||||||
|
|
||||||
filename = "words_" + letters[0] + ".txt"
|
filename = "words_" + letters[0] + ".txt"
|
||||||
try:
|
try:
|
||||||
wordlist = read_wordlist(path.join(path.abspath(wordlist_path), filename))
|
wordlist = read_wordlist(Path(wordlist_path, filename))
|
||||||
index[letters] = wordlist
|
index[letters] = wordlist
|
||||||
print(f">> {letters}: {filename}")
|
log.info(">> %s: %s", letters, filename)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print(f">> {letters}: -- Skipping -- no wordlist found for {letters}")
|
log.info(">> %s: -- Skipping -- no wordlist found for %s", letters, letters)
|
||||||
index[letters] = {}
|
index[letters] = {}
|
||||||
|
|
||||||
print("Generating WordTrees...")
|
log.info("Generating WordTrees...")
|
||||||
params = [ [alphabet, board, cell, index[cell.letters] ] for cell in board.board.values()]
|
params = [
|
||||||
|
[alphabet, board, cell, index[cell.letters]] for cell in board.board.values()
|
||||||
|
]
|
||||||
with Pool(processes=len(board.board)) as pool:
|
with Pool(processes=len(board.board)) as pool:
|
||||||
for i, res in enumerate(pool.map(build_boggle_tree, params)):
|
for i, res in enumerate(pool.map(build_boggle_tree, params)):
|
||||||
print(f">> {params[i][2]}")
|
log.info(">> %s", params[i][2])
|
||||||
board_tree[params[i][2].pos] = res
|
board_tree[params[i][2].pos] = res
|
||||||
|
|
||||||
return board_tree
|
return board_tree
|
||||||
|
|
||||||
|
|
||||||
def read_wordlist(file):
|
def read_wordlist(file):
|
||||||
'''Return dictionary of words with associated word count (1 by default)'''
|
"""Return dictionary of words with associated word count (1 by default)"""
|
||||||
with open(file, 'r', encoding='utf-8') as file:
|
with open(file, "r", encoding="utf-8") as file:
|
||||||
return {k:1 for k in file.read().split()}
|
return file.read().split()
|
||||||
|
|
||||||
|
|
||||||
|
class BadBoardFormat(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def read_boggle_file(file):
|
def read_boggle_file(file):
|
||||||
'''Return list of rows from Boggle board csv file'''
|
"""Return list of rows from Boggle board csv file
|
||||||
with open(file, 'r', encoding='utf-8') as file:
|
|
||||||
return [x.rstrip().split(',') for x in file.readlines()]
|
The size of the board is determined by the width (number of comma-separated values)
|
||||||
|
of the first (non-empty) line in the file.
|
||||||
|
|
||||||
|
"""
|
||||||
|
with open(file, "r", encoding="utf-8") as file:
|
||||||
|
board = []
|
||||||
|
|
||||||
|
board.append([x.strip() for x in file.readline().split(",")])
|
||||||
|
board_size = len(board[0])
|
||||||
|
for line in file.readlines():
|
||||||
|
if line.strip() == "":
|
||||||
|
raise BadBoardFormat("board files must contain no blank lines")
|
||||||
|
|
||||||
|
row = [x.strip() for x in line.strip().split(",")]
|
||||||
|
if len(row) != board_size:
|
||||||
|
raise BadBoardFormat("the length of each row must be the same")
|
||||||
|
|
||||||
|
board.append(row)
|
||||||
|
|
||||||
|
return board
|
||||||
|
|
||||||
|
|
||||||
|
def find_paths_by_word(board_letters, dictionary_path, max_len):
|
||||||
|
"""Return list of paths by word"""
|
||||||
|
boggle_board = BoggleBoard(board_letters, max_len)
|
||||||
|
boggle_tree = build_full_boggle_tree(boggle_board, dictionary_path)
|
||||||
|
paths_by_word = functools.reduce(
|
||||||
|
operator.iconcat, [x.word_paths for x in boggle_tree.values()], []
|
||||||
|
)
|
||||||
|
return paths_by_word
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
CC = gcc
|
||||||
|
CFLAGS = -Wall -Werror -std=gnu17 -g3
|
||||||
|
OBJS = boggler.o
|
||||||
|
|
||||||
|
all: $(OBJS)
|
||||||
|
$(CC) $(OBJS) -o boggler
|
||||||
|
|
||||||
|
boggler.o: boggler.c board.h tree.h
|
||||||
|
$(CC) $(CFLAGS) -c boggler.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *~ *.o boggler
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
#ifndef BOGGLER_UTILS
|
||||||
|
#define BOGGLER_UTILS
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* Board is structured like so when referencing cells
|
||||||
|
* x ->
|
||||||
|
* +---+---+---+---+
|
||||||
|
* y |0,0|1,0|2,0|3,0| -+
|
||||||
|
* | |---------------| |
|
||||||
|
* v |0,1|1,1|2,1|3,1| |
|
||||||
|
* |---------------| | height
|
||||||
|
* |0,2|1,2|2,2|3,2| |
|
||||||
|
* |---------------| |
|
||||||
|
* |0,3|1,3|2,3|3,3| -+
|
||||||
|
* +---+---+---+---+
|
||||||
|
* | |
|
||||||
|
* +-------------+
|
||||||
|
* width
|
||||||
|
*
|
||||||
|
* Vec2 = (x, y) = (col, row)
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct BoardCell {
|
||||||
|
char *letters;
|
||||||
|
uint8_t row;
|
||||||
|
uint8_t col;
|
||||||
|
struct BoardCell **adjacent_cells;
|
||||||
|
uint8_t adjacent_cnt;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Vec2 {
|
||||||
|
uint8_t row;
|
||||||
|
uint8_t col;
|
||||||
|
} Vec2;
|
||||||
|
|
||||||
|
typedef struct Board {
|
||||||
|
/* BoardCells are indexed from top-to-bottom, left-to-right
|
||||||
|
* For instance a 3x3 board would have cells ordered like this
|
||||||
|
* +---+---+---+
|
||||||
|
* | 0 | 1 | 2 |
|
||||||
|
* |---+---+---|
|
||||||
|
* | 3 | 4 | 5 |
|
||||||
|
* |---+---+---|
|
||||||
|
* | 6 | 7 | 8 |
|
||||||
|
* +---+---+---+
|
||||||
|
*/
|
||||||
|
uint8_t height;
|
||||||
|
unsigned short width;
|
||||||
|
struct BoardCell **cells;
|
||||||
|
} Board;
|
||||||
|
|
||||||
|
struct BoardCell *create_board_cell(char *letters, uint8_t row, uint8_t col) {
|
||||||
|
/* BoardCells are created with 8 adjacent cells since that is the minimum required
|
||||||
|
* for centrally placed (not on sides or corners) cells on a board.
|
||||||
|
*/
|
||||||
|
struct BoardCell *cell = malloc(sizeof(struct BoardCell));
|
||||||
|
cell->letters = letters;
|
||||||
|
cell->row = row;
|
||||||
|
cell->col = col;
|
||||||
|
|
||||||
|
return cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BoardCell *get_cell_at(Board *board, Vec2 pos) {
|
||||||
|
return board->cells[pos.row * pos.col + pos.col];
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_boardcell(struct BoardCell *c) {
|
||||||
|
printf("%3s | (%d,%d)\n", c->letters, c->row, c->col);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int print_board(Board *board) {
|
||||||
|
uint8_t row_len = (board->width * 4 + 1) * sizeof(char) + 1;
|
||||||
|
char *row_delim = malloc(row_len);
|
||||||
|
snprintf(row_delim, 2, "%c", '+');
|
||||||
|
for (uint8_t i = 0; i < board->width; i++) {
|
||||||
|
strcat(row_delim, "----");
|
||||||
|
}
|
||||||
|
row_delim[strlen(row_delim)-1] = '+';
|
||||||
|
|
||||||
|
for (uint8_t row = 0; row < board->height; row++) {
|
||||||
|
printf("%s\n", row_delim);
|
||||||
|
for (uint8_t col = 0; col < board->width; col++) {
|
||||||
|
printf("|%2s ", board->cells[(row * board->width) + col]->letters);
|
||||||
|
}
|
||||||
|
puts("|");
|
||||||
|
}
|
||||||
|
printf("%s\n", row_delim);
|
||||||
|
|
||||||
|
free(row_delim);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_board(Board *b) {
|
||||||
|
if (b != NULL) {
|
||||||
|
for (uint8_t i = 0; i < b->width * b->height; i++) {
|
||||||
|
free(b->cells[i]);
|
||||||
|
b->cells[i] = NULL;
|
||||||
|
}
|
||||||
|
free(b->cells);
|
||||||
|
free(b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Vec2[] get_adjacent_indexes(uint8_t board_size, Vec2 pos) {
|
||||||
|
// // Calculate total possible number of adjacent cells
|
||||||
|
// uint16_t = total_adj_cell_cnt = ((board-size-2) * (board-size-2) * 8) + ((board-size-2) * 4 * 5) + (4 * 3);
|
||||||
|
//
|
||||||
|
// Vec2[] indexes = malloc(8 * sizeof(Vec2));
|
||||||
|
// uint16_t i = 0;
|
||||||
|
// if (pos.row > 0) {
|
||||||
|
// indexes[i].append((row-1, col)) // up
|
||||||
|
// if col > 0:
|
||||||
|
// indexes.append((row-1, col-1)) // up-left
|
||||||
|
// if col < self.width - 1:
|
||||||
|
// indexes.append((row-1, col+1)) // up-right
|
||||||
|
// }
|
||||||
|
// if row < self.height - 1:
|
||||||
|
// indexes.append((row+1, col)) // down
|
||||||
|
// if col > 0:
|
||||||
|
// indexes.append((row+1, col-1)) // down-left
|
||||||
|
// if col < self.width - 1:
|
||||||
|
// indexes.append((row+1, col+1)) // down-right
|
||||||
|
// if col > 0:
|
||||||
|
// indexes.append((row, col-1)) // left
|
||||||
|
// if col < self.width - 1:
|
||||||
|
// indexes.append((row, col+1)) // right
|
||||||
|
//
|
||||||
|
// if (i != 8) {
|
||||||
|
// indexes = realloc(i * sizeof(Vec2));
|
||||||
|
// }
|
||||||
|
// return indexes
|
||||||
|
//}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include "board.h"
|
||||||
|
#include "tree.h"
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
const uint8_t BOARD_SIZE = 4;
|
||||||
|
char *letters[] = {
|
||||||
|
"u", "n", "r", "e",
|
||||||
|
"qu","n", "i", "l",
|
||||||
|
"i", "s", "h", "a",
|
||||||
|
"s", "e", "l", "b"
|
||||||
|
};
|
||||||
|
char **cell_letters = malloc(BOARD_SIZE * sizeof(struct BoardCell*));
|
||||||
|
|
||||||
|
struct BoardCell **cells = malloc(sizeof(struct BoardCell*) * BOARD_SIZE * BOARD_SIZE);
|
||||||
|
for (uint8_t i = 0; i < BOARD_SIZE * BOARD_SIZE; i++) {
|
||||||
|
cells[i] = create_board_cell(letters[i], (int)(i / BOARD_SIZE), i % BOARD_SIZE);
|
||||||
|
print_boardcell(cells[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Board board = { .height = 4, .width = 4, .cells = cells };
|
||||||
|
print_board(&board);
|
||||||
|
free(cell_letters);
|
||||||
|
|
||||||
|
struct WordNode *root = malloc(sizeof(struct WordNode) + sizeof(struct WordNode*));
|
||||||
|
init_wordnode(root, false, cells[0], NULL, NULL, 0);
|
||||||
|
add_child_node(&root, cells[5], false);
|
||||||
|
add_child_node(&root, cells[4], false);
|
||||||
|
print_wordnode(root);
|
||||||
|
print_wordnode_path(root->children[0]);
|
||||||
|
|
||||||
|
free_wordnode_children(root);
|
||||||
|
free(root);
|
||||||
|
for (uint8_t i = 0; i < BOARD_SIZE * BOARD_SIZE; i++) {
|
||||||
|
free(cells[i]);
|
||||||
|
}
|
||||||
|
free(cells);
|
||||||
|
}
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
#ifndef WORD_TREE
|
||||||
|
#define WORD_TREE
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "board.h"
|
||||||
|
|
||||||
|
struct WordNode {
|
||||||
|
bool is_word;
|
||||||
|
struct BoardCell *cell;
|
||||||
|
struct WordNode *parent;
|
||||||
|
uint8_t child_cnt;
|
||||||
|
struct WordNode *children[];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WordTree {
|
||||||
|
char *alphabet;
|
||||||
|
struct WordNode *root;
|
||||||
|
};
|
||||||
|
|
||||||
|
void *init_wordnode(struct WordNode *n, bool is_word, struct BoardCell *cell,
|
||||||
|
struct WordNode *parent, struct WordNode *children[], uint8_t child_cnt) {
|
||||||
|
n->is_word = is_word;
|
||||||
|
n->cell = cell;
|
||||||
|
n->parent = parent;
|
||||||
|
if (children != NULL) {
|
||||||
|
for (uint8_t i = 0; i < child_cnt; i++) {
|
||||||
|
n->children[i] = children[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n->child_cnt = child_cnt;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
void *print_wordnode(struct WordNode *n) {
|
||||||
|
if (n == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
printf("%3s | (%d,%d) | %3d\n", n->cell->letters, n->cell->row, n->cell->col, n->child_cnt);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *print_wordnode_path(struct WordNode *n) {
|
||||||
|
if (n == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
struct WordNode *node = n;
|
||||||
|
|
||||||
|
// Print letters from leaf to root
|
||||||
|
do {
|
||||||
|
printf("%s < ", node->cell->letters);
|
||||||
|
node = node->parent;
|
||||||
|
} while(node != NULL);
|
||||||
|
puts("ROOT");
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WordNode *add_child_node(struct WordNode **parent, struct BoardCell *cell, bool is_word) {
|
||||||
|
*parent = realloc(*parent, sizeof(struct WordNode) + sizeof(struct WordNode) * ((*parent)->child_cnt + 1));
|
||||||
|
(*parent)->children[(*parent)->child_cnt] = malloc(sizeof(struct WordNode));
|
||||||
|
init_wordnode((*parent)->children[(*parent)->child_cnt], is_word, cell, *parent, NULL, 0);
|
||||||
|
(*parent)->child_cnt++;
|
||||||
|
return (*parent)->children[(*parent)->child_cnt];
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_wordnode_children(struct WordNode *n) {
|
||||||
|
// TODO: recursively free wordnode children
|
||||||
|
for (uint8_t i = 0; i < n->child_cnt; i++) {
|
||||||
|
free(n->children[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void *insert_word(struct WordTree *tree, char *word) {
|
||||||
|
// TODO: Traverse tree from tree->root and add nodes needed to complete `word`
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int search(struct WordTree *tree, char *word) {
|
||||||
|
// TODO: Traverse `tree` node-by-node and return an array of Board paths for `word`
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WORD_TREE */
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# Listed alphabetically
|
||||||
|
a,a,a,f,r,s
|
||||||
|
a,a,e,e,e,e
|
||||||
|
a,a,f,i,r,s
|
||||||
|
a,d,e,n,n,n
|
||||||
|
a,e,e,e,e,m
|
||||||
|
a,e,e,g,m,u
|
||||||
|
a,e,g,m,n,n
|
||||||
|
a,f,i,r,s,y
|
||||||
|
an,er,he,in,qu,th
|
||||||
|
b,j,k,qu,x,z
|
||||||
|
c,c,e,n,s,t
|
||||||
|
c,e,i,i,l,t
|
||||||
|
c,e,i,l,p,t
|
||||||
|
c,e,i,p,s,t
|
||||||
|
d,d,h,n,o,t
|
||||||
|
d,h,h,l,n,o
|
||||||
|
d,h,l,n,o,r
|
||||||
|
d,l,o,h,h,r
|
||||||
|
e,i,i,i,t,t
|
||||||
|
e,m,o,t,t,t
|
||||||
|
e,n,s,s,s,u
|
||||||
|
f,i,p,r,s,y
|
||||||
|
g,o,r,r,v,w
|
||||||
|
i,k,l,qu,u,w
|
||||||
|
n,o,o,t,u,w
|
||||||
|
o,o,o,t,t,u
|
||||||
|
Executable
+35
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ -z $1 ] || [ -z $2 ]; then
|
||||||
|
echo "Usage: WORDLIST OUT_DIR"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
rg "(^a[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_a.txt"
|
||||||
|
rg "(^b[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_b.txt"
|
||||||
|
rg "(^c[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_c.txt"
|
||||||
|
rg "(^d[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_d.txt"
|
||||||
|
rg "(^e[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_e.txt"
|
||||||
|
rg "(^f[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_f.txt"
|
||||||
|
rg "(^g[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_g.txt"
|
||||||
|
rg "(^h[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_h.txt"
|
||||||
|
rg "(^i[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_i.txt"
|
||||||
|
rg "(^j[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_j.txt"
|
||||||
|
rg "(^k[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_k.txt"
|
||||||
|
rg "(^l[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_l.txt"
|
||||||
|
rg "(^m[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_m.txt"
|
||||||
|
rg "(^n[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_n.txt"
|
||||||
|
rg "(^o[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_o.txt"
|
||||||
|
rg "(^p[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_p.txt"
|
||||||
|
rg "(^q[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_q.txt"
|
||||||
|
rg "(^r[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_r.txt"
|
||||||
|
rg "(^s[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_s.txt"
|
||||||
|
rg "(^t[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_t.txt"
|
||||||
|
rg "(^u[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_u.txt"
|
||||||
|
rg "(^v[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_v.txt"
|
||||||
|
rg "(^w[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_w.txt"
|
||||||
|
rg "(^x[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_x.txt"
|
||||||
|
rg "(^y[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_y.txt"
|
||||||
|
rg "(^z[a-z]+).*$" -or '$1' $1 | sort | uniq > "$2/words_z.txt"
|
||||||
|
touch "$2/words__.txt"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
Generated
+612
@@ -0,0 +1,612 @@
|
|||||||
|
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "astroid"
|
||||||
|
version = "2.15.5"
|
||||||
|
description = "An abstract syntax tree for Python with inference support."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.2"
|
||||||
|
files = [
|
||||||
|
{file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"},
|
||||||
|
{file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
lazy-object-proxy = ">=1.4.0"
|
||||||
|
wrapt = {version = ">=1.14,<2", markers = "python_version >= \"3.11\""}
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfgv"
|
||||||
|
version = "3.4.0"
|
||||||
|
description = "Validate configuration and produce human readable error messages."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9"},
|
||||||
|
{file = "cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorama"
|
||||||
|
version = "0.4.6"
|
||||||
|
description = "Cross-platform colored terminal text."
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||||
|
files = [
|
||||||
|
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||||
|
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dill"
|
||||||
|
version = "0.3.6"
|
||||||
|
description = "serialize all of python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
|
||||||
|
{file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
graph = ["objgraph (>=1.7.2)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "distlib"
|
||||||
|
version = "0.3.7"
|
||||||
|
description = "Distribution utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = "*"
|
||||||
|
files = [
|
||||||
|
{file = "distlib-0.3.7-py2.py3-none-any.whl", hash = "sha256:2e24928bc811348f0feb63014e97aaae3037f2cf48712d51ae61df7fd6075057"},
|
||||||
|
{file = "distlib-0.3.7.tar.gz", hash = "sha256:9dafe54b34a028eafd95039d5e5d4851a13734540f1331060d31c9916e7147a8"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filelock"
|
||||||
|
version = "3.12.2"
|
||||||
|
description = "A platform independent file lock."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "filelock-3.12.2-py3-none-any.whl", hash = "sha256:cbb791cdea2a72f23da6ac5b5269ab0a0d161e9ef0100e653b69049a7706d1ec"},
|
||||||
|
{file = "filelock-3.12.2.tar.gz", hash = "sha256:002740518d8aa59a26b0c76e10fb8c6e15eae825d34b6fdf670333fd7b938d81"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo (>=2023.5.20)", "sphinx (>=7.0.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
||||||
|
testing = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "diff-cover (>=7.5)", "pytest (>=7.3.1)", "pytest-cov (>=4.1)", "pytest-mock (>=3.10)", "pytest-timeout (>=2.1)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "identify"
|
||||||
|
version = "2.5.27"
|
||||||
|
description = "File identification library for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "identify-2.5.27-py2.py3-none-any.whl", hash = "sha256:fdb527b2dfe24602809b2201e033c2a113d7bdf716db3ca8e3243f735dcecaba"},
|
||||||
|
{file = "identify-2.5.27.tar.gz", hash = "sha256:287b75b04a0e22d727bc9a41f0d4f3c1bcada97490fa6eabb5b28f0e9097e733"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
license = ["ukkonen"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iniconfig"
|
||||||
|
version = "2.0.0"
|
||||||
|
description = "brain-dead simple config-ini parsing"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
||||||
|
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "isort"
|
||||||
|
version = "5.12.0"
|
||||||
|
description = "A Python utility / library to sort Python imports."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8.0"
|
||||||
|
files = [
|
||||||
|
{file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
|
||||||
|
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
colors = ["colorama (>=0.4.3)"]
|
||||||
|
pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
|
||||||
|
plugins = ["setuptools"]
|
||||||
|
requirements-deprecated-finder = ["pip-api", "pipreqs"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy-object-proxy"
|
||||||
|
version = "1.9.0"
|
||||||
|
description = "A fast and thorough lazy object proxy."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b40387277b0ed2d0602b8293b94d7257e17d1479e257b4de114ea11a8cb7f2d7"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8c6cfb338b133fbdbc5cfaa10fe3c6aeea827db80c978dbd13bc9dd8526b7d4"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:721532711daa7db0d8b779b0bb0318fa87af1c10d7fe5e52ef30f8eff254d0cd"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:66a3de4a3ec06cd8af3f61b8e1ec67614fbb7c995d02fa224813cb7afefee701"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:1aa3de4088c89a1b69f8ec0dcc169aa725b0ff017899ac568fe44ddc1396df46"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-win32.whl", hash = "sha256:f0705c376533ed2a9e5e97aacdbfe04cecd71e0aa84c7c0595d02ef93b6e4455"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:ea806fd4c37bf7e7ad82537b0757999264d5f70c45468447bb2b91afdbe73a6e"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:946d27deaff6cf8452ed0dba83ba38839a87f4f7a9732e8f9fd4107b21e6ff07"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a31b086e7e68b24b99b23d57723ef7e2c6d81ed21007b6281ebcd1688acb0a"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f699ac1c768270c9e384e4cbd268d6e67aebcfae6cd623b4d7c3bfde5a35db59"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bfb38f9ffb53b942f2b5954e0f610f1e721ccebe9cce9025a38c8ccf4a5183a4"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:189bbd5d41ae7a498397287c408617fe5c48633e7755287b21d741f7db2706a9"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-win32.whl", hash = "sha256:81fc4d08b062b535d95c9ea70dbe8a335c45c04029878e62d744bdced5141586"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:f2457189d8257dd41ae9b434ba33298aec198e30adf2dcdaaa3a28b9994f6adb"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d9e25ef10a39e8afe59a5c348a4dbf29b4868ab76269f81ce1674494e2565a6e"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cbf9b082426036e19c6924a9ce90c740a9861e2bdc27a4834fd0a910742ac1e8"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9f5fa4a61ce2438267163891961cfd5e32ec97a2c444e5b842d574251ade27d2"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:8fa02eaab317b1e9e03f69aab1f91e120e7899b392c4fc19807a8278a07a97e8"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:e7c21c95cae3c05c14aafffe2865bbd5e377cfc1348c4f7751d9dc9a48ca4bda"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-win32.whl", hash = "sha256:f12ad7126ae0c98d601a7ee504c1122bcef553d1d5e0c3bfa77b16b3968d2734"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp37-cp37m-win_amd64.whl", hash = "sha256:edd20c5a55acb67c7ed471fa2b5fb66cb17f61430b7a6b9c3b4a1e40293b1671"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2d0daa332786cf3bb49e10dc6a17a52f6a8f9601b4cf5c295a4f85854d61de63"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cd077f3d04a58e83d04b20e334f678c2b0ff9879b9375ed107d5d07ff160171"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:660c94ea760b3ce47d1855a30984c78327500493d396eac4dfd8bd82041b22be"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:212774e4dfa851e74d393a2370871e174d7ff0ebc980907723bb67d25c8a7c30"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f0117049dd1d5635bbff65444496c90e0baa48ea405125c088e93d9cf4525b11"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-win32.whl", hash = "sha256:0a891e4e41b54fd5b8313b96399f8b0e173bbbfc03c7631f01efbe29bb0bcf82"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:9990d8e71b9f6488e91ad25f322898c136b008d87bf852ff65391b004da5e17b"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9e7551208b2aded9c1447453ee366f1c4070602b3d932ace044715d89666899b"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f83ac4d83ef0ab017683d715ed356e30dd48a93746309c8f3517e1287523ef4"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7322c3d6f1766d4ef1e51a465f47955f1e8123caee67dd641e67d539a534d006"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:18b78ec83edbbeb69efdc0e9c1cb41a3b1b1ed11ddd8ded602464c3fc6020494"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:09763491ce220c0299688940f8dc2c5d05fd1f45af1e42e636b2e8b2303e4382"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-win32.whl", hash = "sha256:9090d8e53235aa280fc9239a86ae3ea8ac58eff66a705fa6aa2ec4968b95c821"},
|
||||||
|
{file = "lazy_object_proxy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:db1c1722726f47e10e0b5fdbf15ac3b8adb58c091d12b3ab713965795036985f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "markdown-it-py"
|
||||||
|
version = "2.2.0"
|
||||||
|
description = "Python port of markdown-it. Markdown parsing, done right!"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "markdown-it-py-2.2.0.tar.gz", hash = "sha256:7c9a5e412688bc771c67432cbfebcdd686c93ce6484913dccf06cb5a0bea35a1"},
|
||||||
|
{file = "markdown_it_py-2.2.0-py3-none-any.whl", hash = "sha256:5a35f8d1870171d9acc47b99612dc146129b631baf04970128b568f190d0cc30"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mdurl = ">=0.1,<1.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
benchmarking = ["psutil", "pytest", "pytest-benchmark"]
|
||||||
|
code-style = ["pre-commit (>=3.0,<4.0)"]
|
||||||
|
compare = ["commonmark (>=0.9,<1.0)", "markdown (>=3.4,<4.0)", "mistletoe (>=1.0,<2.0)", "mistune (>=2.0,<3.0)", "panflute (>=2.3,<3.0)"]
|
||||||
|
linkify = ["linkify-it-py (>=1,<3)"]
|
||||||
|
plugins = ["mdit-py-plugins"]
|
||||||
|
profiling = ["gprof2dot"]
|
||||||
|
rtd = ["attrs", "myst-parser", "pyyaml", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinx_book_theme"]
|
||||||
|
testing = ["coverage", "pytest", "pytest-cov", "pytest-regressions"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mccabe"
|
||||||
|
version = "0.7.0"
|
||||||
|
description = "McCabe checker, plugin for flake8"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"},
|
||||||
|
{file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mdurl"
|
||||||
|
version = "0.1.2"
|
||||||
|
description = "Markdown URL utilities"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8"},
|
||||||
|
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy"
|
||||||
|
version = "1.3.0"
|
||||||
|
description = "Optional static typing for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "mypy-1.3.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c1eb485cea53f4f5284e5baf92902cd0088b24984f4209e25981cc359d64448d"},
|
||||||
|
{file = "mypy-1.3.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:4c99c3ecf223cf2952638da9cd82793d8f3c0c5fa8b6ae2b2d9ed1e1ff51ba85"},
|
||||||
|
{file = "mypy-1.3.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:550a8b3a19bb6589679a7c3c31f64312e7ff482a816c96e0cecec9ad3a7564dd"},
|
||||||
|
{file = "mypy-1.3.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cbc07246253b9e3d7d74c9ff948cd0fd7a71afcc2b77c7f0a59c26e9395cb152"},
|
||||||
|
{file = "mypy-1.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:a22435632710a4fcf8acf86cbd0d69f68ac389a3892cb23fbad176d1cddaf228"},
|
||||||
|
{file = "mypy-1.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6e33bb8b2613614a33dff70565f4c803f889ebd2f859466e42b46e1df76018dd"},
|
||||||
|
{file = "mypy-1.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d23370d2a6b7a71dc65d1266f9a34e4cde9e8e21511322415db4b26f46f6b8c"},
|
||||||
|
{file = "mypy-1.3.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658fe7b674769a0770d4b26cb4d6f005e88a442fe82446f020be8e5f5efb2fae"},
|
||||||
|
{file = "mypy-1.3.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d29e324cdda61daaec2336c42512e59c7c375340bd202efa1fe0f7b8f8ca"},
|
||||||
|
{file = "mypy-1.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:d0b6c62206e04061e27009481cb0ec966f7d6172b5b936f3ead3d74f29fe3dcf"},
|
||||||
|
{file = "mypy-1.3.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:76ec771e2342f1b558c36d49900dfe81d140361dd0d2df6cd71b3db1be155409"},
|
||||||
|
{file = "mypy-1.3.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ebc95f8386314272bbc817026f8ce8f4f0d2ef7ae44f947c4664efac9adec929"},
|
||||||
|
{file = "mypy-1.3.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:faff86aa10c1aa4a10e1a301de160f3d8fc8703b88c7e98de46b531ff1276a9a"},
|
||||||
|
{file = "mypy-1.3.0-cp37-cp37m-win_amd64.whl", hash = "sha256:8c5979d0deb27e0f4479bee18ea0f83732a893e81b78e62e2dda3e7e518c92ee"},
|
||||||
|
{file = "mypy-1.3.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c5d2cc54175bab47011b09688b418db71403aefad07cbcd62d44010543fc143f"},
|
||||||
|
{file = "mypy-1.3.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:87df44954c31d86df96c8bd6e80dfcd773473e877ac6176a8e29898bfb3501cb"},
|
||||||
|
{file = "mypy-1.3.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:473117e310febe632ddf10e745a355714e771ffe534f06db40702775056614c4"},
|
||||||
|
{file = "mypy-1.3.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:74bc9b6e0e79808bf8678d7678b2ae3736ea72d56eede3820bd3849823e7f305"},
|
||||||
|
{file = "mypy-1.3.0-cp38-cp38-win_amd64.whl", hash = "sha256:44797d031a41516fcf5cbfa652265bb994e53e51994c1bd649ffcd0c3a7eccbf"},
|
||||||
|
{file = "mypy-1.3.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ddae0f39ca146972ff6bb4399f3b2943884a774b8771ea0a8f50e971f5ea5ba8"},
|
||||||
|
{file = "mypy-1.3.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1c4c42c60a8103ead4c1c060ac3cdd3ff01e18fddce6f1016e08939647a0e703"},
|
||||||
|
{file = "mypy-1.3.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e86c2c6852f62f8f2b24cb7a613ebe8e0c7dc1402c61d36a609174f63e0ff017"},
|
||||||
|
{file = "mypy-1.3.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f9dca1e257d4cc129517779226753dbefb4f2266c4eaad610fc15c6a7e14283e"},
|
||||||
|
{file = "mypy-1.3.0-cp39-cp39-win_amd64.whl", hash = "sha256:95d8d31a7713510685b05fbb18d6ac287a56c8f6554d88c19e73f724a445448a"},
|
||||||
|
{file = "mypy-1.3.0-py3-none-any.whl", hash = "sha256:a8763e72d5d9574d45ce5881962bc8e9046bf7b375b0abf031f3e6811732a897"},
|
||||||
|
{file = "mypy-1.3.0.tar.gz", hash = "sha256:e1f4d16e296f5135624b34e8fb741eb0eadedca90862405b1f1fde2040b9bd11"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
mypy-extensions = ">=1.0.0"
|
||||||
|
typing-extensions = ">=3.10"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dmypy = ["psutil (>=4.0)"]
|
||||||
|
install-types = ["pip"]
|
||||||
|
python2 = ["typed-ast (>=1.4.0,<2)"]
|
||||||
|
reports = ["lxml"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mypy-extensions"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "Type system extensions for programs checked with the mypy type checker."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.5"
|
||||||
|
files = [
|
||||||
|
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
|
||||||
|
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nodeenv"
|
||||||
|
version = "1.8.0"
|
||||||
|
description = "Node.js virtual environment builder"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*"
|
||||||
|
files = [
|
||||||
|
{file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"},
|
||||||
|
{file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
setuptools = "*"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "packaging"
|
||||||
|
version = "23.1"
|
||||||
|
description = "Core utilities for Python packages"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"},
|
||||||
|
{file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "platformdirs"
|
||||||
|
version = "3.5.1"
|
||||||
|
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"},
|
||||||
|
{file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
||||||
|
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pluggy"
|
||||||
|
version = "1.0.0"
|
||||||
|
description = "plugin and hook calling mechanisms for python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "pluggy-1.0.0-py2.py3-none-any.whl", hash = "sha256:74134bbf457f031a36d68416e1509f34bd5ccc019f0bcc952c7b909d06b37bd3"},
|
||||||
|
{file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
dev = ["pre-commit", "tox"]
|
||||||
|
testing = ["pytest", "pytest-benchmark"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pre-commit"
|
||||||
|
version = "3.3.3"
|
||||||
|
description = "A framework for managing and maintaining multi-language pre-commit hooks."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "pre_commit-3.3.3-py2.py3-none-any.whl", hash = "sha256:10badb65d6a38caff29703362271d7dca483d01da88f9d7e05d0b97171c136cb"},
|
||||||
|
{file = "pre_commit-3.3.3.tar.gz", hash = "sha256:a2256f489cd913d575c145132ae196fe335da32d91a8294b7afe6622335dd023"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
cfgv = ">=2.0.0"
|
||||||
|
identify = ">=1.0.0"
|
||||||
|
nodeenv = ">=0.11.1"
|
||||||
|
pyyaml = ">=5.1"
|
||||||
|
virtualenv = ">=20.10.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pygments"
|
||||||
|
version = "2.15.1"
|
||||||
|
description = "Pygments is a syntax highlighting package written in Python."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "Pygments-2.15.1-py3-none-any.whl", hash = "sha256:db2db3deb4b4179f399a09054b023b6a586b76499d36965813c71aa8ed7b5fd1"},
|
||||||
|
{file = "Pygments-2.15.1.tar.gz", hash = "sha256:8ace4d3c1dd481894b2005f560ead0f9f19ee64fe983366be1a21e171d12775c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
plugins = ["importlib-metadata"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pylint"
|
||||||
|
version = "2.17.4"
|
||||||
|
description = "python code static checker"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.2"
|
||||||
|
files = [
|
||||||
|
{file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"},
|
||||||
|
{file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
astroid = ">=2.15.4,<=2.17.0-dev0"
|
||||||
|
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||||
|
dill = {version = ">=0.3.6", markers = "python_version >= \"3.11\""}
|
||||||
|
isort = ">=4.2.5,<6"
|
||||||
|
mccabe = ">=0.6,<0.8"
|
||||||
|
platformdirs = ">=2.2.0"
|
||||||
|
tomlkit = ">=0.10.1"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
spelling = ["pyenchant (>=3.2,<4.0)"]
|
||||||
|
testutils = ["gitpython (>3)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pytest"
|
||||||
|
version = "7.3.1"
|
||||||
|
description = "pytest: simple powerful testing with Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "pytest-7.3.1-py3-none-any.whl", hash = "sha256:3799fa815351fea3a5e96ac7e503a96fa51cc9942c3753cda7651b93c1cfa362"},
|
||||||
|
{file = "pytest-7.3.1.tar.gz", hash = "sha256:434afafd78b1d78ed0addf160ad2b77a30d35d4bdf8af234fe621919d9ed15e3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
iniconfig = "*"
|
||||||
|
packaging = "*"
|
||||||
|
pluggy = ">=0.12,<2.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pyyaml"
|
||||||
|
version = "6.0.1"
|
||||||
|
description = "YAML parser and emitter for Python"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||||
|
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||||
|
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||||
|
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||||
|
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||||
|
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||||
|
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
||||||
|
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
||||||
|
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
||||||
|
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
||||||
|
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
||||||
|
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
||||||
|
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
||||||
|
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
||||||
|
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
||||||
|
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
||||||
|
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||||
|
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||||
|
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||||
|
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||||
|
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||||
|
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||||
|
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rich"
|
||||||
|
version = "13.4.1"
|
||||||
|
description = "Render rich text, tables, progress bars, syntax highlighting, markdown and more to the terminal"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7.0"
|
||||||
|
files = [
|
||||||
|
{file = "rich-13.4.1-py3-none-any.whl", hash = "sha256:d204aadb50b936bf6b1a695385429d192bc1fdaf3e8b907e8e26f4c4e4b5bf75"},
|
||||||
|
{file = "rich-13.4.1.tar.gz", hash = "sha256:76f6b65ea7e5c5d924ba80e322231d7cb5b5981aa60bfc1e694f1bc097fe6fe1"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
markdown-it-py = ">=2.2.0,<3.0.0"
|
||||||
|
pygments = ">=2.13.0,<3.0.0"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
jupyter = ["ipywidgets (>=7.5.1,<9)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "setuptools"
|
||||||
|
version = "68.1.2"
|
||||||
|
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.8"
|
||||||
|
files = [
|
||||||
|
{file = "setuptools-68.1.2-py3-none-any.whl", hash = "sha256:3d8083eed2d13afc9426f227b24fd1659489ec107c0e86cec2ffdde5c92e790b"},
|
||||||
|
{file = "setuptools-68.1.2.tar.gz", hash = "sha256:3d4dfa6d95f1b101d695a6160a7626e15583af71a5f52176efa5d39a054d475d"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5,<=7.1.2)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (==0.8.3)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||||
|
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||||
|
testing-integration = ["build[virtualenv]", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tomlkit"
|
||||||
|
version = "0.11.8"
|
||||||
|
description = "Style preserving TOML library"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"},
|
||||||
|
{file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typing-extensions"
|
||||||
|
version = "4.6.2"
|
||||||
|
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"},
|
||||||
|
{file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "virtualenv"
|
||||||
|
version = "20.24.1"
|
||||||
|
description = "Virtual Python Environment builder"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "virtualenv-20.24.1-py3-none-any.whl", hash = "sha256:01aacf8decd346cf9a865ae85c0cdc7f64c8caa07ff0d8b1dfc1733d10677442"},
|
||||||
|
{file = "virtualenv-20.24.1.tar.gz", hash = "sha256:2ef6a237c31629da6442b0bcaa3999748108c7166318d1f55cc9f8d7294e97bd"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.dependencies]
|
||||||
|
distlib = ">=0.3.6,<1"
|
||||||
|
filelock = ">=3.12,<4"
|
||||||
|
platformdirs = ">=3.5.1,<4"
|
||||||
|
|
||||||
|
[package.extras]
|
||||||
|
docs = ["furo (>=2023.5.20)", "proselint (>=0.13)", "sphinx (>=7.0.1)", "sphinx-argparse (>=0.4)", "sphinxcontrib-towncrier (>=0.2.1a0)", "towncrier (>=23.6)"]
|
||||||
|
test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess (>=1)", "flaky (>=3.7)", "packaging (>=23.1)", "pytest (>=7.3.1)", "pytest-env (>=0.8.1)", "pytest-freezer (>=0.4.6)", "pytest-mock (>=3.10)", "pytest-randomly (>=3.12)", "pytest-timeout (>=2.1)", "setuptools (>=67.8)", "time-machine (>=2.9)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wrapt"
|
||||||
|
version = "1.15.0"
|
||||||
|
description = "Module for decorators, wrappers and monkey patching."
|
||||||
|
optional = false
|
||||||
|
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||||
|
files = [
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"},
|
||||||
|
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"},
|
||||||
|
{file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"},
|
||||||
|
{file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"},
|
||||||
|
{file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"},
|
||||||
|
{file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"},
|
||||||
|
{file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"},
|
||||||
|
{file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"},
|
||||||
|
{file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"},
|
||||||
|
{file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"},
|
||||||
|
{file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"},
|
||||||
|
{file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"},
|
||||||
|
{file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"},
|
||||||
|
{file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"},
|
||||||
|
{file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"},
|
||||||
|
{file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[metadata]
|
||||||
|
lock-version = "2.0"
|
||||||
|
python-versions = "^3.11"
|
||||||
|
content-hash = "ebdcc3cb72dd9c6dc736b31d92471656c82dc96ec6b9e67bf2886d5ca1c4f499"
|
||||||
+26
-5
@@ -1,10 +1,6 @@
|
|||||||
[build-system]
|
|
||||||
requires = ["hatchling"]
|
|
||||||
build-backend = "hatchling.build"
|
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "boggler"
|
name = "boggler"
|
||||||
version = "2.0.0"
|
version = "2.0.1"
|
||||||
authors = [
|
authors = [
|
||||||
{ name="Cameron Blankenbuehler", email="cameron.blankenbuehler@gmail.com" },
|
{ name="Cameron Blankenbuehler", email="cameron.blankenbuehler@gmail.com" },
|
||||||
]
|
]
|
||||||
@@ -21,3 +17,28 @@ classifiers = [
|
|||||||
[project.urls]
|
[project.urls]
|
||||||
"Homepage" = "https://github.com/cblanken/boggler"
|
"Homepage" = "https://github.com/cblanken/boggler"
|
||||||
"Bug Tracker" = "https://github.com/cblanken/boggler/issues"
|
"Bug Tracker" = "https://github.com/cblanken/boggler/issues"
|
||||||
|
|
||||||
|
[tool.poetry]
|
||||||
|
name = "boggler"
|
||||||
|
version = "2.0.1"
|
||||||
|
description = "Utilities for solving the Boggle word game."
|
||||||
|
authors = ["Cameron Blankenbuehler <cameron.blankenbuehler@protonmail.com>"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
|
[tool.poetry.dependencies]
|
||||||
|
python = "^3.11"
|
||||||
|
rich = "^13.4.1"
|
||||||
|
|
||||||
|
[tool.poetry.scripts]
|
||||||
|
boggler = "boggler.__main__:main"
|
||||||
|
|
||||||
|
|
||||||
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
pytest = "^7.3.1"
|
||||||
|
pylint = "^2.17.4"
|
||||||
|
mypy = "^1.3.0"
|
||||||
|
pre-commit = "^3.3.3"
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["poetry-core"]
|
||||||
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
'''Module to generate random Boggle boards for testing'''
|
|
||||||
from sys import argv, stderr
|
|
||||||
from random import randint, shuffle
|
|
||||||
from math import sqrt
|
|
||||||
from os import path
|
|
||||||
|
|
||||||
def read_dice_file(dice_path: str):
|
|
||||||
'''Return list of die strings from file ignoring all comments (#)'''
|
|
||||||
with open(path.abspath(dice_path), 'r+', encoding="utf-8") as file:
|
|
||||||
return [line.rstrip().split(',') for line in file.readlines() if line[0] != "#"]
|
|
||||||
|
|
||||||
def roll_die(die: str):
|
|
||||||
'''Return a face of the given die string to simulate rolling a die'''
|
|
||||||
return str(die[randint(0, len(die) - 1)])
|
|
||||||
|
|
||||||
def roll_dice(dice: list[str]):
|
|
||||||
'''Return a random roll for each die'''
|
|
||||||
return [ roll_die(die) for die in dice ]
|
|
||||||
|
|
||||||
def get_random_board(dice: list[str]):
|
|
||||||
shuffle(dice)
|
|
||||||
rolls = roll_dice(dice)
|
|
||||||
|
|
||||||
# Format dice rolls for boards file
|
|
||||||
board_size = int(sqrt(len(rolls)))
|
|
||||||
board = []
|
|
||||||
for i in range(0, len(dice), board_size):
|
|
||||||
board.append(rolls[i:i+board_size])
|
|
||||||
return board
|
|
||||||
|
|
||||||
def get_random_board_csv(dice: list[str]):
|
|
||||||
board = get_random_board(dice)
|
|
||||||
board = [",".join(row) for row in board]
|
|
||||||
return board
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if len(argv) != 2:
|
|
||||||
print('Usage: python3 board_randomizer.py <dice_file>')
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
dice = read_dice_file(path.abspath(argv[1]))
|
|
||||||
board = get_random_board_csv(dice)
|
|
||||||
for row in board:
|
|
||||||
print(row)
|
|
||||||
except Exception as e:
|
|
||||||
print("Argument must be a valid file path!", file=stderr)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
"""Boggler Demo"""
|
|
||||||
import sys
|
|
||||||
from pathlib import Path
|
|
||||||
from boggler_utils import BoggleBoard, build_full_boggle_tree, read_boggle_file
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if len(sys.argv) < 3 or len(sys.argv) > 4:
|
|
||||||
print('Usage: python3 boggler.py <BOARD_FILE> <WORDLISTS_DIR> [MAX_WORD_LENGTH]')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
board = read_boggle_file(Path(sys.argv[1]))
|
|
||||||
if len(sys.argv) == 3:
|
|
||||||
boggle_board = BoggleBoard(board)
|
|
||||||
elif len(sys.argv) == 4:
|
|
||||||
try:
|
|
||||||
boggle_board = BoggleBoard(board, int(sys.argv[3]))
|
|
||||||
except ValueError:
|
|
||||||
print("Invalid MAX_WORD_LENGTH. Please try again with a valid integer.")
|
|
||||||
sys.exit(1)
|
|
||||||
try:
|
|
||||||
boggle_tree = build_full_boggle_tree(boggle_board, Path(sys.argv[2]))
|
|
||||||
|
|
||||||
print("\nBOARD")
|
|
||||||
print(boggle_board)
|
|
||||||
|
|
||||||
for start_pos, tree in boggle_tree.items():
|
|
||||||
print(f"\nStarting @ {start_pos}...")
|
|
||||||
for word in tree.word_paths:
|
|
||||||
print(f"{word[0]: <{boggle_board.max_word_len}}: {word[1]}")
|
|
||||||
|
|
||||||
except ValueError as e:
|
|
||||||
print("The [MAX_WORD_LENGTH] argument must be an integer.")
|
|
||||||
print("Please try again.")
|
|
||||||
sys.exit(1)
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
if [ -z $1 ] || [ -z $2 ]; then
|
|
||||||
echo "Usage: WORDLIST OUT_DIR"
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
grep -ioP "^a[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_a.txt"
|
|
||||||
grep -ioP "^b[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_b.txt"
|
|
||||||
grep -ioP "^c[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_c.txt"
|
|
||||||
grep -ioP "^d[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_d.txt"
|
|
||||||
grep -ioP "^e[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_e.txt"
|
|
||||||
grep -ioP "^f[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_f.txt"
|
|
||||||
grep -ioP "^g[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_g.txt"
|
|
||||||
grep -ioP "^h[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_h.txt"
|
|
||||||
grep -ioP "^i[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_i.txt"
|
|
||||||
grep -ioP "^j[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_j.txt"
|
|
||||||
grep -ioP "^k[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_k.txt"
|
|
||||||
grep -ioP "^l[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_l.txt"
|
|
||||||
grep -ioP "^m[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_m.txt"
|
|
||||||
grep -ioP "^n[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_n.txt"
|
|
||||||
grep -ioP "^o[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_o.txt"
|
|
||||||
grep -ioP "^p[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_p.txt"
|
|
||||||
grep -ioP "^q[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_q.txt"
|
|
||||||
grep -ioP "^r[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_r.txt"
|
|
||||||
grep -ioP "^s[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_s.txt"
|
|
||||||
grep -ioP "^t[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_t.txt"
|
|
||||||
grep -ioP "^u[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_u.txt"
|
|
||||||
grep -ioP "^v[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_v.txt"
|
|
||||||
grep -ioP "^w[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_w.txt"
|
|
||||||
grep -ioP "^x[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_x.txt"
|
|
||||||
grep -ioP "^y[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_y.txt"
|
|
||||||
grep -ioP "^z[a-z]+" $1 | tr [A-Z] [a-z] | sort | uniq > "$2/words_z.txt"
|
|
||||||
touch "$2/words__.txt"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,4 @@
|
|||||||
|
u, n,r ,e
|
||||||
|
qu, n,i, l
|
||||||
|
i ,s,h, a
|
||||||
|
s ,e , l,b
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
|
||||||
|
u,n,r,e
|
||||||
|
qu,n,i,l
|
||||||
|
i,s,h,a
|
||||||
|
|
||||||
|
s,e,l,b
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
u,n,r,e
|
||||||
|
qu,n,i,l
|
||||||
|
i,s,h,a
|
||||||
|
s,e,l,b
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
u,n,r,e,a,i
|
||||||
|
qu,n,i,l
|
||||||
|
i,s,h,a,j
|
||||||
|
s,e,l
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
u,n,r,e
|
||||||
|
qu,n,i,l
|
||||||
|
i,s,h,a
|
||||||
|
s,e,l,b
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
u,n,r,e
|
||||||
|
qu,n,i,l
|
||||||
|
i,s,h,a
|
||||||
|
s,e,l,b
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
u,n,r,e,b
|
||||||
|
qu,n,i,l
|
||||||
|
i,s,h,a,g,i
|
||||||
|
s,e,l,b
|
||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../boggler
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user