<p class="hint">Pick a remainder for each base. The Chinese Remainder Theorem guarantees there is <b>exactly one</b> number from 0 to 104 that leaves all three remainders at once. Press <b>Assemble</b> to rebuild it.</p>
<div class="picks">
<label>mod 3 <select id="r3"><option>0</option><option selected>2</option><option>1</option></select></label>
<label>mod 5 <select id="r5"><option>0</option><option>1</option><option>2</option><option selected>3</option><option>4</option></select></label>
<label>mod 7 <select id="r7"><option>0</option><option>1</option><option selected>2</option><option>3</option><option>4</option><option>5</option><option>6</option></select></label>
</div>
<div class="btns">
<button id="go" type="button">Assemble</button>
<button id="verify" type="button" class="ghost">Verify by scanning</button>
</div>
<div class="answer" id="answer">x ≡ 2 (mod 3), 3 (mod 5), 2 (mod 7)</div>
<div class="work" id="work"></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; }
.picks { display: flex; gap: 1rem; flex-wrap: wrap; margin: .2rem 0 .8rem; }
label { font: 600 14px system-ui, sans-serif; color: #1d3557; display: flex; align-items: center; gap: .4rem; }
select { font: 600 14px system-ui, sans-serif; padding: .3rem .4rem; border: 1px solid #cdd9e3; border-radius: 6px; background: #fff; }
.btns { display: flex; gap: .5rem; flex-wrap: wrap; margin-bottom: .8rem; }
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; }
.answer { font: 700 22px ui-monospace, monospace; color: #0a7d33; min-height: 1.4em; margin: .3rem 0; }
.work { font: 500 13px ui-monospace, monospace; color: #41506a; line-height: 1.7; white-space: pre-wrap;
background: #f2f6f9; border: 1px solid #dde6ee; border-radius: 8px; padding: .6rem .8rem; }
const fmt = (s, v) => s.replace(/%(\w+)%/g, (_, k) => String(v[k] ?? ''));
// Chinese Remainder Theorem for the pairwise-coprime bases 3, 5, 7 (product M = 105).
// For each base m_i we precompute a "basis number" e_i with:
// e_i ≡ 1 (mod m_i) and e_i ≡ 0 (mod every other base).
// Then the unique solution is x = (r3*e3 + r5*e5 + r7*e7) mod 105.
const MS = [3, 5, 7], M = 105;
// Extended Euclid -> modular inverse of a mod m.
function inv(a, m){
let [old_r, r] = [((a % m) + m) % m, m];
let [old_s, s] = [1, 0];
while (r !== 0){ const q = Math.floor(old_r / r);
[old_r, r] = [r, old_r - q * r]; [old_s, s] = [s, old_s - q * s]; }
return ((old_s % m) + m) % m;
}
// Basis number for base index i: Mi = M/mi, then ei = Mi * inv(Mi mod mi, mi).
function basis(i){ const mi = MS[i], Mi = M / mi; return (Mi * inv(Mi % mi, mi)) % M; }
const E = MS.map((_, i) => basis(i));
function readPicks(){
return [ +document.getElementById('r3').value,
+document.getElementById('r5').value,
+document.getElementById('r7').value ];
}
function assemble(){
const r = readPicks();
let x = 0; const parts = [];
for (let i = 0; i < 3; i++){ x = (x + r[i] * E[i]) % M;
parts.push(r[i] + '·' + E[i]); }
document.getElementById('answer').textContent = 'x = ' + x;
document.getElementById('work').textContent =
fmt(`Basis numbers (each ≡1 at its base, ≡0 at the others):
e(mod3)=%v%, e(mod5)=%v2%, e(mod7)=%v3%
x = (%parts%) mod 105
x = %x% → %x% mod 3 = %v4%, %x% mod 5 = %v5%, %x% mod 7 = %v6%`, { v: E[0], v2: E[1], v3: E[2], parts: parts.join(' + '), x: x, v4: x % 3, v5: x % 5, v6: x % 7 });
console.log(`CRT solution:`, x, '| remainders', x % 3, x % 5, x % 7);
return x;
}
// Honest cross-check: scan 0..104 and confirm exactly one match (the theorem’s claim).
function verify(){
const r = readPicks(); const hits = [];
for (let n = 0; n < M; n++)
if (n % 3 === r[0] && n % 5 === r[1] && n % 7 === r[2]) hits.push(n);
document.getElementById('work').textContent =
fmt(`Scanning all numbers 0..104 for a match...
Numbers matching all three remainders: [%hits%]
Count = %length% (the theorem promises exactly 1).`, { hits: hits.join(', '), length: hits.length });
console.log(`brute-force matches:`, hits);
}
document.getElementById('go').addEventListener('click', assemble);
document.getElementById('verify').addEventListener('click', verify);
assemble();
Comments
Loading comments...