37 Commits
Author SHA1 Message Date
cblanken a80111072f Bump release version 2022-12-30 20:55:44 -05:00
cblanken fa01d442a5 Fix bug in board randomizer
- The board randomizer did not account for dice files that don't contain an exact integer squared number of dice. For example the 5x5 dice file contains 26 possible dice since 1 extra die is provided.
- The fix takes the square root of the number of dice and takes the floor of that number as the total number of dice to choose.
2022-12-30 19:54:00 -05:00
cblanken 733c1474b0 Add 5x5 dice file 2022-12-30 19:51:41 -05:00
cblanken 54f79c0afe Remove dead code from boggler.py 2022-11-16 20:37:30 -05:00
cblanken 9f364ee90e Remove old dictionary word prefix lists 2022-11-16 20:36:55 -05:00
cblanken e219954ba6 Add function to flatten boggle board results into 1D list 2022-10-10 12:00:42 -04:00
cblanken f4accfe959 Update wordlist splitting script
- use ripgrep to exclude proper nouns (with capitals) output only the
  capture group
2022-09-28 13:01:39 -04:00
cblanken bc70b88bf7 Bump version 2.0.0 2022-09-26 11:44:51 -04:00
cblanken 21aab46b96 Refactor board_randomizer
- Make file read separate and return "dice" or a list of strings from
  dice handling functions for use in downstream programs
2022-09-26 11:40:36 -04:00
cblanken f18c30cb60 Rename Super Big Boggle dice file 2022-09-23 10:20:48 -04:00
cblanken da915b723c Update wordlist splitting script
- Force lowercase on split
- Only match single (non compound) words
- Don't match punctuation
- Sort and uniquify
2022-09-23 10:20:48 -04:00
cblanken d5a102713d Fix die letters for 'New Boggle' dice 2022-09-23 10:20:38 -04:00
cblanken c488263eea Bump version and update license 2022-09-21 10:15:14 -04:00
cblanken fe1f1c2b97 Fix MAX_WORD_LENGTH parsing 2022-09-21 10:04:02 -04:00
cblanken d2584686a3 Fix max word length
- Previously the max word length parameter was checking the tree depths
  instead of the length of the word
- This fix acounts for multi-letter blocks like 'Qu', 'Tr' etc.
2022-09-21 09:45:09 -04:00
cblanken 8f75604d15 Handle blocks with empty strings and non-existant wordlists 2022-09-20 22:45:57 -04:00
cblanken 96da732dd9 Update board_randomizer module
- Fix typo: randimizer to randomizer
- Add module function to get direct 2d array of board values
2022-09-20 15:58:26 -04:00
cblanken ec53042d18 Update and move word splitting script 2022-09-20 13:21:57 -04:00
cblankenandGitHub 5c18a4aebf Update README.md 2022-09-15 14:06:55 -04:00
cblanken b197253d86 Add 9x9 dice file 2022-09-15 13:44:14 -04:00
cblanken 67f8c439b0 Update release version 2022-09-15 13:44:14 -04:00
cblanken 8c41ad212d Add missing __init__.py for PyPI package 2022-09-15 13:44:14 -04:00
cblanken 94800909b4 Update project version number 2022-09-15 13:44:14 -04:00
cblanken f24b996411 Update README.md 2022-09-15 13:44:14 -04:00
cblanken e4df95cd08 Update .gitignore 2022-09-15 13:44:14 -04:00
cblanken 0e9b120e94 Reorganize files into PyPI package format 2022-09-15 13:44:14 -04:00
cblanken 276c27f1ce Add pyproject.toml for PyPI 2022-09-15 13:44:13 -04:00
cblanken d30c44af3c Add MIT LICENSE 2022-09-15 13:43:55 -04:00
cblanken 5da33cf02c Update dice files 2022-09-07 11:27:09 -04:00
cblanken 600efc19c2 Remove old demo code from boggler_utils.py 2022-09-07 10:29:56 -04:00
cblanken cdb1542184 Fix bug loading duplicate wordlist for multi-letter blocks 2022-09-07 10:28:12 -04:00
cblanken 795f1540b4 Generate '_' words file for 6x6 board 2022-09-06 15:34:01 -04:00
cblanken 91390ea425 Add empty _ word files
The "_" is used to support the "blank" or "block" characters in Super Big Boggle (6x6).
2022-09-06 15:28:15 -04:00
cblanken 2a6a27b0b8 Update 4x4 dice and add 6x6 dice 2022-09-06 15:27:19 -04:00
cblanken b445071ccc Merge branch 'multiprocessing' 2022-09-06 15:10:27 -04:00
cblanken 9c8e94964c Add multiprocessing for board solving 2022-09-06 15:08:26 -04:00
cblanken 2fd5b05717 Update .gitignore 2022-09-01 15:29:37 -04:00
88 changed files with 374 additions and 58884 deletions
+8
View File
@@ -1 +1,9 @@
# Byte-compiled / optimized
__pycache__/
*.py[cod]
# Distribution / packaging
dist/
# Env
.vscode .vscode
+8
View File
@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright © 2022 Cameron Blankenbuehler
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+14 -7
View File
@@ -2,8 +2,12 @@
A solver for the popular word game Boggle. A solver for the popular word game Boggle.
# Install # Install
```bash ```console
$ git clone https://github.com/cblanken/boggler.git 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 To use the script to solve a particular Boggle board configuration, you'll need to do a few things
@@ -11,11 +15,11 @@ To use the script to solve a particular Boggle board configuration, you'll need
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.
```console ```console
$ cat boards/b1.csv $ cat board.csv
s,a,i,p y,e,o,s
l,qu,a,y r,e,o,v
u,l,l,s d,f,e,y
o,w,h,a n,m,e,qu
``` ```
2. Find a dictionary wordlist file or create your own 2. Find a dictionary wordlist file or create your own
@@ -394,3 +398,6 @@ quey : [(3, 3), (3, 2), (2, 3)]
quem : [(3, 3), (3, 2), (3, 1)] quem : [(3, 3), (3, 2), (3, 1)]
queme : [(3, 3), (3, 2), (3, 1), (2, 2)] queme : [(3, 3), (3, 2), (3, 1), (2, 2)]
``` ```
# License
The included [wordlists](src/boggler/wordlists) are covered by their respective licenses. All other files MIT © Cameron Blankenbuehler
-31
View File
@@ -1,31 +0,0 @@
'''Module to generate random Boggle boards for testing'''
from sys import argv
from random import randint, shuffle
from math import sqrt
def read_dice_file(path):
# TODO: Factor in 'qu' die face
'''Return list of die strings from file ignoring all comments (#)'''
with open(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 ]
if __name__ == '__main__':
if len(argv) != 2:
print('Usage: python3 board_randomizer.py <dice_file>')
else:
dice_strings = read_dice_file(argv[1])
shuffle(dice_strings)
rolls = roll_dice(dice_strings)
# Format dice rolls for boards file
board_size = int(sqrt(len(rolls)))
for i in range(0, len(dice_strings), board_size):
print(",".join(rolls[i:i+board_size]))
-17
View File
@@ -1,17 +0,0 @@
# front,right,back,left,top,bottom (start with 'one of' the first alphabetical chars
a,h,s,p,o,c
e,r,l,i,x,d
a,g,a,e,e,a
e,y,t,l,r,t
e,o,t,s,s,i
d,r,y,v,l,e
h,n,l,n,z,r
e,r,w,t,v,h
h,i,u,n,m,qu
e,e,h,n,w,g
d,t,y,t,i,s
a,b,b,o,o,j
e,i,u,n,s,e
a,s,p,f,k,f
c,m,u,o,i,t
a,w,t,o,o,t
1 # front right back left top bottom (start with 'one of' the first alphabetical chars
2 a h s p o c
3 e r l i x d
4 a g a e e a
5 e y t l r t
6 e o t s s i
7 d r y v l e
8 h n l n z r
9 e r w t v h
10 h i u n m qu
11 e e h n w g
12 d t y t i s
13 a b b o o j
14 e i u n s e
15 a s p f k f
16 c m u o i t
17 a w t o o t
+23
View File
@@ -0,0 +1,23 @@
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
name = "boggler"
version = "2.0.1"
authors = [
{ name="Cameron Blankenbuehler", email="cameron.blankenbuehler@gmail.com" },
]
description = "Utilities for solving the Boggle word game."
readme="README.md"
license = { file="LICENSE" }
requires-python = ">=3.7"
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: POSIX :: Linux",
]
[project.urls]
"Homepage" = "https://github.com/cblanken/boggler"
"Bug Tracker" = "https://github.com/cblanken/boggler/issues"
-34
View File
@@ -1,34 +0,0 @@
#!/bin/sh
if [ -z $1 ] || [ -z $2 ]; then
echo "Usage: ./filter_prefix.sh WORDLIST OUT_DIR"
exit 0
else
grep -P "^a" $1 > "$2/words_a.txt"
grep -P "^b" $1 > "$2/words_b.txt"
grep -P "^c" $1 > "$2/words_c.txt"
grep -P "^d" $1 > "$2/words_d.txt"
grep -P "^e" $1 > "$2/words_e.txt"
grep -P "^f" $1 > "$2/words_f.txt"
grep -P "^g" $1 > "$2/words_g.txt"
grep -P "^h" $1 > "$2/words_h.txt"
grep -P "^i" $1 > "$2/words_i.txt"
grep -P "^j" $1 > "$2/words_j.txt"
grep -P "^k" $1 > "$2/words_k.txt"
grep -P "^l" $1 > "$2/words_l.txt"
grep -P "^m" $1 > "$2/words_m.txt"
grep -P "^n" $1 > "$2/words_n.txt"
grep -P "^o" $1 > "$2/words_o.txt"
grep -P "^p" $1 > "$2/words_p.txt"
grep -P "^q" $1 > "$2/words_q.txt"
grep -P "^r" $1 > "$2/words_r.txt"
grep -P "^s" $1 > "$2/words_s.txt"
grep -P "^t" $1 > "$2/words_t.txt"
grep -P "^u" $1 > "$2/words_u.txt"
grep -P "^v" $1 > "$2/words_v.txt"
grep -P "^w" $1 > "$2/words_w.txt"
grep -P "^x" $1 > "$2/words_x.txt"
grep -P "^y" $1 > "$2/words_y.txt"
grep -P "^z" $1 > "$2/words_z.txt"
exit 0
fi
View File
+48
View File
@@ -0,0 +1,48 @@
'''Module to generate random Boggle boards for testing'''
from sys import argv, stderr
from random import randint, shuffle
from math import sqrt, floor
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(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: 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 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)
+18 -17
View File
@@ -11,23 +11,24 @@ if __name__ == '__main__':
board = read_boggle_file(Path(sys.argv[1])) board = read_boggle_file(Path(sys.argv[1]))
if len(sys.argv) == 3: if len(sys.argv) == 3:
boggle_board = BoggleBoard(board) boggle_board = BoggleBoard(board)
print(boggle_board)
boggle_tree = build_full_boggle_tree(boggle_board, Path(sys.argv[2]))
elif len(sys.argv) == 4: elif len(sys.argv) == 4:
try : try:
boggle_board = BoggleBoard(board, int(sys.argv[3])) boggle_board = BoggleBoard(board, int(sys.argv[3]))
print(boggle_board) except ValueError:
boggle_tree = build_full_boggle_tree(boggle_board, Path(sys.argv[2])) print("Invalid MAX_WORD_LENGTH. Please try again with a valid integer.")
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) 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)
+39 -33
View File
@@ -1,9 +1,9 @@
'''Boggler Utils''' '''Boggler Utils'''
from __future__ import annotations from __future__ import annotations
from os import path from os import path
from multiprocessing import Pool from multiprocessing import Pool
import sys import functools
import operator
class BoardCell: class BoardCell:
'''Boggle Board cell''' '''Boggle Board cell'''
@@ -199,9 +199,9 @@ class WordNode:
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: str, root: WordNode, words: list[str] = None, def __init__(self, alphabet: list, root: WordNode, words: list[str] = None,
max_word_len = 16) -> WordTree: max_word_len = 16) -> WordTree:
self.__alphabet: str = alphabet self.__alphabet: list = alphabet
self.__wordlist: list[str] = words self.__wordlist: list[str] = words
self.__root: WordNode = root self.__root: WordNode = root
self.__max_word_len: int = max_word_len self.__max_word_len: int = max_word_len
@@ -218,7 +218,7 @@ class WordTree:
self.__insert_word(word) self.__insert_word(word)
@property @property
def alphabet(self) -> str: def alphabet(self) -> list:
'''Getter for alphabet property''' '''Getter for alphabet property'''
return self.__alphabet return self.__alphabet
@@ -280,7 +280,7 @@ class WordTree:
continue continue
try: try:
alpha_index = [x[0] for x in self.alphabet].index(letter) alpha_index = self.alphabet.index(letter)
except ValueError: # letters not in given alphabet except ValueError: # letters not in given alphabet
return False return False
@@ -309,7 +309,6 @@ class WordTree:
# 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
#print(f"Added: {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:
@@ -327,7 +326,7 @@ class WordTree:
# 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, depth: int = 1) -> WordTree: def build_boggle_tree(self, board: BoggleBoard, board_cell: BoardCell, subtree: WordTree, word_len: int = 0) -> WordTree:
'''Return subtree of board given a particular root (first letter). '''Return subtree of board given a particular root (first letter).
Keyword arguments: Keyword arguments:
@@ -337,6 +336,12 @@ class WordTree:
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:
#print(f"MAX DEPTH REACHED! Depth = {depth}")
subtree.active_node = subtree.active_node.parent
self.active_node = self.active_node.parent
return
# 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]
@@ -350,12 +355,6 @@ class WordTree:
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) #print("2: WORD FOUND:", "".join([board.board[x].letters for x in word_path]), word_path)
if depth >= self.max_word_len or depth >= board.max_word_len:
#print(f"MAX DEPTH REACHED! Depth = {depth}")
subtree.active_node = subtree.active_node.parent
self.active_node = self.active_node.parent
return
# 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
@@ -364,8 +363,7 @@ class WordTree:
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[cell.letters] # update subtree pointer
self.active_node = self.active_node.children[cell.letters] # update dictionary tree pointer self.active_node = self.active_node.children[cell.letters] # update dictionary tree pointer
self.build_boggle_tree(board, board.board[cell.pos], subtree, depth=depth+1) self.build_boggle_tree(board, board.board[cell.pos], subtree, word_len=word_len+len(board_cell.letters))
#print(f"depth: {depth}")
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
@@ -386,16 +384,29 @@ def build_full_boggle_tree(board: BoggleBoard, wordlist_path: str) -> dict[str,
index = {} index = {}
print("Reading in wordlists...") print("Reading in wordlists...")
for letter in alphabet: for letters in alphabet:
filename = "words_" + letter[0] + ".txt" if letters == "":
print(f">> {letter}: {filename}") # Skip wordlist read for blocks with empty string
wordlist = read_wordlist(path.join(path.abspath(wordlist_path), filename)) index[""] = {}
index[letter] = wordlist continue
elif letters[0] in index:
index[letters] = index[letters[0]]
continue
filename = "words_" + letters[0] + ".txt"
try:
wordlist = read_wordlist(path.join(path.abspath(wordlist_path), filename))
index[letters] = wordlist
print(f">> {letters}: {filename}")
except FileNotFoundError:
print(f">> {letters}: -- Skipping -- no wordlist found for {letters}")
index[letters] = {}
print("Generating WordTrees...") print("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]}")
board_tree[params[i][2].pos] = res board_tree[params[i][2].pos] = res
return board_tree return board_tree
@@ -410,14 +421,9 @@ def read_boggle_file(file):
with open(file, 'r', encoding='utf-8') as file: with open(file, 'r', encoding='utf-8') as file:
return [x.rstrip().split(',') for x in file.readlines()] return [x.rstrip().split(',') for x in file.readlines()]
if __name__ == "__main__": def find_paths_by_word(board_letters, dictionary_path, max_len):
#b2 = read_boggle_file(sys.argv[1]) '''Return list of paths by word'''
b2 = read_boggle_file("boards/b1.csv") boggle_board = BoggleBoard(board_letters, max_len)
b2_board = BoggleBoard(b2) boggle_tree = build_full_boggle_tree(boggle_board, dictionary_path)
boggle_tree = build_full_boggle_tree(b2_board, "wordlists/dwyl") paths_by_word = functools.reduce(operator.iconcat, [x.word_paths for x in boggle_tree.values()], [])
print("\nBOARD") return paths_by_word
print(b2_board)
w1 = boggle_tree[(0,0)].word_paths
for w in w1:
print(f"{w[0]: <{b2_board.max_word_len}}: {w[1]}")
+17
View File
@@ -0,0 +1,17 @@
# Listed alphabetically
a,a,c,i,o,t
a,b,i,l,t,y
a,b,j,m,o,qu
a,c,d,e,m,p
a,c,e,l,r,s
a,d,e,n,v,z
a,h,m,o,r,s
b,i,f,o,r,x
d,e,n,o,s,w
d,k,n,o,t,u
e,e,f,h,i,y
e,g,k,l,u,y
e,g,i,n,t,v
e,h,i,n,p,s
e,l,p,s,t,u
g,i,l,r,u,w
1 # Listed alphabetically
2 a,a,c,i,o,t
3 a,b,i,l,t,y
4 a,b,j,m,o,qu
5 a,c,d,e,m,p
6 a,c,e,l,r,s
7 a,d,e,n,v,z
8 a,h,m,o,r,s
9 b,i,f,o,r,x
10 d,e,n,o,s,w
11 d,k,n,o,t,u
12 e,e,f,h,i,y
13 e,g,k,l,u,y
14 e,g,i,n,t,v
15 e,h,i,n,p,s
16 e,l,p,s,t,u
17 g,i,l,r,u,w
+17
View File
@@ -0,0 +1,17 @@
# Listed alphabetically
a,a,e,e,g,n
a,b,b,j,o,o
a,c,h,o,p,s
a,f,f,k,p,s
a,o,o,t,t,w
c,i,m,o,t,u
d,e,i,l,r,x
d,e,l,r,v,y
d,i,s,t,t,y
e,e,g,h,n,w
e,e,i,n,s,u
e,h,r,t,v,w
e,i,o,s,s,t
e,l,r,t,t,y
h,i,m,n,qu,u
h,l,n,n,r,z
1 # Listed alphabetically
2 a,a,e,e,g,n
3 a,b,b,j,o,o
4 a,c,h,o,p,s
5 a,f,f,k,p,s
6 a,o,o,t,t,w
7 c,i,m,o,t,u
8 d,e,i,l,r,x
9 d,e,l,r,v,y
10 d,i,s,t,t,y
11 e,e,g,h,n,w
12 e,e,i,n,s,u
13 e,h,r,t,v,w
14 e,i,o,s,s,t
15 e,l,r,t,t,y
16 h,i,m,n,qu,u
17 h,l,n,n,r,z
+27
View File
@@ -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
1 # Listed alphabetically
2 a,a,a,f,r,s
3 a,a,e,e,e,e
4 a,a,f,i,r,s
5 a,d,e,n,n,n
6 a,e,e,e,e,m
7 a,e,e,g,m,u
8 a,e,g,m,n,n
9 a,f,i,r,s,y
10 an,er,he,in,qu,th
11 b,j,k,qu,x,z
12 c,c,e,n,s,t
13 c,e,i,i,l,t
14 c,e,i,l,p,t
15 c,e,i,p,s,t
16 d,d,h,n,o,t
17 d,h,h,l,n,o
18 d,h,l,n,o,r
19 d,l,o,h,h,r
20 e,i,i,i,t,t
21 e,m,o,t,t,t
22 e,n,s,s,s,u
23 f,i,p,r,s,y
24 g,o,r,r,v,w
25 i,k,l,qu,u,w
26 n,o,o,t,u,w
27 o,o,o,t,t,u
+37
View File
@@ -0,0 +1,37 @@
# Listed alphabetically
_,_,_,e,i,o
a,a,a,f,r,s
a,a,e,e,e,e
a,a,e,e,o,o
a,a,f,i,r,s
a,b,d,e,i,o
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,e,i,l,m,n
a,e,i,n,o,u
a,f,i,r,s,y
an,er,he,in,qu,th
b,b,b,j,j,z
c,c,e,n,s,t
c,d,d,l,n,n
c,e,e,i,t,t
c,e,i,p,s,t
c,f,g,n,u,w
d,d,h,n,o,t
d,h,h,l,o,r
d,h,h,n,o,w
d,h,l,n,o,r
e,h,i,l,r,s
e,i,i,l,s,t
e,i,l,p,s,t
e,m,o,t,t,t
e,n,s,s,s,u
g,o,r,r,v,w
h,i,r,s,t,v
h,o,p,r,s,t
i,p,r,s,y,y
j,k,qu,w,x,z
n,o,o,t,u,w
o,o,o,t,t,u
1 # Listed alphabetically
2 _,_,_,e,i,o
3 a,a,a,f,r,s
4 a,a,e,e,e,e
5 a,a,e,e,o,o
6 a,a,f,i,r,s
7 a,b,d,e,i,o
8 a,d,e,n,n,n
9 a,e,e,e,e,m
10 a,e,e,g,m,u
11 a,e,g,m,n,n
12 a,e,i,l,m,n
13 a,e,i,n,o,u
14 a,f,i,r,s,y
15 an,er,he,in,qu,th
16 b,b,b,j,j,z
17 c,c,e,n,s,t
18 c,d,d,l,n,n
19 c,e,e,i,t,t
20 c,e,i,p,s,t
21 c,f,g,n,u,w
22 d,d,h,n,o,t
23 d,h,h,l,o,r
24 d,h,h,n,o,w
25 d,h,l,n,o,r
26 e,h,i,l,r,s
27 e,i,i,l,s,t
28 e,i,l,p,s,t
29 e,m,o,t,t,t
30 e,n,s,s,s,u
31 g,o,r,r,v,w
32 h,i,r,s,t,v
33 h,o,p,r,s,t
34 i,p,r,s,y,y
35 j,k,qu,w,x,z
36 n,o,o,t,u,w
37 o,o,o,t,t,u
+82
View File
@@ -0,0 +1,82 @@
# Made from 6x6 dice repeated to reach 9x9 (81) dice rolls
_,_,_,e,i,o
a,a,a,f,r,s
a,a,e,e,e,e
a,a,e,e,o,o
a,a,f,i,r,s
a,b,d,e,i,o
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,e,i,l,m,n
a,e,i,n,o,u
a,f,i,r,s,y
an,er,he,in,qu,th
b,b,b,j,j,z
c,c,e,n,s,t
c,d,d,l,n,n
c,e,e,i,t,t
c,e,i,p,s,t
c,f,g,n,u,w
d,d,h,n,o,t
d,h,h,l,o,r
d,h,h,n,o,w
d,h,l,n,o,r
e,h,i,l,r,s
e,i,i,l,s,t
e,i,l,p,s,t
e,m,o,t,t,t
e,n,s,s,s,u
g,o,r,r,v,w
h,i,r,s,t,v
h,o,p,r,s,t
i,p,r,s,y,y
j,k,qu,w,x,z
n,o,o,t,u,w
o,o,o,t,t,u
_,_,_,e,i,o
a,a,a,f,r,s
a,a,e,e,e,e
a,a,e,e,o,o
a,a,f,i,r,s
a,b,d,e,i,o
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,e,i,l,m,n
a,e,i,n,o,u
a,f,i,r,s,y
an,er,he,in,qu,th
b,b,b,j,j,z
c,c,e,n,s,t
c,d,d,l,n,n
c,e,e,i,t,t
c,e,i,p,s,t
c,f,g,n,u,w
d,d,h,n,o,t
d,h,h,l,o,r
d,h,h,n,o,w
d,h,l,n,o,r
e,h,i,l,r,s
e,i,i,l,s,t
e,i,l,p,s,t
e,m,o,t,t,t
e,n,s,s,s,u
g,o,r,r,v,w
h,i,r,s,t,v
h,o,p,r,s,t
i,p,r,s,y,y
j,k,qu,w,x,z
n,o,o,t,u,w
o,o,o,t,t,u
e,m,o,t,t,t
e,n,s,s,s,u
g,o,r,r,v,w
h,i,r,s,t,v
h,o,p,r,s,t
i,p,r,s,y,y
j,k,qu,w,x,z
n,o,o,t,u,w
o,o,o,t,t,u
1 # Made from 6x6 dice repeated to reach 9x9 (81) dice rolls
2 _,_,_,e,i,o
3 a,a,a,f,r,s
4 a,a,e,e,e,e
5 a,a,e,e,o,o
6 a,a,f,i,r,s
7 a,b,d,e,i,o
8 a,d,e,n,n,n
9 a,e,e,e,e,m
10 a,e,e,g,m,u
11 a,e,g,m,n,n
12 a,e,i,l,m,n
13 a,e,i,n,o,u
14 a,f,i,r,s,y
15 an,er,he,in,qu,th
16 b,b,b,j,j,z
17 c,c,e,n,s,t
18 c,d,d,l,n,n
19 c,e,e,i,t,t
20 c,e,i,p,s,t
21 c,f,g,n,u,w
22 d,d,h,n,o,t
23 d,h,h,l,o,r
24 d,h,h,n,o,w
25 d,h,l,n,o,r
26 e,h,i,l,r,s
27 e,i,i,l,s,t
28 e,i,l,p,s,t
29 e,m,o,t,t,t
30 e,n,s,s,s,u
31 g,o,r,r,v,w
32 h,i,r,s,t,v
33 h,o,p,r,s,t
34 i,p,r,s,y,y
35 j,k,qu,w,x,z
36 n,o,o,t,u,w
37 o,o,o,t,t,u
38 _,_,_,e,i,o
39 a,a,a,f,r,s
40 a,a,e,e,e,e
41 a,a,e,e,o,o
42 a,a,f,i,r,s
43 a,b,d,e,i,o
44 a,d,e,n,n,n
45 a,e,e,e,e,m
46 a,e,e,g,m,u
47 a,e,g,m,n,n
48 a,e,i,l,m,n
49 a,e,i,n,o,u
50 a,f,i,r,s,y
51 an,er,he,in,qu,th
52 b,b,b,j,j,z
53 c,c,e,n,s,t
54 c,d,d,l,n,n
55 c,e,e,i,t,t
56 c,e,i,p,s,t
57 c,f,g,n,u,w
58 d,d,h,n,o,t
59 d,h,h,l,o,r
60 d,h,h,n,o,w
61 d,h,l,n,o,r
62 e,h,i,l,r,s
63 e,i,i,l,s,t
64 e,i,l,p,s,t
65 e,m,o,t,t,t
66 e,n,s,s,s,u
67 g,o,r,r,v,w
68 h,i,r,s,t,v
69 h,o,p,r,s,t
70 i,p,r,s,y,y
71 j,k,qu,w,x,z
72 n,o,o,t,u,w
73 o,o,o,t,t,u
74 e,m,o,t,t,t
75 e,n,s,s,s,u
76 g,o,r,r,v,w
77 h,i,r,s,t,v
78 h,o,p,r,s,t
79 i,p,r,s,y,y
80 j,k,qu,w,x,z
81 n,o,o,t,u,w
82 o,o,o,t,t,u
+35
View File
@@ -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
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