// 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'));