fuzzyworld

word-waltz / files / scripts / build-word-list.js

build-word-list.js

Blame: the commit that last changed each line · file · history

4e18328c 2026-03-26 Pavel Safronov1#!/usr/bin/env node
2// Builds src/utils/wordList.ts from filtered-wordle-words.csv (answers)
3// and src/utils/validGuesses.ts from the word-list npm package.
4import { readFileSync, writeFileSync } from 'fs';
5import { resolve, dirname } from 'path';
6import { fileURLToPath } from 'url';
7import wordListPath from 'word-list';
8
9const __dirname = dirname(fileURLToPath(import.meta.url));
10const root = resolve(__dirname, '..');
11
12// --- 1. Generate validGuesses.ts from word-list package ---
13const allWords = readFileSync(wordListPath, 'utf8').split('\n');
14const guesses = allWords.filter(w => /^[a-z]{5}$/.test(w));
15writeFileSync(
16 resolve(root, 'src/utils/validGuesses.ts'),
17 [
18 '// cspell:disable',
19 '// AUTO-GENERATED — do not edit. Run: node scripts/build-word-list.js',
20 `export const VALID_GUESSES = new Set<string>(${JSON.stringify(guesses)});`,
21 '',
22 ].join('\n'),
23 'utf8',
24);
25console.log(`validGuesses.ts: ${guesses.length} words`);
26
27// --- 2. Generate wordList.ts from CSV answers list ---
28const answers = readFileSync(resolve(root, 'filtered-wordle-words.csv'), 'utf8')
29 .split('\n')
30 .map(w => w.trim().toLowerCase())
31 .filter(w => /^[a-z]{5}$/.test(w))
32 .sort();
33
34const answerLines = answers.map(w => ` "${w}",`).join('\n');
35const wordListTs = `// cspell:disable
36import { VALID_GUESSES } from './validGuesses.js';
37
38// The ~2300 common words Wordle picks from.
39// Used for WordPicker validation (challenger) and getRandomWord() in solo mode.
40const ANSWER_WORDS: string[] = [
41${answerLines}
42];
43
44const ANSWER_SET = new Set<string>(ANSWER_WORDS);
45
46/** Returns true if the word is a valid guess (full dictionary — answers + extended list). */
47export function isValidWord(word: string): boolean {
48 const w = word.toLowerCase();
49 return w.length === 5 && (ANSWER_SET.has(w) || VALID_GUESSES.has(w));
50}
51
52/** Returns true if the word can be used as a challenge (answers list only). */
53export function isValidAnswer(word: string): boolean {
54 return word.length === 5 && ANSWER_SET.has(word.toLowerCase());
55}
56
57/** Returns a random word from the answers list, upper-cased. */
58export function getRandomWord(): string {
59 return ANSWER_WORDS[Math.floor(Math.random() * ANSWER_WORDS.length)].toUpperCase();
60}
61`;
62
63writeFileSync(resolve(root, 'src/utils/wordList.ts'), wordListTs, 'utf8');
64console.log(`wordList.ts: ${answers.length} answer words`);