---
title: 'Numbers Game'
url: 'https://am4info.com/afterburner/numberion'
markdown: 'https://am4info.com/afterburner/numberion.md'
date: '2026-10-11'
description: "#ng-wrap{--bg:#f4f1ea;--card:#fff;--ink:#1d2433;--mut:#6b7385;--acc:#1f5eff;--tile:#e8ecf5;--good:#12805c;--bad:#c0392b;--line:#d9dce5;max-width:560px;margin:0 auto;font-family:system-ui,-apple-system,\"Segoe UI\",Roboto,sans-serif;box-sizing:border-box} @media (prefers-color-scheme:dark){#ng-wrap{--card:#1b2030;--ink:#eef0f6;--mut:#99a1b5;--acc:#5b8cff;--tile:#2a3148;--good:#3ed598;--bad:#ff7b6b;--line:#333b52}} #ng-wrap *{box-sizing:border-box} #ng-root{background:var(--card);color:var(--ink);border:1px solid var(--line);border-radius:16px;padding:20px;display:flex;flex-direction:column;gap:14px;line-height:1.3} #ng-root .bar{display:flex;gap:8px;align-items:center;justify-content:space-between;flex-wrap:wrap} #ng-root .seg{display:flex;gap:4px} #ng-root button{font:inherit;cursor:pointer;border:1px solid var(--line);background:var(--tile);color:var(--ink);border-radius:10px;padding:10px 14px;font-weight:600;margin:0;text-transform:none;letter-spacing:normal;box-shadow:none} #ng-root button:disabled{opacity:.35;cursor:not-allowed} #ng-root .seg button.on{background:var(--acc);color:#fff;border-color:var(--acc)} #ng-root #ng-start{background:var(--acc);color:#fff;border-color:var(--acc)} #ng-root #ng-timer{font-size:1.4rem;font-variant-numeric:tabular-nums;font-weight:700} #ng-root #ng-timer.low{color:var(--bad)} #ng-root #ng-target{font-size:3.4rem;font-weight:800;text-align:center;letter-spacing:2px;padding:8px;border-radius:12px;background:var(--tile)} #ng-root .row{display:flex;gap:8px;justify-content:center;flex-wrap:wrap} #ng-root .tile{min-width:56px;font-size:1.4rem;padding:14px 8px;flex:1 1 0;max-width:80px} #ng-root .op{font-size:1.4rem;flex:1 1 0;padding:12px 0} #ng-root #ng-eq{flex:2 1 0;background:var(--good);color:#fff;border-color:var(--good);font-size:1.8rem} #ng-root #ng-display{min-height:64px;border:2px solid var(--line);border-radius:12px;padding:12px;font-size:1.5rem;font-variant-numeric:tabular-nums;word-break:break-word;display:flex;align-items:center} #ng-root #ng-display .ph{color:var(--mut);font-size:1rem} #ng-root #ng-msg{min-height:3.2em;text-align:center;font-size:1.05rem;line-height:1.4} #ng-root #ng-msg.good{color:var(--good)} #ng-root #ng-msg.bad{color:var(--bad)} #ng-root .small{font-size:.95rem;flex:1} #ng-wrap .ng-note{margin:12px 4px 0;text-align:center;font-size:.9rem;opacity:.7} 60s120s180s 60 Start --- + − × ÷ ( ) = Your calculation appears here Clear last Reset Select desired time to solve the puzzle, then press \"Start\".Each number can be used once.Divisions must come out as whole numbers.Negative intermediate results are not allowed. (function () { const R = document.getElementById('ng-root'); const $ = s => R.querySelector(s); const $$ = s => R.querySelectorAll(s); const rnd = (a, b) => Math.floor(Math.random() * (b - a + 1)) + a; const pick = a => a[rnd(0, a.length - 1)]; let S = { target: 0, nums: [], tokens: [], running: false, dur: 60, end: 0, timer: null }; // ---------- Solver (exact search, closest if no exact) ---------- function solve(nums, target) { let best = { v: null, e: '', d: Infinity }; const check = it => { const d = Math.abs(it.v - target); if (d < best.d) best = { v: it.v, e: it.e, d }; }; function depthOK(e) { let d = 0; for (let i = 0; i < e.length - 1; i++) { if (e[i] === '(') d++; else if (e[i] === ')') d--; if (d === 0) return false; } return true; } const strip = e => (e[0] === '(' && e[e.length - 1] === ')' && depthOK(e)) ? e.slice(1, -1) : e; function rec(items) { if (best.d === 0) return; for (let i = 0; i < items.length; i++) for (let j = i + 1; j < items.length; j++) { const a = items[i], b = items[j]; const rest = items.filter((_, k) => k !== i && k !== j); const hi = a.v >= b.v ? a : b, lo = hi === a ? b : a; const cands = [{ v: a.v + b.v, e: `(${a.e} + ${b.e})` }]; if (hi.v > lo.v) cands.push({ v: hi.v - lo.v, e: `(${hi.e} − ${lo.e})` }); if (a.v !== 1 && b.v !== 1) cands.push({ v: a.v * b.v, e: `(${a.e} × ${b.e})` }); if (lo.v !== 1 && hi.v % lo.v === 0) cands.push({ v: hi.v / lo.v, e: `(${hi.e} ÷ ${lo.e})` }); for (const c of cands) { check(c); if (best.d === 0) { best.e = c.e; return; } rec([...rest, c]); if (best.d === 0) return; } } } const items = nums.map(n => ({ v: n, e: String(n) })); items.forEach(check); rec(items); return { v: best.v, e: strip(best.e), exact: best.d === 0 }; } // ---------- Evaluator (standard precedence, whole numbers only) ---------- function evaluate(tokens) { let p = 0; const peek = () => tokens[p] && tokens[p].s; function factor() { const t = tokens[p++]; if (t.s === '(') { const v = expr(); p++; return v; } return t.v; } function term() { let v = factor(); while (peek() === '*' || peek() === '/') { const o = tokens[p++].s, r = factor(); if (o === '*') v *= r; else { if (r === 0 || v % r !== 0) throw new Error('Division must give a whole number.'); v /= r; } } return v; } function expr() { let v = term(); while (peek() === '+' || peek() === '-') { const o = tokens[p++].s, r = term(); v = o === '+' ? v + r : v - r; if (v < 0) throw new Error('Negative intermediate results are not allowed.'); } return v; } return expr(); } // ---------- UI ---------- const sym = { '*': '×', '/': '÷', '-': '−' }; function msg(html, cls) { const m = $('#ng-msg'); m.innerHTML = html; m.className = cls || ''; } const last = () => S.tokens[S.tokens.length - 1]; const open = () => S.tokens.reduce((n, t) => n + (t.s === '(' ? 1 : t.s === ')' ? -1 : 0), 0); const endsValue = () => { const l = last(); return l && (l.n || l.s === ')'); }; function refresh() { $('#ng-display').innerHTML = S.tokens.length ? S.tokens.map(t => sym[t.s] || t.s).join(' ') : 'Your calculation appears here'; const on = S.running, v = endsValue(); $$('.tile').forEach((b, i) => b.disabled = !on || S.nums[i].used || v || (last() && last().s === ')')); $$('[data-o]').forEach(b => { const o = b.dataset.o; if (o === '(') b.disabled = !on || v; else if (o === ')') b.disabled = !on || !v || open() `${n.v}`).join(''); $$('.tile').forEach(b => b.onclick = () => { const i = +b.dataset.i; S.nums[i].used = true; add({ s: String(S.nums[i].v), n: true, v: S.nums[i].v, i }); }); } function startGame() { clearInterval(S.timer); S.target = rnd(100, 999); S.nums = [...Array(4)].map(() => rnd(1, 9)).concat(pick([10, 15, 20, 25]), pick([40, 50, 75])).map(v => ({ v, used: false })); S.tokens = []; S.running = true; $('#ng-target').textContent = S.target; buildTiles(); $$('#ng-timeSel button').forEach(b => b.disabled = true); $('#ng-start').disabled = true; msg('Go! Reach the target or get as close as you can.'); S.end = Date.now() + S.dur * 1000; tick(); S.timer = setInterval(tick, 200); refresh(); } function tick() { const left = Math.max(0, Math.ceil((S.end - Date.now()) / 1000)); $('#ng-timer').textContent = left; $('#ng-timer').className = left n.v), S.target); msg(`⏰ Time's up – you lost.${s.exact ? 'Solution' : `No exact solution; closest is ${s.v} (off by ${Math.abs(S.target - s.v)})`}:${s.e} = ${s.v}`, 'bad'); } function equals() { let r; try { r = evaluate(S.tokens); } catch (e) { msg('⚠️ ' + e.message, 'bad'); return; } const d = Math.abs(r - S.target); if (d === 0) finish(true, `🎉 Correct! ${r} is exactly the target.`); else msg(`Result: ${r} – ${d} ${r > S.target ? 'above' : 'below'} the target (difference ${d}). Reset and try again!`, 'bad'); } $('#ng-start').onclick = startGame; $('#ng-eq').onclick = equals; $$('[data-o]').forEach(b => b.onclick = () => add({ s: b.dataset.o })); $('#ng-clear').onclick = () => { const t = S.tokens.pop(); if (t && t.n) S.nums[t.i].used = false; refresh(); }; $('#ng-reset').onclick = () => { S.tokens = []; S.nums.forEach(n => n.used = false); refresh(); }; $$('#ng-timeSel button').forEach(b => b.onclick = () => { S.dur = +b.dataset.t; $$('#ng-timeSel button').forEach(x => x.classList.toggle('on', x === b)); $('#ng-timer').textContent = S.dur; }); refresh(); })();"
---

# Numbers Game

 60  

---

Your calculation appears here

Select desired time to solve the puzzle, then press "Start".
Each number can be used once.
Divisions must come out as whole numbers.
Negative intermediate results are not allowed.

---

## Navigation

- Parent: [Afterburner](https://am4info.com/afterburner.md)
- Next: [Sign Code Breaker](https://am4info.com/afterburner/sign-code-breaker.md)
