import { operators } from './globals' import { Operation, OperatorType } from './types' import { shuffle } from './utils' type HistoryType = { a: number; b: number; op: OperatorType }[] export function isOperationResultValid(op: Operation): boolean { return ( !!op.operator && !!op.left && !!op.right && Number.isInteger(operate(op.operator, op.left?.value, op.right?.value)) ) } export function isOperationInvalid(op: Operation): boolean { if (!isOperationReady(op)) return false return !isOperationResultValid(op) } export function isOperationReady(op: Operation): boolean { return !!op.operator && !!op.left && !!op.right } export function getEmptyOperation(): Operation { return { left: null, right: null, operator: null, result: null, } } export function operate( operator: OperatorType, valA: number, valB: number, ): number { switch (operator) { case '+': return valA + valB case '-': return valA - valB case '*': return valA * valB case '/': return valA / valB } } export function isSolvable(result: number, plaquettes: number[]): boolean { console.log('---') console.log('Solving ' + result) // Bigger numbers have more time to solve themselves const maxIterations = result * 100 function printHistory(history: HistoryType): void { for (const item of history) { if (item.a < item.b) [item.a, item.b] = [item.b, item.a] console.log( `${item.a} ${item.op} ${item.b} = ${operate(item.op, item.a, item.b)}`, ) } } function loopOperations(plaquettes: number[], history: HistoryType): void { for (let i = 0; i < plaquettes.length - 1; ++i) { for (let j = i + 1; j < plaquettes.length; ++j) { let a = plaquettes[i] let b = plaquettes[j] if (a < b) [a, b] = [b, a] const ops = shuffle([...operators]) for (const op of ops) { if (op === '/' && a % b !== 0) continue recursOperation(op, a, b, plaquettes, history) } } } } function recursOperation( operator: OperatorType, valA: number, valB: number, oldPlaquettes: number[], oldHistory: HistoryType, ): void { if (found) return if (++numberOfIterations > maxIterations) return const plaquettes = [...oldPlaquettes] const history = [...oldHistory] // remove values from plaquettes const idxA = plaquettes.findIndex(p => p === valA) plaquettes.splice(idxA, 1) const idxB = plaquettes.findIndex(p => p === valB) plaquettes.splice(idxB, 1) // calculate result and push it into plaquettes const r = operate(operator, valA, valB) plaquettes.push(r) // Save step history.push({ a: valA, b: valB, op: operator }) // Found the solution if (plaquettes.indexOf(result) > -1) { histories.push(history) if (!found) { found = true console.log(`1e solution trouvée en ${Date.now() - start}ms`) } return } // Exhausted all plaquettes else if (plaquettes.length === 1) { return } loopOperations(plaquettes, history) } const histories: HistoryType[] = [] // Start calculations const start = Date.now() let found = false let numberOfIterations = 0 loopOperations(plaquettes, []) if (found) { console.log( `Réussite : ${Date.now() - start}ms et ${numberOfIterations} iterations`, ) } else { console.log( `Echec : ${Date.now() - start}ms et ${numberOfIterations} iterations`, ) } if (histories.length) { // printHistory(histories[0]) } return found // histories.sort((a, b) => a.length - b.length) // console.log( // `${histories.length} combinaisons trouvées en ${Date.now() - start}ms`, // ) // Entre 18 et 1410 // if (histories.length) { // console.log() // printHistory(histories[0]) // } }