interface Template { pattern: string weight: number } const SHIFT_LOW = [4, 5, 6, 7] const SHIFT_MID = [8, 9, 10, 11, 12] const SHIFT_HIGH = [13, 14, 15, 16] const SHIFTS = [...SHIFT_LOW, ...SHIFT_MID, ...SHIFT_HIGH] const MASKS = [1, 2, 3, 4, 5, 7, 8, 11, 13, 15, 16, 31, 32, 42, 63, 64, 127, 128, 255] const MULTIPLIERS = [2, 3, 5, 7, 11, 13] const MELODIC_MODS = [3, 5, 7, 9, 12, 16, 24, 32, 48, 64, 96, 128, 192, 255] const DIV_FACTORS = [2, 3, 4, 5, 6, 8, 10, 12, 16, 24, 32] const SMALL_NUMS = [1, 2, 3, 4, 5, 6, 7, 8] const TEMPLATES: Template[] = [ { pattern: "t*(N&t>>S)", weight: 8 }, { pattern: "t*((t>>S)&N)", weight: 8 }, { pattern: "t*(N|(t>>S))", weight: 5 }, { pattern: "(t*X&t>>S1)|(t*X2&t>>S2)", weight: 10 }, { pattern: "t*(t>>S1|t>>S2)", weight: 10 }, { pattern: "t*(t>>S1&t>>S2)", weight: 8 }, { pattern: "(t>>S1)|(t>>S2)", weight: 7 }, { pattern: "(t>>S1)&(t>>S2)", weight: 7 }, { pattern: "t&t>>S", weight: 6 }, { pattern: "(t&t>>S1)*(t>>S2|t>>S3)", weight: 8 }, { pattern: "(t>>S)&N", weight: 5 }, { pattern: "t*(t>>S)", weight: 4 }, { pattern: "(t*X)&(t>>S)", weight: 6 }, { pattern: "t^(t>>S)", weight: 5 }, { pattern: "(t>>S1)^(t>>S2)", weight: 6 }, { pattern: "t*(N&(t>>S1|t>>S2))", weight: 7 }, { pattern: "((t>>S1)&N)*(t>>S2)", weight: 6 }, { pattern: "t*((t>>S1)|(t>>S2))&N", weight: 7 }, { pattern: "(t&(t>>S1))^(t>>S2)", weight: 5 }, { pattern: "t/(t%(t>>S|t>>S2))", weight: 3 }, { pattern: "t<<((t>>S1|t>>S2)^(t>>S3))", weight: 4 }, { pattern: "(t>>S)%(N)", weight: 3 }, { pattern: "t%(N)+(t>>S)", weight: 4 }, { pattern: "(t*X&t>>S1)^(t>>S2)", weight: 5 }, { pattern: "((t>>S1)|(t>>S2))&((t>>S3)|(t>>S4))", weight: 6 }, { pattern: "t&t>>S", weight: 7 }, { pattern: "(t>>S1&t>>S2)*t>>S3", weight: 6 }, { pattern: "(t&(t>>S1))&(t>>S2)", weight: 6 }, { pattern: "((t>>S1)&t)*(t>>S2&t)", weight: 7 }, { pattern: "t&(t>>S1)&(t>>S2)", weight: 6 }, { pattern: "t%(M1)+(t>>S1)%(M2)", weight: 7 }, { pattern: "(t%M)*(t>>S)", weight: 6 }, { pattern: "t*((t>>S1)%(M))", weight: 6 }, { pattern: "(t*(t>>S))%M", weight: 5 }, { pattern: "(t%M1)^(t>>S)%(M2)", weight: 5 }, { pattern: "((t>>S)%M1)*(t%M2)", weight: 6 }, { pattern: "t/(t%(t>>S))", weight: 4 }, { pattern: "t/(D+(t>>S))", weight: 5 }, { pattern: "t/(D+(t>>S1|t>>S2))", weight: 5 }, { pattern: "(t>>S)/(D+(t&N))", weight: 4 }, { pattern: "t/(D*(t>>S))", weight: 4 }, { pattern: "t^(t>>S1)^(t>>S2)", weight: 6 }, { pattern: "((t>>S1)^(t>>S2))*(t>>S3)", weight: 7 }, { pattern: "(t^t>>S1)&(t^t>>S2)", weight: 6 }, { pattern: "t^(t>>S1)^(t>>S2)^(t>>S3)", weight: 5 }, { pattern: "(t^(t>>S1))*(t^(t>>S2))", weight: 6 }, { pattern: "((t*t)/(t^t>>S))&N", weight: 5 }, { pattern: "(t*(t>>S1))^(t*(t>>S2))", weight: 6 }, { pattern: "((t>>S1)*(t>>S2))&((t>>S3)|(t>>S4))", weight: 6 }, { pattern: "(t&(t>>S1))^((t>>S2)&(t>>S3))", weight: 5 } ] function randomElement(arr: T[]): T { return arr[Math.floor(Math.random() * arr.length)] } function fillTemplate(pattern: string): string { let formula = pattern const sMatches = formula.match(/S\d*/g) || [] const uniqueShifts = [...new Set(sMatches)] uniqueShifts.forEach(placeholder => { const shift = randomElement(SHIFTS) formula = formula.replace(new RegExp(placeholder, 'g'), shift.toString()) }) const nMatches = formula.match(/N\d*/g) || [] const uniqueMasks = [...new Set(nMatches)] uniqueMasks.forEach(placeholder => { const mask = randomElement(MASKS) formula = formula.replace(new RegExp(placeholder, 'g'), mask.toString()) }) const mMatches = formula.match(/M\d*/g) || [] const uniqueMods = [...new Set(mMatches)] uniqueMods.forEach(placeholder => { const mod = randomElement(MELODIC_MODS) formula = formula.replace(new RegExp(placeholder, 'g'), mod.toString()) }) const dMatches = formula.match(/D\d*/g) || [] const uniqueDivs = [...new Set(dMatches)] uniqueDivs.forEach(placeholder => { const div = randomElement(DIV_FACTORS) formula = formula.replace(new RegExp(placeholder, 'g'), div.toString()) }) const xMatches = formula.match(/X\d*/g) || [] const uniqueMults = [...new Set(xMatches)] uniqueMults.forEach(placeholder => { const mult = randomElement(MULTIPLIERS) formula = formula.replace(new RegExp(placeholder, 'g'), mult.toString()) }) return formula } function applyParenthesizationRandomization(formula: string): string { if (Math.random() < 0.2) { const operators = formula.match(/[\+\-\*\/\&\|\^]/g) if (operators && operators.length > 0) { const parts = formula.split(/([+\-*\/&|^])/) if (parts.length >= 3) { const idx = Math.floor(Math.random() * (parts.length - 2) / 2) * 2 parts[idx] = `(${parts[idx]})` } return parts.join('') } } return formula } function applyNegationRandomization(formula: string): string { const tMatches = [...formula.matchAll(/\bt\b/g)] if (tMatches.length === 0) return formula if (Math.random() < 0.1) { const idx = Math.floor(Math.random() * tMatches.length) const match = tMatches[idx] const before = formula.slice(0, match.index!) const after = formula.slice(match.index! + 1) return before + '(-t)' + after } if (Math.random() < 0.15) { const idx = Math.floor(Math.random() * tMatches.length) const match = tMatches[idx] const before = formula.slice(0, match.index!) const after = formula.slice(match.index! + 1) return before + '(~t)' + after } return formula } export function generateRandomFormula(complexity: number = 1): string { const complexityWeights = [ { simple: 0.6, medium: 0.3, complex: 0.1 }, { simple: 0.3, medium: 0.5, complex: 0.2 }, { simple: 0.1, medium: 0.3, complex: 0.6 } ] const weights = complexityWeights[complexity] || complexityWeights[1] const filteredTemplates = TEMPLATES.map(t => { const patternComplexity = (t.pattern.match(/[SNMDX]\d*/g) || []).length let weight = t.weight if (patternComplexity <= 2) { weight *= weights.simple } else if (patternComplexity <= 4) { weight *= weights.medium } else { weight *= weights.complex } return { ...t, weight } }) const totalWeight = filteredTemplates.reduce((sum, t) => sum + t.weight, 0) let random = Math.random() * totalWeight let selectedTemplate = filteredTemplates[0] for (const template of filteredTemplates) { random -= template.weight if (random <= 0) { selectedTemplate = template break } } let formula = fillTemplate(selectedTemplate.pattern) formula = applyParenthesizationRandomization(formula) formula = applyNegationRandomization(formula) const extraLayerChance = complexity === 0 ? 0.10 : complexity === 1 ? 0.20 : 0.35 if (Math.random() < extraLayerChance) { const op = randomElement(['&', '|', '^', '+', '-', '*']) const num = randomElement(SMALL_NUMS) formula = `(${formula})${op}${num}` } return formula } export function generateFormulaGrid(rows: number, cols: number, complexity: number = 1): string[][] { const grid: string[][] = [] for (let i = 0; i < rows; i++) { const row: string[] = [] for (let j = 0; j < cols; j++) { row.push(generateRandomFormula(complexity)) } grid.push(row) } return grid }