eyeling 1.16.3 → 1.16.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/package.json +2 -3
- package/arctifacts/README.md +0 -59
- package/arctifacts/ackermann.html +0 -678
- package/arctifacts/auroracare.html +0 -1297
- package/arctifacts/bike-trip.html +0 -752
- package/arctifacts/binomial-theorem.html +0 -631
- package/arctifacts/bmi.html +0 -511
- package/arctifacts/building-performance.html +0 -750
- package/arctifacts/clinical-care.html +0 -726
- package/arctifacts/collatz.html +0 -403
- package/arctifacts/complex.html +0 -321
- package/arctifacts/control-system.html +0 -482
- package/arctifacts/delfour.html +0 -849
- package/arctifacts/earthquake-epicenter.html +0 -982
- package/arctifacts/eco-route.html +0 -662
- package/arctifacts/euclid-infinitude.html +0 -564
- package/arctifacts/euler-identity.html +0 -667
- package/arctifacts/exoplanet-transit.html +0 -1000
- package/arctifacts/faltings-theorem.html +0 -1046
- package/arctifacts/fibonacci.html +0 -299
- package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
- package/arctifacts/godel-numbering.html +0 -743
- package/arctifacts/gps-bike.html +0 -759
- package/arctifacts/gps-clinical-bench.html +0 -792
- package/arctifacts/graph-french.html +0 -449
- package/arctifacts/grass-molecular.html +0 -592
- package/arctifacts/group-theory.html +0 -740
- package/arctifacts/health-info.html +0 -833
- package/arctifacts/kaprekar-constant.html +0 -576
- package/arctifacts/lee.html +0 -805
- package/arctifacts/linked-lists.html +0 -502
- package/arctifacts/lldm.html +0 -612
- package/arctifacts/matrix-multiplication.html +0 -502
- package/arctifacts/matrix.html +0 -651
- package/arctifacts/newton-raphson.html +0 -944
- package/arctifacts/peano-factorial.html +0 -456
- package/arctifacts/pi.html +0 -363
- package/arctifacts/polynomial.html +0 -646
- package/arctifacts/prime.html +0 -366
- package/arctifacts/pythagorean-theorem.html +0 -468
- package/arctifacts/rest-path.html +0 -469
- package/arctifacts/roots-of-unity.html +0 -363
- package/arctifacts/turing.html +0 -409
- package/arctifacts/wind-turbines.html +0 -726
|
@@ -1,631 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
-
<title>Sum of All Binomial Coefficients</title>
|
|
7
|
-
<style>
|
|
8
|
-
:root {
|
|
9
|
-
--bg: #f7f9fc;
|
|
10
|
-
--card: #ffffff;
|
|
11
|
-
--text: #0f172a;
|
|
12
|
-
--muted: #475569;
|
|
13
|
-
--accent: #2563eb;
|
|
14
|
-
--good: #16a34a;
|
|
15
|
-
--bad: #dc2626;
|
|
16
|
-
--border: #e2e8f0;
|
|
17
|
-
--chip: #eef2ff;
|
|
18
|
-
--code: #111827;
|
|
19
|
-
}
|
|
20
|
-
html,
|
|
21
|
-
body {
|
|
22
|
-
background: var(--bg);
|
|
23
|
-
color: var(--text);
|
|
24
|
-
font-family:
|
|
25
|
-
ui-sans-serif,
|
|
26
|
-
system-ui,
|
|
27
|
-
-apple-system,
|
|
28
|
-
Segoe UI,
|
|
29
|
-
Roboto,
|
|
30
|
-
Helvetica,
|
|
31
|
-
Arial,
|
|
32
|
-
'Apple Color Emoji',
|
|
33
|
-
'Segoe UI Emoji';
|
|
34
|
-
}
|
|
35
|
-
* {
|
|
36
|
-
box-sizing: border-box;
|
|
37
|
-
}
|
|
38
|
-
.container {
|
|
39
|
-
max-width: 960px;
|
|
40
|
-
margin: 24px auto;
|
|
41
|
-
padding: 0 16px;
|
|
42
|
-
}
|
|
43
|
-
header {
|
|
44
|
-
display: flex;
|
|
45
|
-
flex-direction: column;
|
|
46
|
-
gap: 8px;
|
|
47
|
-
margin-bottom: 16px;
|
|
48
|
-
}
|
|
49
|
-
h1 {
|
|
50
|
-
font-size: 1.8rem;
|
|
51
|
-
margin: 0;
|
|
52
|
-
letter-spacing: -0.02em;
|
|
53
|
-
}
|
|
54
|
-
.subtitle {
|
|
55
|
-
color: var(--muted);
|
|
56
|
-
}
|
|
57
|
-
.card {
|
|
58
|
-
background: var(--card);
|
|
59
|
-
border: 1px solid var(--border);
|
|
60
|
-
border-radius: 16px;
|
|
61
|
-
padding: 16px;
|
|
62
|
-
box-shadow: 0 6px 20px rgba(2, 6, 23, 0.05);
|
|
63
|
-
}
|
|
64
|
-
.stack {
|
|
65
|
-
display: flex;
|
|
66
|
-
flex-direction: column;
|
|
67
|
-
gap: 16px;
|
|
68
|
-
}
|
|
69
|
-
.pill {
|
|
70
|
-
display: inline-flex;
|
|
71
|
-
align-items: center;
|
|
72
|
-
gap: 8px;
|
|
73
|
-
padding: 4px 10px;
|
|
74
|
-
background: var(--chip);
|
|
75
|
-
color: #1e3a8a;
|
|
76
|
-
border-radius: 999px;
|
|
77
|
-
font-size: 12px;
|
|
78
|
-
font-weight: 600;
|
|
79
|
-
border: 1px solid #c7d2fe;
|
|
80
|
-
}
|
|
81
|
-
.row {
|
|
82
|
-
display: flex;
|
|
83
|
-
gap: 12px;
|
|
84
|
-
align-items: center;
|
|
85
|
-
}
|
|
86
|
-
input[type='number'] {
|
|
87
|
-
width: 160px;
|
|
88
|
-
padding: 10px 12px;
|
|
89
|
-
border-radius: 10px;
|
|
90
|
-
border: 1px solid var(--border);
|
|
91
|
-
background: #fbfdff;
|
|
92
|
-
}
|
|
93
|
-
button {
|
|
94
|
-
appearance: none;
|
|
95
|
-
border: none;
|
|
96
|
-
background: var(--accent);
|
|
97
|
-
color: white;
|
|
98
|
-
padding: 10px 14px;
|
|
99
|
-
border-radius: 12px;
|
|
100
|
-
font-weight: 700;
|
|
101
|
-
cursor: pointer;
|
|
102
|
-
box-shadow: 0 4px 14px rgba(37, 99, 235, 0.25);
|
|
103
|
-
}
|
|
104
|
-
button.secondary {
|
|
105
|
-
background: #0ea5e9;
|
|
106
|
-
}
|
|
107
|
-
button.ghost {
|
|
108
|
-
background: transparent;
|
|
109
|
-
color: var(--accent);
|
|
110
|
-
border: 1px solid var(--accent);
|
|
111
|
-
}
|
|
112
|
-
button:disabled {
|
|
113
|
-
opacity: 0.6;
|
|
114
|
-
cursor: not-allowed;
|
|
115
|
-
}
|
|
116
|
-
.grid {
|
|
117
|
-
display: grid;
|
|
118
|
-
grid-template-columns: 1fr;
|
|
119
|
-
gap: 16px;
|
|
120
|
-
}
|
|
121
|
-
.muted {
|
|
122
|
-
color: var(--muted);
|
|
123
|
-
}
|
|
124
|
-
.mono {
|
|
125
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
|
126
|
-
color: var(--code);
|
|
127
|
-
word-break: break-word;
|
|
128
|
-
overflow-wrap: anywhere;
|
|
129
|
-
white-space: normal;
|
|
130
|
-
}
|
|
131
|
-
.kpi {
|
|
132
|
-
display: flex;
|
|
133
|
-
gap: 16px;
|
|
134
|
-
flex-wrap: wrap;
|
|
135
|
-
}
|
|
136
|
-
.kpi .card {
|
|
137
|
-
padding: 12px 14px;
|
|
138
|
-
}
|
|
139
|
-
.k {
|
|
140
|
-
font-weight: 700;
|
|
141
|
-
}
|
|
142
|
-
.v {
|
|
143
|
-
font-variant-numeric: tabular-nums;
|
|
144
|
-
}
|
|
145
|
-
.list {
|
|
146
|
-
display: flex;
|
|
147
|
-
flex-direction: column;
|
|
148
|
-
gap: 12px;
|
|
149
|
-
}
|
|
150
|
-
.term {
|
|
151
|
-
padding: 10px;
|
|
152
|
-
background: #f8fafc;
|
|
153
|
-
border: 1px dashed var(--border);
|
|
154
|
-
border-radius: 12px;
|
|
155
|
-
}
|
|
156
|
-
details {
|
|
157
|
-
border: 1px solid var(--border);
|
|
158
|
-
border-radius: 12px;
|
|
159
|
-
padding: 10px 12px;
|
|
160
|
-
background: #fafcff;
|
|
161
|
-
}
|
|
162
|
-
details summary {
|
|
163
|
-
cursor: pointer;
|
|
164
|
-
font-weight: 700;
|
|
165
|
-
color: #0b3eaa;
|
|
166
|
-
}
|
|
167
|
-
.badge {
|
|
168
|
-
padding: 2px 8px;
|
|
169
|
-
border-radius: 999px;
|
|
170
|
-
font-weight: 700;
|
|
171
|
-
font-size: 12px;
|
|
172
|
-
border: 1px solid #cbd5e1;
|
|
173
|
-
background: #f1f5f9;
|
|
174
|
-
color: #0f172a;
|
|
175
|
-
}
|
|
176
|
-
.ok {
|
|
177
|
-
background: #dcfce7;
|
|
178
|
-
color: #166534;
|
|
179
|
-
border: 1px solid #86efac;
|
|
180
|
-
}
|
|
181
|
-
.fail {
|
|
182
|
-
background: #fee2e2;
|
|
183
|
-
color: #991b1b;
|
|
184
|
-
border: 1px solid #fecaca;
|
|
185
|
-
}
|
|
186
|
-
.harness {
|
|
187
|
-
border-left: 6px solid #c7d2fe;
|
|
188
|
-
}
|
|
189
|
-
.h-title {
|
|
190
|
-
display: flex;
|
|
191
|
-
align-items: center;
|
|
192
|
-
justify-content: space-between;
|
|
193
|
-
gap: 8px;
|
|
194
|
-
}
|
|
195
|
-
.small {
|
|
196
|
-
font-size: 12px;
|
|
197
|
-
}
|
|
198
|
-
code {
|
|
199
|
-
background: #f1f5f9;
|
|
200
|
-
padding: 2px 6px;
|
|
201
|
-
border-radius: 6px;
|
|
202
|
-
}
|
|
203
|
-
footer {
|
|
204
|
-
color: var(--muted);
|
|
205
|
-
font-size: 12px;
|
|
206
|
-
text-align: center;
|
|
207
|
-
margin: 16px 0 40px;
|
|
208
|
-
}
|
|
209
|
-
.divider {
|
|
210
|
-
height: 1px;
|
|
211
|
-
background: var(--border);
|
|
212
|
-
margin: -4px 0 8px;
|
|
213
|
-
}
|
|
214
|
-
.chips {
|
|
215
|
-
display: flex;
|
|
216
|
-
flex-wrap: wrap;
|
|
217
|
-
gap: 8px;
|
|
218
|
-
}
|
|
219
|
-
.chips .badge {
|
|
220
|
-
word-break: break-all;
|
|
221
|
-
overflow-wrap: anywhere;
|
|
222
|
-
white-space: normal;
|
|
223
|
-
}
|
|
224
|
-
.kpi .card .v {
|
|
225
|
-
word-break: break-word;
|
|
226
|
-
overflow-wrap: anywhere;
|
|
227
|
-
}
|
|
228
|
-
.row {
|
|
229
|
-
min-width: 0;
|
|
230
|
-
}
|
|
231
|
-
</style>
|
|
232
|
-
</head>
|
|
233
|
-
<body>
|
|
234
|
-
<div class="container stack">
|
|
235
|
-
<header class="card stack">
|
|
236
|
-
<div class="row" style="justify-content: space-between; align-items: flex-start; width: 100%">
|
|
237
|
-
<div>
|
|
238
|
-
<h1>Sum of all binomial coefficients</h1>
|
|
239
|
-
</div>
|
|
240
|
-
</div>
|
|
241
|
-
<span class="badge">Problem: B(n) = Σₖ₌₀ⁿ C(n,k)</span>
|
|
242
|
-
<p class="muted">
|
|
243
|
-
Give a non‑negative integer <em>n</em>. This page states the closed form of <span class="mono">B(n)</span>,
|
|
244
|
-
explains why it is true in mathematical English, and verifies it with a built‑in test harness.
|
|
245
|
-
</p>
|
|
246
|
-
</header>
|
|
247
|
-
|
|
248
|
-
<!-- INPUT -->
|
|
249
|
-
<section class="card stack" id="input-card">
|
|
250
|
-
<h2 style="margin: 0">Input</h2>
|
|
251
|
-
<div class="divider"></div>
|
|
252
|
-
<div class="row">
|
|
253
|
-
<label class="mono">n = </label>
|
|
254
|
-
<input id="nInput" type="number" min="0" step="1" value="4000" />
|
|
255
|
-
<button type="button" id="solve">Evaluate B(n)</button>
|
|
256
|
-
<button type="button" id="clear">Clear</button>
|
|
257
|
-
</div>
|
|
258
|
-
<p class="small muted">
|
|
259
|
-
Constraints: n ∈ ℕ, typically n ≤ 1000 for display. All arithmetic uses exact <code>BigInt</code>.
|
|
260
|
-
</p>
|
|
261
|
-
</section>
|
|
262
|
-
|
|
263
|
-
<!-- OUTPUT -->
|
|
264
|
-
<section class="card stack" id="output-card" aria-live="polite">
|
|
265
|
-
<h2 style="margin: 0">Output</h2>
|
|
266
|
-
<div class="divider"></div>
|
|
267
|
-
|
|
268
|
-
<!-- Answer KPIs -->
|
|
269
|
-
<section class="stack">
|
|
270
|
-
<div class="kpi">
|
|
271
|
-
<div class="card">
|
|
272
|
-
<div class="k">Answer</div>
|
|
273
|
-
<div id="answer" class="v mono">—</div>
|
|
274
|
-
</div>
|
|
275
|
-
<div class="card">
|
|
276
|
-
<div class="k">Closed form</div>
|
|
277
|
-
<div id="closed" class="v mono">B(n) = 2^n</div>
|
|
278
|
-
</div>
|
|
279
|
-
<div class="card">
|
|
280
|
-
<div class="k">Σ C(n,k)</div>
|
|
281
|
-
<div id="sumRow" class="v mono">—</div>
|
|
282
|
-
</div>
|
|
283
|
-
<div class="card">
|
|
284
|
-
<div class="k">Row length</div>
|
|
285
|
-
<div id="rowLen" class="v mono">—</div>
|
|
286
|
-
</div>
|
|
287
|
-
</div>
|
|
288
|
-
</section>
|
|
289
|
-
|
|
290
|
-
<!-- Reason Why (mathematical English) -->
|
|
291
|
-
<section class="stack">
|
|
292
|
-
<h3 style="margin: 0">Reason Why</h3>
|
|
293
|
-
<div class="list">
|
|
294
|
-
<div class="term">
|
|
295
|
-
<strong>Algebraic.</strong> The binomial theorem states
|
|
296
|
-
<span class="mono">(x + y)^n = Σₖ C(n,k) x^{n−k} y^k</span>. Substituting
|
|
297
|
-
<span class="mono">x = y = 1</span> gives <span class="mono">2^n = Σₖ C(n,k)</span>. Hence
|
|
298
|
-
<span class="mono">B(n) = 2^n</span>.
|
|
299
|
-
</div>
|
|
300
|
-
<div class="term">
|
|
301
|
-
<strong>Combinatorial.</strong> Each term <span class="mono">C(n,k)</span> counts the
|
|
302
|
-
<span class="mono">k</span>‑element subsets of an <span class="mono">n</span>‑set. Summing over all
|
|
303
|
-
<span class="mono">k</span> counts every subset exactly once, so the total is the number of all subsets,
|
|
304
|
-
namely <span class="mono">2^n</span>.
|
|
305
|
-
</div>
|
|
306
|
-
<div class="term">
|
|
307
|
-
<strong>Symmetry check.</strong> Because <span class="mono">C(n,k) = C(n,n−k)</span>, the partial sums are
|
|
308
|
-
pairwise matched; the extremes satisfy <span class="mono">C(n,0)=C(n,n)=1</span>.
|
|
309
|
-
</div>
|
|
310
|
-
</div>
|
|
311
|
-
<details>
|
|
312
|
-
<summary>Show coefficients C(n,k)</summary>
|
|
313
|
-
<div id="row" class="chips mono"></div>
|
|
314
|
-
</details>
|
|
315
|
-
</section>
|
|
316
|
-
|
|
317
|
-
<!-- Check (harness) for the user's n -->
|
|
318
|
-
<section class="stack">
|
|
319
|
-
<h3 style="margin: 0">Check (harness)</h3>
|
|
320
|
-
<div id="checks" class="list"></div>
|
|
321
|
-
</section>
|
|
322
|
-
</section>
|
|
323
|
-
|
|
324
|
-
<!-- PRELOADED HARNESS CASES (≥ 6) -->
|
|
325
|
-
<section class="card stack harness" id="preloaded">
|
|
326
|
-
<div class="h-title">
|
|
327
|
-
<h2 style="margin: 0">Preloaded Checks (harness)</h2>
|
|
328
|
-
<div class="row">
|
|
329
|
-
<button id="runAll">Run all</button>
|
|
330
|
-
<button class="ghost" id="clearHarness">Clear results</button>
|
|
331
|
-
</div>
|
|
332
|
-
</div>
|
|
333
|
-
<p class="small muted">
|
|
334
|
-
Each block recomputes <span class="mono">B(n)</span> two ways (<span class="mono">Σ C(n,k)</span> vs
|
|
335
|
-
<span class="mono">2^n</span>) and asserts they agree. One case is intentionally invalid.
|
|
336
|
-
</p>
|
|
337
|
-
<div id="harnesses" class="stack"></div>
|
|
338
|
-
</section>
|
|
339
|
-
|
|
340
|
-
<footer>
|
|
341
|
-
<div>Built as a self‑checking artifact: program → <em>Answer</em>, <em>Reason Why</em>, <em>Check</em>.</div>
|
|
342
|
-
<div class="small">This page performs only on‑device computation.</div>
|
|
343
|
-
</footer>
|
|
344
|
-
</div>
|
|
345
|
-
|
|
346
|
-
<script>
|
|
347
|
-
// ---------- BigInt helpers ----------
|
|
348
|
-
const ZERO = 0n,
|
|
349
|
-
ONE = 1n,
|
|
350
|
-
TWO = 2n;
|
|
351
|
-
const toBig = (x) => {
|
|
352
|
-
try {
|
|
353
|
-
return BigInt(x);
|
|
354
|
-
} catch {
|
|
355
|
-
return null;
|
|
356
|
-
}
|
|
357
|
-
};
|
|
358
|
-
const isNonNegInt = (b) => b !== null && b >= 0n;
|
|
359
|
-
|
|
360
|
-
// fast power: a^e for BigInt
|
|
361
|
-
function pow(a, e) {
|
|
362
|
-
let base = a,
|
|
363
|
-
exp = e,
|
|
364
|
-
res = 1n;
|
|
365
|
-
while (exp > 0n) {
|
|
366
|
-
if (exp & 1n) res *= base;
|
|
367
|
-
base *= base;
|
|
368
|
-
exp >>= 1n;
|
|
369
|
-
}
|
|
370
|
-
return res;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// compute the nth binomial row [C(n,0),...,C(n,n)] as BigInts
|
|
374
|
-
function binomRow(n) {
|
|
375
|
-
const N = Number(n);
|
|
376
|
-
const row = new Array(N + 1);
|
|
377
|
-
row[0] = 1n;
|
|
378
|
-
for (let k = 1; k <= N; k++) {
|
|
379
|
-
// C(n,k) = C(n,k-1) * (n-k+1)/k
|
|
380
|
-
const prev = row[k - 1];
|
|
381
|
-
const num = n - BigInt(k) + 1n; // BigInt
|
|
382
|
-
const den = BigInt(k);
|
|
383
|
-
row[k] = (prev * num) / den; // exact division for binomial coefficients
|
|
384
|
-
}
|
|
385
|
-
return row;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
function sumRow(row) {
|
|
389
|
-
return row.reduce((acc, v) => acc + v, 0n);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// ---------- UI helpers ----------
|
|
393
|
-
const el = (tag, attrs = {}, children = []) => {
|
|
394
|
-
const node = document.createElement(tag);
|
|
395
|
-
Object.entries(attrs).forEach(([k, v]) => {
|
|
396
|
-
if (k === 'class') node.className = v;
|
|
397
|
-
else if (k === 'html') node.innerHTML = v;
|
|
398
|
-
else if (k.startsWith('on')) node.addEventListener(k.slice(2).toLowerCase(), v);
|
|
399
|
-
else node.setAttribute(k, v);
|
|
400
|
-
});
|
|
401
|
-
children.forEach((c) => node.appendChild(typeof c === 'string' ? document.createTextNode(c) : c));
|
|
402
|
-
return node;
|
|
403
|
-
};
|
|
404
|
-
|
|
405
|
-
function renderChips(div, row) {
|
|
406
|
-
div.replaceChildren(...row.map((v, k) => el('span', { class: 'badge' }, [`C(n,${k})=${v.toString()}`])));
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
function renderChecks(n, row, sum, pow2) {
|
|
410
|
-
const checks = document.getElementById('checks');
|
|
411
|
-
const list = [];
|
|
412
|
-
|
|
413
|
-
const eq = sum === pow2;
|
|
414
|
-
list.push(
|
|
415
|
-
el('div', { class: 'row' }, [
|
|
416
|
-
el('span', { class: 'badge ' + (eq ? 'ok' : 'fail') }, [eq ? 'PASS' : 'FAIL']),
|
|
417
|
-
document.createTextNode(' Equality '),
|
|
418
|
-
el('span', { class: 'mono' }, ['Σ C(n,k) = 2^n']),
|
|
419
|
-
]),
|
|
420
|
-
);
|
|
421
|
-
|
|
422
|
-
const ends = row.length >= 1 && row[0] === 1n && row[row.length - 1] === 1n;
|
|
423
|
-
list.push(
|
|
424
|
-
el('div', { class: 'row' }, [
|
|
425
|
-
el('span', { class: 'badge ' + (ends ? 'ok' : 'fail') }, [ends ? 'PASS' : 'FAIL']),
|
|
426
|
-
el('span', { class: 'mono' }, ['C(n,0)=C(n,n)=1']),
|
|
427
|
-
]),
|
|
428
|
-
);
|
|
429
|
-
|
|
430
|
-
const sym = row.every((v, i) => v === row[row.length - 1 - i]);
|
|
431
|
-
list.push(
|
|
432
|
-
el('div', { class: 'row' }, [
|
|
433
|
-
el('span', { class: 'badge ' + (sym ? 'ok' : 'fail') }, [sym ? 'PASS' : 'FAIL']),
|
|
434
|
-
el('span', { class: 'mono' }, ['Symmetry C(n,k)=C(n,n−k)']),
|
|
435
|
-
]),
|
|
436
|
-
);
|
|
437
|
-
|
|
438
|
-
const lenOk = row.length === Number(n) + 1;
|
|
439
|
-
list.push(
|
|
440
|
-
el('div', { class: 'row' }, [
|
|
441
|
-
el('span', { class: 'badge ' + (lenOk ? 'ok' : 'fail') }, [lenOk ? 'PASS' : 'FAIL']),
|
|
442
|
-
el('span', { class: 'mono' }, ['Row length n+1']),
|
|
443
|
-
]),
|
|
444
|
-
);
|
|
445
|
-
|
|
446
|
-
// middle (when n even)
|
|
447
|
-
if (n % 2n === 0n) {
|
|
448
|
-
const mid = row[Number(n / 2n)];
|
|
449
|
-
const midOk = typeof mid !== 'undefined' && mid >= 1n;
|
|
450
|
-
list.push(
|
|
451
|
-
el('div', { class: 'row' }, [
|
|
452
|
-
el('span', { class: 'badge ' + (midOk ? 'ok' : 'fail') }, [midOk ? 'PASS' : 'FAIL']),
|
|
453
|
-
el('span', { class: 'mono' }, ['Central coefficient ≥ 1']),
|
|
454
|
-
]),
|
|
455
|
-
);
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
// Pascal identity spot-check (random k)
|
|
459
|
-
if (row.length > 2) {
|
|
460
|
-
const k = Math.min(2, row.length - 2);
|
|
461
|
-
const lhs = row[k];
|
|
462
|
-
const rhs = row[k - 1] + row[k + 1] * 0n + (row[k - 1] + row[k]) - row[k - 1]; // keep code simple, see below
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
list.push(
|
|
466
|
-
el('div', { class: 'row' }, [
|
|
467
|
-
el('span', { class: 'badge ok' }, ['FACT']),
|
|
468
|
-
el('span', { class: 'small muted' }, [
|
|
469
|
-
'Any subset of an n‑set corresponds to a unique 0/1 choice per element ⇒ 2^n subsets.',
|
|
470
|
-
]),
|
|
471
|
-
]),
|
|
472
|
-
);
|
|
473
|
-
|
|
474
|
-
checks.replaceChildren(...list);
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
function evaluate() {
|
|
478
|
-
const nVal = toBig(document.getElementById('nInput').value.trim());
|
|
479
|
-
if (!isNonNegInt(nVal)) {
|
|
480
|
-
document.getElementById('answer').textContent = '—';
|
|
481
|
-
document.getElementById('sumRow').textContent = '—';
|
|
482
|
-
document.getElementById('rowLen').textContent = '—';
|
|
483
|
-
document.getElementById('row').replaceChildren();
|
|
484
|
-
document
|
|
485
|
-
.getElementById('checks')
|
|
486
|
-
.replaceChildren(
|
|
487
|
-
el('div', { class: 'term' }, [
|
|
488
|
-
el('span', { class: 'badge fail' }, ['FAIL']),
|
|
489
|
-
document.createTextNode(' n must be a non‑negative integer.'),
|
|
490
|
-
]),
|
|
491
|
-
);
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
const n = nVal;
|
|
495
|
-
const row = binomRow(n);
|
|
496
|
-
const S = sumRow(row);
|
|
497
|
-
const P = pow(2n, n);
|
|
498
|
-
|
|
499
|
-
document.getElementById('answer').textContent = `B(${n}) = ${P.toString()}`;
|
|
500
|
-
document.getElementById('sumRow').textContent = S.toString();
|
|
501
|
-
document.getElementById('rowLen').textContent = `${row.length}`;
|
|
502
|
-
renderChips(document.getElementById('row'), row);
|
|
503
|
-
renderChecks(n, row, S, P);
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
document.getElementById('solve').onclick = evaluate;
|
|
507
|
-
document.getElementById('clear').onclick = () => {
|
|
508
|
-
document.getElementById('nInput').value = '';
|
|
509
|
-
document.getElementById('answer').textContent = '—';
|
|
510
|
-
document.getElementById('sumRow').textContent = '—';
|
|
511
|
-
document.getElementById('rowLen').textContent = '—';
|
|
512
|
-
document.getElementById('row').replaceChildren();
|
|
513
|
-
document.getElementById('checks').replaceChildren();
|
|
514
|
-
};
|
|
515
|
-
|
|
516
|
-
// ---------- Preloaded harnesses (≥ 8 including one invalid) ----------
|
|
517
|
-
const harnessList = [
|
|
518
|
-
{ n: 0, title: 'n = 0 ⇒ [1] and B(0)=1' },
|
|
519
|
-
{ n: 1, title: 'n = 1 ⇒ [1,1] and B(1)=2' },
|
|
520
|
-
{ n: 2, title: 'n = 2 ⇒ [1,2,1] and B(2)=4' },
|
|
521
|
-
{ n: 3, title: 'n = 3 ⇒ [1,3,3,1] and B(3)=8' },
|
|
522
|
-
{ n: 5, title: 'n = 5 ⇒ B(5)=32' },
|
|
523
|
-
{ n: 10, title: 'n = 10 ⇒ B(10)=1024' },
|
|
524
|
-
{ n: 20, title: 'n = 20 ⇒ B(20)=1,048,576' },
|
|
525
|
-
{ n: -1, title: 'Invalid (should fail): n = -1', negative: true },
|
|
526
|
-
];
|
|
527
|
-
|
|
528
|
-
const harnessDiv = document.getElementById('harnesses');
|
|
529
|
-
|
|
530
|
-
function makeHarnessCard(h) {
|
|
531
|
-
const card = el('section', { class: 'card stack' });
|
|
532
|
-
const head = el('div', { class: 'h-title' }, [
|
|
533
|
-
el('div', {}, [el('strong', {}, [h.title])]),
|
|
534
|
-
el('div', { class: 'small muted' }, ['Check (harness)']),
|
|
535
|
-
]);
|
|
536
|
-
const kpis = el('div', { class: 'kpi' });
|
|
537
|
-
const ans = el('div', { class: 'card' });
|
|
538
|
-
ans.append(el('div', { class: 'k' }, ['Answer']), el('div', { class: 'v mono' }, ['—']));
|
|
539
|
-
const closed = el('div', { class: 'card' });
|
|
540
|
-
closed.append(el('div', { class: 'k' }, ['Closed form']), el('div', { class: 'v mono' }, ['B(n)=2^n']));
|
|
541
|
-
const sumK = el('div', { class: 'card' });
|
|
542
|
-
sumK.append(el('div', { class: 'k' }, ['Σ C(n,k)']), el('div', { class: 'v mono' }, ['—']));
|
|
543
|
-
const len = el('div', { class: 'card' });
|
|
544
|
-
len.append(el('div', { class: 'k' }, ['Row length']), el('div', { class: 'v mono' }, ['—']));
|
|
545
|
-
kpis.append(ans, closed, sumK, len);
|
|
546
|
-
|
|
547
|
-
const reason = el('p', { class: 'muted small' }, [
|
|
548
|
-
'Because (1+1)^n = Σ C(n,k) by the binomial theorem, setting x=y=1 yields B(n)=2^n; combinatorially, it counts all subsets.',
|
|
549
|
-
]);
|
|
550
|
-
const checks = el('div', { class: 'list' });
|
|
551
|
-
const run = el('button', { class: 'secondary' }, ['Run']);
|
|
552
|
-
|
|
553
|
-
run.onclick = () => {
|
|
554
|
-
const nBig = toBig(h.n);
|
|
555
|
-
if (!isNonNegInt(nBig)) {
|
|
556
|
-
ans.querySelector('.v').textContent = '—';
|
|
557
|
-
sumK.querySelector('.v').textContent = '—';
|
|
558
|
-
len.querySelector('.v').textContent = '—';
|
|
559
|
-
checks.replaceChildren(
|
|
560
|
-
el('div', { class: 'term' }, [
|
|
561
|
-
el('span', { class: 'badge fail' }, ['FAIL']),
|
|
562
|
-
document.createTextNode(' n must be a non‑negative integer.'),
|
|
563
|
-
]),
|
|
564
|
-
);
|
|
565
|
-
return;
|
|
566
|
-
}
|
|
567
|
-
const row = binomRow(nBig);
|
|
568
|
-
const S = sumRow(row);
|
|
569
|
-
const P = pow(2n, nBig);
|
|
570
|
-
ans.querySelector('.v').textContent = `B(${nBig}) = ${P}`;
|
|
571
|
-
sumK.querySelector('.v').textContent = S.toString();
|
|
572
|
-
len.querySelector('.v').textContent = `${row.length}`;
|
|
573
|
-
|
|
574
|
-
const list = [];
|
|
575
|
-
const eq = S === P;
|
|
576
|
-
list.push(
|
|
577
|
-
el('div', { class: 'row' }, [
|
|
578
|
-
el('span', { class: 'badge ' + (eq ? 'ok' : 'fail') }, [eq ? 'PASS' : 'FAIL']),
|
|
579
|
-
document.createTextNode(' Equality '),
|
|
580
|
-
el('span', { class: 'mono' }, ['Σ C(n,k) = 2^n']),
|
|
581
|
-
]),
|
|
582
|
-
);
|
|
583
|
-
const ends = row.length >= 1 && row[0] === 1n && row[row.length - 1] === 1n;
|
|
584
|
-
list.push(
|
|
585
|
-
el('div', { class: 'row' }, [
|
|
586
|
-
el('span', { class: 'badge ' + (ends ? 'ok' : 'fail') }, [ends ? 'PASS' : 'FAIL']),
|
|
587
|
-
el('span', { class: 'mono' }, ['C(n,0)=C(n,n)=1']),
|
|
588
|
-
]),
|
|
589
|
-
);
|
|
590
|
-
const sym = row.every((v, i) => v === row[row.length - 1 - i]);
|
|
591
|
-
list.push(
|
|
592
|
-
el('div', { class: 'row' }, [
|
|
593
|
-
el('span', { class: 'badge ' + (sym ? 'ok' : 'fail') }, [sym ? 'PASS' : 'FAIL']),
|
|
594
|
-
el('span', { class: 'mono' }, ['Symmetry C(n,k)=C(n,n−k)']),
|
|
595
|
-
]),
|
|
596
|
-
);
|
|
597
|
-
list.push(
|
|
598
|
-
el('div', { class: 'row' }, [
|
|
599
|
-
el('span', { class: 'badge ok' }, ['FACT']),
|
|
600
|
-
el('span', { class: 'small muted' }, [`B(${nBig}) counts all 0/1 choices across ${nBig} elements.`]),
|
|
601
|
-
]),
|
|
602
|
-
);
|
|
603
|
-
checks.replaceChildren(...list);
|
|
604
|
-
};
|
|
605
|
-
|
|
606
|
-
if (h.negative) {
|
|
607
|
-
const warn = el('div', { class: 'small muted' }, [
|
|
608
|
-
'This case is intentionally invalid and should report a failure.',
|
|
609
|
-
]);
|
|
610
|
-
card.append(head, kpis, reason, warn, checks, run);
|
|
611
|
-
} else {
|
|
612
|
-
card.append(head, kpis, reason, checks, run);
|
|
613
|
-
}
|
|
614
|
-
return card;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
harnessList.forEach((h) => harnessDiv.appendChild(makeHarnessCard(h)));
|
|
618
|
-
document.getElementById('runAll').onclick = () => {
|
|
619
|
-
const buttons = [...harnessDiv.querySelectorAll('button.secondary')];
|
|
620
|
-
buttons.forEach((b) => b.click());
|
|
621
|
-
};
|
|
622
|
-
document.getElementById('clearHarness').onclick = () => {
|
|
623
|
-
harnessDiv.querySelectorAll('.list').forEach((div) => div.replaceChildren());
|
|
624
|
-
harnessDiv.querySelectorAll('.v').forEach((div) => (div.textContent = '—'));
|
|
625
|
-
};
|
|
626
|
-
|
|
627
|
-
// auto-evaluate initial n
|
|
628
|
-
evaluate();
|
|
629
|
-
</script>
|
|
630
|
-
</body>
|
|
631
|
-
</html>
|