Suppose someone hands you DECIDE, a perfect box: feed it any logical statement and it answers yes or no. Could it really exist? Let's test the dream by trying to use it — and watch it collapse.
<p class="hint">Suppose <b>DECIDE</b> exists: a box that reads any program and says whether it <b>HALTS</b> or <b>LOOPS</b> forever. Build the trap program <b>SPITE</b> with it, then run DECIDE on SPITE itself and watch the logic break.</p>
<div class="rack">
<div class="card box">
<div class="title">DECIDE(P)</div>
<div class="sub">our assumed truth-machine</div>
<code>if P halts → return HALTS<br>else → return LOOPS</code>
</div>
<div class="card spite">
<div class="title">SPITE()</div>
<div class="sub">deliberately contrary</div>
<code>if DECIDE(SPITE)==HALTS:<br> loop forever<br>else:<br> halt</code>
</div>
</div>
<div class="status" id="status">Click below to ask DECIDE about SPITE.</div>
<div class="btns">
<button id="run" type="button">Run DECIDE(SPITE)</button>
<button id="reset" type="button" class="ghost">Reset</button>
</div>
<div class="trace" id="trace"></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 .8rem; line-height: 1.45; }
.rack { display: flex; gap: .7rem; flex-wrap: wrap; margin: .4rem 0 .8rem; }
.card { flex: 1 1 200px; border-radius: 10px; padding: .7rem .8rem; border: 1px solid #cdd9e3; background: #f3f7fb; }
.card.spite { background: #fdeef0; border-color: #f3c9cf; }
.title { font: 700 15px ui-monospace, monospace; color: #1d3557; }
.card.spite .title { color: #c92f3c; }
.sub { font-size: .78rem; color: #667; margin: .1rem 0 .5rem; }
code { display: block; font: 600 12.5px ui-monospace, monospace; color: #2b3a4a; line-height: 1.5; }
.status { font-size: 1rem; font-weight: 600; margin: .5rem 0; min-height: 1.4em; }
.status.bad { color: #c92f3c; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .6rem; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
.trace { font: 500 13px ui-monospace, monospace; color: #333; line-height: 1.6; }
.trace .step { padding: .2rem 0; opacity: 0; transform: translateY(4px); transition: all .25s; }
.trace .step.show { opacity: 1; transform: none; }
.trace .clash { color: #c92f3c; font-weight: 700; }
.trace .arrow { color: #1d3557; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// The Entscheidungsproblem reduces to the halting problem. A universal decider
// DECIDE(P) would let us build SPITE: it asks DECIDE about ITSELF and then does
// the OPPOSITE. Whatever DECIDE answers, SPITE makes it wrong — so DECIDE cannot
// exist. This is Turing's 1936 diagonal contradiction, the core of the proof.
// We model both branches of DECIDE’s answer and show each leads to a clash.
function reason(answer){
// answer is what DECIDE supposedly says about SPITE: ’HALTS’ or ’LOOPS’.
// SPITE is built to do the opposite of DECIDE’s verdict.
const spiteActuallyDoes = (answer === 'HALTS') ? 'LOOPS' : 'HALTS';
const consistent = (spiteActuallyDoes === answer); // can never be true
return { answer, spiteActuallyDoes, consistent };
}
const steps = [
a => fmt('DECIDE(SPITE) is forced to answer something: say it returns <b>%answer%</b>.', { answer: a.answer }),
a => fmt('<span class="arrow">→</span> By DECIDE’s promise, that means SPITE truly %v%.', { v: a.answer === 'HALTS' ? 'halts' : 'loops forever' }),
a => fmt('<span class="arrow">→</span> But SPITE was written to do the OPPOSITE of DECIDE: so SPITE actually <b>%spiteActuallyDoes%</b>.', { spiteActuallyDoes: a.spiteActuallyDoes }),
a => fmt('<span class="clash">✗ Contradiction: DECIDE said %answer%, SPITE does %spiteActuallyDoes%.</span>', { answer: a.answer, spiteActuallyDoes: a.spiteActuallyDoes })
];
let toggle = 'HALTS';
function run(){
const a = reason(toggle);
toggle = (toggle === 'HALTS') ? 'LOOPS' : 'HALTS'; // try the other branch next time
const t = document.getElementById('trace'); t.innerHTML = '';
const s = document.getElementById('status');
s.textContent = 'Tracing the logic...'; s.className = 'status';
steps.forEach((fn,i) => {
const d = document.createElement('div'); d.className = 'step'; d.innerHTML = fn(a);
t.appendChild(d);
setTimeout(() => d.classList.add('show'), 250 * (i+1));
});
setTimeout(() => {
s.textContent = 'No consistent answer exists — so DECIDE cannot exist. (Try again; the other branch fails too.)';
s.className = 'status bad';
}, 250 * (steps.length+1));
console.assert(!a.consistent, 'DECIDE must be inconsistent for SPITE');
console.log('Branch', a.answer, '-> SPITE does', a.spiteActuallyDoes, '| consistent?', a.consistent);
}
function reset(){
document.getElementById('trace').innerHTML = '';
const s = document.getElementById('status');
s.textContent = 'Click below to ask DECIDE about SPITE.'; s.className = 'status';
toggle = 'HALTS';
}
document.getElementById('run').addEventListener('click', run);
document.getElementById('reset').addEventListener('click', reset);
<p class="hint">Suppose <b>DECIDE</b> exists: a box that reads any program and says whether it <b>HALTS</b> or <b>LOOPS</b> forever. Build the trap program <b>SPITE</b> with it, then run DECIDE on SPITE itself and watch the logic break.</p>
<div class="rack">
<div class="card box">
<div class="title">DECIDE(P)</div>
<div class="sub">our assumed truth-machine</div>
<code>if P halts → return HALTS<br>else → return LOOPS</code>
</div>
<div class="card spite">
<div class="title">SPITE()</div>
<div class="sub">deliberately contrary</div>
<code>if DECIDE(SPITE)==HALTS:<br> loop forever<br>else:<br> halt</code>
</div>
</div>
<div class="status" id="status">Click below to ask DECIDE about SPITE.</div>
<div class="btns">
<button id="run" type="button">Run DECIDE(SPITE)</button>
<button id="reset" type="button" class="ghost">Reset</button>
</div>
<div class="trace" id="trace"></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 .8rem; line-height: 1.45; }
.rack { display: flex; gap: .7rem; flex-wrap: wrap; margin: .4rem 0 .8rem; }
.card { flex: 1 1 200px; border-radius: 10px; padding: .7rem .8rem; border: 1px solid #cdd9e3; background: #f3f7fb; }
.card.spite { background: #fdeef0; border-color: #f3c9cf; }
.title { font: 700 15px ui-monospace, monospace; color: #1d3557; }
.card.spite .title { color: #c92f3c; }
.sub { font-size: .78rem; color: #667; margin: .1rem 0 .5rem; }
code { display: block; font: 600 12.5px ui-monospace, monospace; color: #2b3a4a; line-height: 1.5; }
.status { font-size: 1rem; font-weight: 600; margin: .5rem 0; min-height: 1.4em; }
.status.bad { color: #c92f3c; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .6rem; }
button { font: 600 14px system-ui, sans-serif; padding: .45rem .9rem; border: 1px solid #1d3557;
background: #1d3557; color: #fff; border-radius: 8px; cursor: pointer; }
button.ghost { background: #fff; color: #1d3557; }
.trace { font: 500 13px ui-monospace, monospace; color: #333; line-height: 1.6; }
.trace .step { padding: .2rem 0; opacity: 0; transform: translateY(4px); transition: all .25s; }
.trace .step.show { opacity: 1; transform: none; }
.trace .clash { color: #c92f3c; font-weight: 700; }
.trace .arrow { color: #1d3557; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// The Entscheidungsproblem reduces to the halting problem. A universal decider
// DECIDE(P) would let us build SPITE: it asks DECIDE about ITSELF and then does
// the OPPOSITE. Whatever DECIDE answers, SPITE makes it wrong — so DECIDE cannot
// exist. This is Turing's 1936 diagonal contradiction, the core of the proof.
// We model both branches of DECIDE’s answer and show each leads to a clash.
function reason(answer){
// answer is what DECIDE supposedly says about SPITE: ’HALTS’ or ’LOOPS’.
// SPITE is built to do the opposite of DECIDE’s verdict.
const spiteActuallyDoes = (answer === 'HALTS') ? 'LOOPS' : 'HALTS';
const consistent = (spiteActuallyDoes === answer); // can never be true
return { answer, spiteActuallyDoes, consistent };
}
const steps = [
a => fmt('DECIDE(SPITE) is forced to answer something: say it returns <b>%answer%</b>.', { answer: a.answer }),
a => fmt('<span class="arrow">→</span> By DECIDE’s promise, that means SPITE truly %v%.', { v: a.answer === 'HALTS' ? 'halts' : 'loops forever' }),
a => fmt('<span class="arrow">→</span> But SPITE was written to do the OPPOSITE of DECIDE: so SPITE actually <b>%spiteActuallyDoes%</b>.', { spiteActuallyDoes: a.spiteActuallyDoes }),
a => fmt('<span class="clash">✗ Contradiction: DECIDE said %answer%, SPITE does %spiteActuallyDoes%.</span>', { answer: a.answer, spiteActuallyDoes: a.spiteActuallyDoes })
];
let toggle = 'HALTS';
function run(){
const a = reason(toggle);
toggle = (toggle === 'HALTS') ? 'LOOPS' : 'HALTS'; // try the other branch next time
const t = document.getElementById('trace'); t.innerHTML = '';
const s = document.getElementById('status');
s.textContent = 'Tracing the logic...'; s.className = 'status';
steps.forEach((fn,i) => {
const d = document.createElement('div'); d.className = 'step'; d.innerHTML = fn(a);
t.appendChild(d);
setTimeout(() => d.classList.add('show'), 250 * (i+1));
});
setTimeout(() => {
s.textContent = 'No consistent answer exists — so DECIDE cannot exist. (Try again; the other branch fails too.)';
s.className = 'status bad';
}, 250 * (steps.length+1));
console.assert(!a.consistent, 'DECIDE must be inconsistent for SPITE');
console.log('Branch', a.answer, '-> SPITE does', a.spiteActuallyDoes, '| consistent?', a.consistent);
}
function reset(){
document.getElementById('trace').innerHTML = '';
const s = document.getElementById('status');
s.textContent = 'Click below to ask DECIDE about SPITE.'; s.className = 'status';
toggle = 'HALTS';
}
document.getElementById('run').addEventListener('click', run);
document.getElementById('reset').addEventListener('click', reset);
The demo wires the dream to the halting problem: "will program P stop, or run forever?" Turing showed that question is undecidable. But if DECIDE existed, we could phrase "P halts on input X" as a logical statement and just ask it. That would solve the halting problem — which is impossible. So DECIDE cannot exist. The same loop that breaks the box is the heart of Turing's 1936 proof.
Comments
Loading comments...