// ambiguous-gen.mjs — 答えが一意に決まらない数列・文字列を量産する。 // Reflective エンジンの5戦略を再利用し、「複数の戦略が同時に自己検証を通る」入力だけを採用する。 import { STRATEGIES, STRATEGY_ORDER } from '../reflective-ai/worker/src/engine.js'; function mulberry32(seed) { let a = seed >>> 0; return function () { a |= 0; a = (a + 0x6d2b79f5) | 0; let t = Math.imul(a ^ (a >>> 15), 1 | a); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; }; } // ある入力に対して、検証を通る(=verified)戦略とその答えを全部集める。 export function solutions(prompt) { const out = []; for (const name of STRATEGY_ORDER) { const r = STRATEGIES[name](prompt); if (r.verified && r.answer !== null && r.answer !== undefined) { out.push({ strategy: name, answer: r.answer, reason: r.reason }); } } return out; } // 複数の解が成立する = 曖昧な入力。 export function isAmbiguous(prompt) { return solutions(prompt).length >= 2; } // 整数列の候補を生成し、曖昧なものだけ返す。 export function generateAmbiguousNumbers(rng, count) { const found = []; const seen = new Set(); let guard = 0; while (found.length < count && guard < count * 200) { guard++; const n = 3 + Math.floor(rng() * 4); // 3..6 項 const start = 1 + Math.floor(rng() * 6); const kind = rng(); let seq; if (kind < 0.5) { const d = 1 + Math.floor(rng() * 5); seq = Array.from({ length: n }, (_, i) => start + d * i); } else { const r = 2 + Math.floor(rng() * 3); seq = Array.from({ length: n }, (_, i) => start * r ** i); } const key = JSON.stringify(seq); if (seen.has(key)) continue; const sols = solutions(seq); if (sols.length >= 2) { seen.add(key); found.push({ prompt: seq, solutions: sols, kind: 'number' }); } } return found; } // 周期文字列の候補から、曖昧なもの(例: 周期1と周期2が両立)を返す。 export function generateAmbiguousStrings(rng, count) { const found = []; const seen = new Set(); const alphabet = 'ab'; let guard = 0; while (found.length < count && guard < count * 200) { guard++; const len = 4 + Math.floor(rng() * 5); let s = ''; for (let i = 0; i < len; i++) s += alphabet[Math.floor(rng() * alphabet.length)]; if (seen.has(s)) continue; const sols = solutions(s); if (sols.length >= 2) { seen.add(s); found.push({ prompt: s, solutions: sols, kind: 'string' }); } } return found; } export function generate(seed, count) { const rng = mulberry32(seed); const seen = new Set(); const out = []; const nums = generateAmbiguousNumbers(rng, count * 2); const strs = generateAmbiguousStrings(rng, count * 2); for (const it of [...nums, ...strs]) { const k = JSON.stringify(it.prompt); if (seen.has(k)) continue; seen.add(k); out.push(it); if (out.length >= count) break; } return out; } // CLI: node ambiguous-gen.mjs [count] [seed] if (import.meta.url === `file://${process.argv[1]}`) { const count = Number(process.argv[2] || 10); const seed = Number(process.argv[3] || 42); const items = generate(seed, count); console.log(JSON.stringify(items, null, 2)); }