|
|
@@ -1,57 +1,47 @@
|
|
|
-import { readFileSync, writeFileSync } from 'fs';
|
|
|
+import { readFileSync } from 'fs';
|
|
|
import { resolve, dirname } from 'path';
|
|
|
import { fileURLToPath } from 'url';
|
|
|
-import type { WordBank, SolverReplay } from '@wordle/shared';
|
|
|
-import { solveEntropy } from './entropy.js';
|
|
|
-import { solveFrequency } from './frequency.js';
|
|
|
-import { solveVowelFirst } from './vowel-first.js';
|
|
|
-import { solveGreedy } from './greedy.js';
|
|
|
+import type { WordBank } from '@wordle/shared';
|
|
|
+import { solveEntropy, solveFrequency, solveVowelFirst, solveGreedy } from '@wordle/shared';
|
|
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
const MAX_ATTEMPTS = 6;
|
|
|
|
|
|
-function solveBank(bankPath: string) {
|
|
|
+const SOLVERS = [
|
|
|
+ { name: 'Entropy', fn: solveEntropy },
|
|
|
+ { name: 'Frequency', fn: solveFrequency },
|
|
|
+ { name: 'Vowel First', fn: solveVowelFirst },
|
|
|
+ { name: 'Greedy', fn: solveGreedy },
|
|
|
+];
|
|
|
+
|
|
|
+function validateBank(bankPath: string) {
|
|
|
console.log(`\n=== ${bankPath} ===`);
|
|
|
const bank: WordBank = JSON.parse(readFileSync(bankPath, 'utf-8'));
|
|
|
const allWords = bank.guessable;
|
|
|
|
|
|
- console.log(`Solving ${bank.targets.length} targets with ${allWords.length} words...`);
|
|
|
-
|
|
|
- let solved = 0, failed = 0;
|
|
|
- const newTargets: WordBank['targets'] = [];
|
|
|
+ console.log(`Validating ${bank.targets.length} targets with ${allWords.length} words...`);
|
|
|
|
|
|
+ let ok = 0, unsolvable = 0;
|
|
|
for (const target of bank.targets) {
|
|
|
- const results = [
|
|
|
- { name: 'Entropy', ...solveEntropy(target.word, allWords, MAX_ATTEMPTS) },
|
|
|
- { name: 'Frequency', ...solveFrequency(target.word, allWords, MAX_ATTEMPTS) },
|
|
|
- { name: 'Vowel First', ...solveVowelFirst(target.word, allWords, MAX_ATTEMPTS) },
|
|
|
- { name: 'Greedy', ...solveGreedy(target.word, allWords, MAX_ATTEMPTS) },
|
|
|
- ];
|
|
|
+ const results = SOLVERS.map((s) => ({
|
|
|
+ name: s.name,
|
|
|
+ ...s.fn(target.word, allWords, MAX_ATTEMPTS),
|
|
|
+ }));
|
|
|
|
|
|
const passResults = results.filter((r) => r.attempts <= MAX_ATTEMPTS);
|
|
|
if (passResults.length === 0) {
|
|
|
- console.log(` REMOVED: ${target.word} (unsolvable)`);
|
|
|
- failed++;
|
|
|
- continue;
|
|
|
+ console.log(` UNSOLVABLE: ${target.word}`);
|
|
|
+ unsolvable++;
|
|
|
+ } else {
|
|
|
+ ok++;
|
|
|
}
|
|
|
-
|
|
|
- const avg = passResults.reduce((s, r) => s + r.attempts, 0) / passResults.length;
|
|
|
- const difficulty = Math.round(avg * 100) / 100;
|
|
|
- const replays: SolverReplay[] = results
|
|
|
- .filter((r) => r.attempts <= MAX_ATTEMPTS)
|
|
|
- .map((r) => ({ solver: r.name, steps: r.steps }));
|
|
|
-
|
|
|
- newTargets.push({ ...target, difficulty, replays });
|
|
|
- solved++;
|
|
|
- if (solved % 10 === 0) console.log(` ${solved}/${bank.targets.length}...`);
|
|
|
+ if ((ok + unsolvable) % 10 === 0) console.log(` ${ok + unsolvable}/${bank.targets.length}...`);
|
|
|
}
|
|
|
|
|
|
- const newBank: WordBank = { guessable: bank.guessable, targets: newTargets };
|
|
|
- writeFileSync(bankPath, JSON.stringify(newBank, null, 2) + '\n', 'utf-8');
|
|
|
- console.log(`Done! ${solved} solved, ${failed} removed.`);
|
|
|
+ console.log(`Done! ${ok} solvable, ${unsolvable} unsolvable.`);
|
|
|
}
|
|
|
|
|
|
const DATA_DIR = resolve(__dirname, '../../data');
|
|
|
-solveBank(resolve(DATA_DIR, 'word-bank.json'));
|
|
|
-solveBank(resolve(DATA_DIR, 'word-bank-ru.json'));
|
|
|
-console.log('\nAll banks updated.');
|
|
|
+validateBank(resolve(DATA_DIR, 'word-bank.json'));
|
|
|
+validateBank(resolve(DATA_DIR, 'word-bank-ru.json'));
|
|
|
+console.log('\nAll banks validated.');
|