Files
quartiles/scripts/analyze-word-variety.mjs

45 lines
1.9 KiB
JavaScript

// Reports how often short (1-2 tile) words repeat across generated puzzles.
// Usage: node scripts/analyze-word-variety.mjs [days=365]
import { generateDailyPuzzle } from '../src/engine/generator.js';
const days = Number(process.argv[2]) || 365;
const counts = new Map();
const targetCounts = new Map();
let totalSmall = 0;
const start = new Date(2026, 0, 1);
for (let i = 0; i < days; i++) {
const d = new Date(start);
d.setDate(d.getDate() + i);
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
const puzzle = generateDailyPuzzle(dateStr);
for (const q of puzzle.targetQuartiles) targetCounts.set(q, (targetCounts.get(q) || 0) + 1);
for (const w of puzzle.words) {
if (w.tileCount > 2) continue;
totalSmall++;
counts.set(w.word, (counts.get(w.word) || 0) + 1);
}
}
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]);
const top20 = sorted.slice(0, 20).reduce((s, [, c]) => s + c, 0);
console.log(`Puzzles: ${days}`);
const maxTarget = Math.max(...targetCounts.values());
console.log(`Target words: ${targetCounts.size} distinct, most repeated used ${maxTarget}x`);
console.log(`Short-word slots: ${totalSmall} (${(totalSmall / days).toFixed(1)}/puzzle)`);
console.log(`Distinct short words: ${counts.size}`);
console.log(`Top-20 words fill ${((top20 / totalSmall) * 100).toFixed(1)}% of short-word slots`);
const byLen = new Map();
for (const [w, c] of counts) {
const k = w.length <= 3 ? `${w.length} letters` : '4+ letters';
const e = byLen.get(k) || { slots: 0, distinct: 0 };
e.slots += c;
e.distinct++;
byLen.set(k, e);
}
for (const [k, e] of [...byLen].sort()) {
console.log(` ${k.padEnd(11)} ${(e.slots / days).toFixed(1)}/puzzle, ${e.distinct} distinct, avg repeat ${(e.slots / e.distinct).toFixed(1)}x`);
}
console.log('Most repeated:');
console.log(sorted.slice(0, 25).map(([w, c]) => ` ${w.padEnd(12)} ${c}`).join('\n'));