Skip to content

Commit

Permalink
feat: intial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Lustyn committed Jan 18, 2022
0 parents commit 8784927
Show file tree
Hide file tree
Showing 12 changed files with 642 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.js
*.hurdle
node_modules/
37 changes: 37 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# hurdle
A small library that implements a tree structure for storing and querying case-insensitive word lists from games like Wordle.

## `hurdle.hurdle`
hurdle(path: string): Promise<HurdleTree>

Loads a JSON array of words from `path` and returns a `HurdleTree` object. This will cache a copy of the constructed tree to `${path}.hurdle` if one does not already exist, and reload it in subsequent calls.

## `HurdleTree.constructor`
constructor(root?: IHurdleTreeNode): HurdleTree

Constructs a new `HurdleTree`, optionally passing in the root node if you want to start with a pre-existing tree.

## `HurdleTree.insert`
insert(word: string): void

Inserts a word into the tree.

## `HurdleTree.insertMany`
insertMany(words: string[]): void

Inserts many words into the tree.

## `HurdleTree.searchIncludes`
searchIncludes(includes: Set<AChar>): string[]

Searches the tree for words that include ALL the characters in the given set at least once.

## `HurdleTree.searchIncludesOnly`
searchIncludesOnly(includes: Set<AChar>): string[]

Searches the tree for words that include ONLY the characters in the given set.

## `HurdleTree.searchExcludes`
searchExcludes(excludes: Set<AChar>): string[]

Searches the tree for words that exclude all the characters in the given set.
32 changes: 32 additions & 0 deletions examples/benchmarkExcludes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { hurdle, unique } from "../src/hurdle";
import * as fs from "fs/promises";
import { WORDS_PATH } from "./utils";

async function main() {
const tree = await hurdle(WORDS_PATH);

const testChars = unique("test");

const words = JSON.parse(await fs.readFile(WORDS_PATH, "utf8"));
console.time("iter");
let iterWords = [];
for (const word of words) {
let match = true;
for (const char of unique(word)) {
if (testChars.has(char)) {
match = false;
break;
}
}
if (match) iterWords.push(word);
}
console.timeEnd("iter");

console.time("query");
const queryWords = tree.searchExcludes(testChars)
console.timeEnd("query");

console.assert(iterWords.length === queryWords.length, "iter and query word counts must match");
};

main().catch(console.error);
18 changes: 18 additions & 0 deletions examples/excludes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { hurdle, setToArray, unique } from "../src/hurdle";
import { logTruncatedList, WORDS_PATH } from "./utils";

async function main() {
// Construct a tree from the words in a json file
const tree = await hurdle(WORDS_PATH);

// Create a Set of unique characters from the word "test"
const excludeChars = unique("test");

// Find words in the tree which do not contain ALL characters in the set
const words = tree.searchExcludes(excludeChars)

console.log(`The following words do not contain the characters ${setToArray(excludeChars).join(", ")}:`);
logTruncatedList(words, 10);
};

main().catch(console.error);
18 changes: 18 additions & 0 deletions examples/includes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { hurdle, setToArray, unique } from "../src/hurdle";
import { logTruncatedList, WORDS_PATH } from "./utils";

async function main() {
// Construct a tree from the words in a json file
const tree = await hurdle(WORDS_PATH);

// Create a Set of unique characters from the word "test"
const includeChars = unique("test");

// Find words in the tree which contain ALL characters in the set
const words = tree.searchIncludes(includeChars)

console.log(`The following words contain the characters ${setToArray(includeChars).join(", ")}:`);
logTruncatedList(words, 10);
};

main().catch(console.error);
18 changes: 18 additions & 0 deletions examples/includesOnly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { hurdle, setToArray, unique } from "../src/hurdle";
import { logTruncatedList, WORDS_PATH } from "./utils";

async function main() {
// Construct a tree from the words in a json file
const tree = await hurdle(WORDS_PATH);

// Create a Set of unique characters from the word "test"
const includeChars = unique("test");

// Find words in the tree which contain ONLY characters in the set
const words = tree.searchIncludesOnly(includeChars)

console.log(`The following words contain ONLY the characters ${setToArray(includeChars).join(", ")}:`);
logTruncatedList(words, 10);
};

main().catch(console.error);
11 changes: 11 additions & 0 deletions examples/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import path from "path";

export const WORDS_PATH = path.join(__dirname, "wordle_words.json");

export function logTruncatedList(words: string[], truncateAmount: number) {
const amountTruncated = words.length - truncateAmount;
const truncatedWords = words.slice(0, truncateAmount);
console.log(truncatedWords.join(", "));
if (amountTruncated > 0)
console.log(`... and ${amountTruncated} more`);
}
1 change: 1 addition & 0 deletions examples/wordle_words.json

Large diffs are not rendered by default.

Loading

0 comments on commit 8784927

Please sign in to comment.