Below is a toy "machine" that must finish each input within a step budget that grows with the input size n. You pick the budget's growth rate — linear (n), quadratic (n2) or cubic (n3) — and the machine runs a task that genuinely needs about n2 · log n steps.
<p class="hint">The machine runs a real task on each input that costs about
<b>n²·log₂n</b> steps. Pick how fast the <b>step budget</b> may grow, then run.
An input is <b>solved</b> if it finishes inside the budget; otherwise it
<b>times out</b>. Raise the budget and watch timed-out inputs become solvable.</p>
<div class="controls">
<label>Budget growth:
<select id="rate">
<option value="lin">linear (8·n)</option>
<option value="quad">quadratic (8·n²)</option>
<option value="cube" selected>cubic (8·n³)</option>
</select>
</label>
<button id="run" type="button">Run the machine</button>
</div>
<table class="grid" id="grid"></table>
<div class="status" id="status">Choose a budget and press Run.</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.5; }
.controls { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin-bottom: .6rem; }
label { font-size: .9rem; font-weight: 600; display: flex; gap: .4rem; align-items: center; }
select { font: 600 14px system-ui, sans-serif; padding: .35rem .5rem; border-radius: 8px; border: 1px solid #adb1b8; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
table.grid { border-collapse: collapse; width: 100%; font-size: .9rem; margin: .3rem 0; }
.grid th, .grid td { border: 1px solid #cdd9e3; padding: .4rem .5rem; text-align: right; }
.grid th { background: #e8eef3; color: #1d3557; }
.grid td.lbl { text-align: left; font-weight: 600; }
tr.ok td { background: #e7f6ec; }
tr.bad td { background: #fdecec; }
.tag { font-weight: 700; }
.tag.ok { color: #0a7d33; }
.tag.bad { color: #c92f3c; }
.status { font-size: 1rem; font-weight: 600; margin: .5rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// The time hierarchy theorem (Hartmanis & Stearns, 1965): a problem can need
// strictly more time than a smaller budget allows. Here a fixed task costs about
// n^2 * log2(n) "steps". We measure the REAL step count, then compare it to a
// budget that grows linearly, quadratically or cubically. For large n the
// task overruns a linear/quadratic budget but always fits a cubic one — so
// raising the resource strictly enlarges the set of solvable inputs.
const SIZES = [2, 4, 6, 8, 12, 16];
const C = 8; // budget constant, same across rates for a fair comparison
// Run the actual task and count steps performed. Cost ~ n^2 * log2(n).
function runTask(n){
let steps = 0, acc = 0;
const passes = Math.max(1, Math.ceil(Math.log2(n))); // ~log2(n) passes
for(let p = 0; p < passes; p++)
for(let i = 0; i < n; i++)
for(let j = 0; j < n; j++){ steps++; acc = (acc + i*j + p) % 1000003; }
return { steps, acc };
}
function budget(rate, n){
if(rate === 'lin') return C * n;
if(rate === 'quad') return C * n * n;
return C * n * n * n; // cube
}
function run(){
const rate = document.getElementById('rate').value;
const rows = [];
let solved = 0;
for(const n of SIZES){
const { steps } = runTask(n);
const b = budget(rate, n);
const ok = steps <= b;
if(ok) solved++;
rows.push({ n, steps, b, ok });
}
const grid = document.getElementById('grid');
let html = '<tr><th class="lbl">input size n</th><th>steps needed (~n²·log n)</th><th>budget</th><th>result</th></tr>';
for(const r of rows){
const cls = r.ok ? 'ok' : 'bad';
const tag = r.ok ? '<span class="tag ok">solved</span>' : '<span class="tag bad">timed out</span>';
html += `<tr class="${cls}"><td class="lbl">n = ${r.n}</td><td>${r.steps.toLocaleString()}</td><td>${r.b.toLocaleString()}</td><td>${tag}</td></tr>`;
}
grid.innerHTML = html;
const s = document.getElementById('status');
s.className = 'status ok';
s.textContent = fmt('Budget = %rate%: %solved% of %length% inputs solved within budget.', { rate: rate, solved: solved, length: SIZES.length });
console.log('rate', rate, 'solved', solved, 'of', SIZES.length, rows);
}
document.getElementById('run').addEventListener('click', run);
run();
<p class="hint">The machine runs a real task on each input that costs about
<b>n²·log₂n</b> steps. Pick how fast the <b>step budget</b> may grow, then run.
An input is <b>solved</b> if it finishes inside the budget; otherwise it
<b>times out</b>. Raise the budget and watch timed-out inputs become solvable.</p>
<div class="controls">
<label>Budget growth:
<select id="rate">
<option value="lin">linear (8·n)</option>
<option value="quad">quadratic (8·n²)</option>
<option value="cube" selected>cubic (8·n³)</option>
</select>
</label>
<button id="run" type="button">Run the machine</button>
</div>
<table class="grid" id="grid"></table>
<div class="status" id="status">Choose a budget and press Run.</div>
* { box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #222; margin: 0; }
.hint { font-size: .9rem; color: #444; margin: 0 0 .7rem; line-height: 1.5; }
.controls { display: flex; gap: .6rem; align-items: center; flex-wrap: wrap; margin-bottom: .6rem; }
label { font-size: .9rem; font-weight: 600; display: flex; gap: .4rem; align-items: center; }
select { font: 600 14px system-ui, sans-serif; padding: .35rem .5rem; border-radius: 8px; border: 1px solid #adb1b8; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
table.grid { border-collapse: collapse; width: 100%; font-size: .9rem; margin: .3rem 0; }
.grid th, .grid td { border: 1px solid #cdd9e3; padding: .4rem .5rem; text-align: right; }
.grid th { background: #e8eef3; color: #1d3557; }
.grid td.lbl { text-align: left; font-weight: 600; }
tr.ok td { background: #e7f6ec; }
tr.bad td { background: #fdecec; }
.tag { font-weight: 700; }
.tag.ok { color: #0a7d33; }
.tag.bad { color: #c92f3c; }
.status { font-size: 1rem; font-weight: 600; margin: .5rem 0; min-height: 1.4em; }
.status.ok { color: #0a7d33; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// The time hierarchy theorem (Hartmanis & Stearns, 1965): a problem can need
// strictly more time than a smaller budget allows. Here a fixed task costs about
// n^2 * log2(n) "steps". We measure the REAL step count, then compare it to a
// budget that grows linearly, quadratically or cubically. For large n the
// task overruns a linear/quadratic budget but always fits a cubic one — so
// raising the resource strictly enlarges the set of solvable inputs.
const SIZES = [2, 4, 6, 8, 12, 16];
const C = 8; // budget constant, same across rates for a fair comparison
// Run the actual task and count steps performed. Cost ~ n^2 * log2(n).
function runTask(n){
let steps = 0, acc = 0;
const passes = Math.max(1, Math.ceil(Math.log2(n))); // ~log2(n) passes
for(let p = 0; p < passes; p++)
for(let i = 0; i < n; i++)
for(let j = 0; j < n; j++){ steps++; acc = (acc + i*j + p) % 1000003; }
return { steps, acc };
}
function budget(rate, n){
if(rate === 'lin') return C * n;
if(rate === 'quad') return C * n * n;
return C * n * n * n; // cube
}
function run(){
const rate = document.getElementById('rate').value;
const rows = [];
let solved = 0;
for(const n of SIZES){
const { steps } = runTask(n);
const b = budget(rate, n);
const ok = steps <= b;
if(ok) solved++;
rows.push({ n, steps, b, ok });
}
const grid = document.getElementById('grid');
let html = '<tr><th class="lbl">input size n</th><th>steps needed (~n²·log n)</th><th>budget</th><th>result</th></tr>';
for(const r of rows){
const cls = r.ok ? 'ok' : 'bad';
const tag = r.ok ? '<span class="tag ok">solved</span>' : '<span class="tag bad">timed out</span>';
html += `<tr class="${cls}"><td class="lbl">n = ${r.n}</td><td>${r.steps.toLocaleString()}</td><td>${r.b.toLocaleString()}</td><td>${tag}</td></tr>`;
}
grid.innerHTML = html;
const s = document.getElementById('status');
s.className = 'status ok';
s.textContent = fmt('Budget = %rate%: %solved% of %length% inputs solved within budget.', { rate: rate, solved: solved, length: SIZES.length });
console.log('rate', rate, 'solved', solved, 'of', SIZES.length, rows);
}
document.getElementById('run').addEventListener('click', run);
run();
Watch the asymmetry. With a linear budget many inputs time out — the machine literally cannot finish. Bump the budget up to cubic and those very same inputs now complete with room to spare. The set of "solvable within budget" inputs grew strictly larger just because the resource did. That little jump is the hierarchy theorem in miniature. See it pushed to the extreme in the exponential time hypothesis.
Comments
Loading comments...