eyeling 1.15.11 → 1.15.13

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.
Files changed (50) hide show
  1. package/README.md +3 -3
  2. package/follows-from/artifacts/ackermann.html +678 -0
  3. package/follows-from/artifacts/auroracare.html +1297 -0
  4. package/follows-from/artifacts/bike-trip.html +752 -0
  5. package/follows-from/artifacts/binomial-theorem.html +631 -0
  6. package/follows-from/artifacts/bmi.html +511 -0
  7. package/follows-from/artifacts/building-performance.html +750 -0
  8. package/follows-from/artifacts/clinical-care.html +726 -0
  9. package/follows-from/artifacts/collatz.html +403 -0
  10. package/follows-from/artifacts/complex.html +321 -0
  11. package/follows-from/artifacts/control-system.html +482 -0
  12. package/follows-from/artifacts/delfour.html +849 -0
  13. package/follows-from/artifacts/earthquake-epicenter.html +982 -0
  14. package/follows-from/artifacts/eco-route.html +662 -0
  15. package/follows-from/artifacts/euclid-infinitude.html +564 -0
  16. package/follows-from/artifacts/euler-identity.html +667 -0
  17. package/follows-from/artifacts/exoplanet-transit.html +1000 -0
  18. package/follows-from/artifacts/faltings-theorem.html +1046 -0
  19. package/follows-from/artifacts/fibonacci.html +299 -0
  20. package/follows-from/artifacts/fundamental-theorem-arithmetic.html +398 -0
  21. package/follows-from/artifacts/godel-numbering.html +743 -0
  22. package/follows-from/artifacts/gps-bike.html +759 -0
  23. package/follows-from/artifacts/gps-clinical-bench.html +792 -0
  24. package/follows-from/artifacts/graph-french.html +449 -0
  25. package/follows-from/artifacts/grass-molecular.html +592 -0
  26. package/follows-from/artifacts/group-theory.html +740 -0
  27. package/follows-from/artifacts/health-info.html +833 -0
  28. package/follows-from/artifacts/kaprekar-constant.html +576 -0
  29. package/follows-from/artifacts/lee.html +805 -0
  30. package/follows-from/artifacts/linked-lists.html +502 -0
  31. package/follows-from/artifacts/lldm.html +612 -0
  32. package/follows-from/artifacts/matrix-multiplication.html +502 -0
  33. package/follows-from/artifacts/matrix.html +651 -0
  34. package/follows-from/artifacts/newton-raphson.html +944 -0
  35. package/follows-from/artifacts/peano-factorial.html +456 -0
  36. package/follows-from/artifacts/pi.html +363 -0
  37. package/follows-from/artifacts/polynomial.html +646 -0
  38. package/follows-from/artifacts/prime.html +366 -0
  39. package/follows-from/artifacts/pythagorean-theorem.html +468 -0
  40. package/follows-from/artifacts/rest-path.html +469 -0
  41. package/follows-from/artifacts/roots-of-unity.html +363 -0
  42. package/follows-from/artifacts/turing.html +409 -0
  43. package/follows-from/artifacts/wind-turbines.html +726 -0
  44. package/follows-from/index.html +549 -0
  45. package/follows-from/library/index.md +22 -0
  46. package/follows-from/logo.svg +12 -0
  47. package/follows-from/manifesto.md +48 -0
  48. package/follows-from/method/index.md +30 -0
  49. package/follows-from/path/index.md +20 -0
  50. package/package.json +4 -3
@@ -0,0 +1,363 @@
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>Roots of Unity</title>
7
+ <style>
8
+ :root {
9
+ --bg: #f6f8fb;
10
+ --ink: #0f172a;
11
+ --sub: #334155;
12
+ --line: #d5dbe7;
13
+ --circle: #eaf3ff;
14
+ --edge: #4f79c8;
15
+ --pt: #0ea5e9;
16
+ --axis: #94a3b8;
17
+ --ok: #059669;
18
+ --bad: #dc2626;
19
+ }
20
+ html,
21
+ body {
22
+ margin: 0;
23
+ background: var(--bg);
24
+ color: var(--ink);
25
+ font-family:
26
+ system-ui,
27
+ Segoe UI,
28
+ Roboto,
29
+ Helvetica,
30
+ Arial,
31
+ sans-serif;
32
+ }
33
+ header {
34
+ padding: 18px 20px;
35
+ border-bottom: 1px solid var(--line);
36
+ }
37
+ h1 {
38
+ margin: 0 0 6px;
39
+ font-size: 22px;
40
+ }
41
+ h2 {
42
+ margin: 18px 0 10px;
43
+ font-size: 17px;
44
+ }
45
+ p,
46
+ li,
47
+ small {
48
+ line-height: 1.45;
49
+ }
50
+ main {
51
+ display: block;
52
+ padding: 18px 20px 40px;
53
+ }
54
+ .card {
55
+ background: #fff;
56
+ border: 1px solid var(--line);
57
+ border-radius: 12px;
58
+ box-shadow: 0 1px 0 rgba(15, 23, 42, 0.04);
59
+ margin: 0 0 18px;
60
+ }
61
+ .card header {
62
+ padding: 12px 14px;
63
+ border-bottom: 1px solid var(--line);
64
+ border-radius: 12px 12px 0 0;
65
+ }
66
+ .card section {
67
+ padding: 14px;
68
+ }
69
+ .muted {
70
+ color: var(--sub);
71
+ }
72
+ .mono {
73
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
74
+ }
75
+ .ok {
76
+ color: var(--ok);
77
+ }
78
+ .bad {
79
+ color: var(--bad);
80
+ }
81
+ svg {
82
+ max-width: 50%;
83
+ height: auto;
84
+ display: block;
85
+ margin: 0 auto;
86
+ shape-rendering: geometricPrecision;
87
+ }
88
+ </style>
89
+ </head>
90
+ <body>
91
+ <header>
92
+ <h1>Roots of Unity</h1>
93
+ </header>
94
+
95
+ <main>
96
+ <!-- WHAT THIS IS -->
97
+ <article class="card">
98
+ <header><h2>What this is?</h2></header>
99
+ <section>
100
+ <p>
101
+ An Argand diagram of the <em>n</em>-th roots of unity: points <em>z<sub>k</sub></em> = cos(2πk/n) + i
102
+ sin(2πk/n) for k = 0,…,n−1. They lie on the unit circle, equally spaced, forming a regular <em>n</em>-gon.
103
+ Multiplying by a unit complex number rotates; raising to the <em>n</em>-th power maps all points to 1.
104
+ </p>
105
+ </section>
106
+ </article>
107
+
108
+ <!-- ANSWER -->
109
+ <article class="card">
110
+ <header><h2>Answer — drawing</h2></header>
111
+ <section>
112
+ <svg id="fig" viewBox="0 0 240 240" aria-label="n-th roots of unity on the unit circle">
113
+ <g id="grid"></g>
114
+ <g id="axes"></g>
115
+ <g id="poly"></g>
116
+ <g id="points"></g>
117
+ </svg>
118
+ </section>
119
+ </article>
120
+
121
+ <!-- REASON -->
122
+ <article class="card">
123
+ <header><h2>Reason</h2></header>
124
+ <section>
125
+ <ol>
126
+ <li>
127
+ Solutions of z<sup>n</sup> = 1 are z<sub>k</sub> = cos(2πk/n) + i sin(2πk/n), k = 0,…,n−1 (De Moivre).
128
+ </li>
129
+ <li>All have |z<sub>k</sub>| = 1, arguments 2πk/n, hence equal spacing by 2π/n and a regular polygon.</li>
130
+ <li>
131
+ Sum of all roots is 0 and product is (−1)<sup>n−1</sup>. The polygon (circumradius 1) has area A = (n/2) ·
132
+ sin(2π/n).
133
+ </li>
134
+ </ol>
135
+ </section>
136
+ </article>
137
+
138
+ <!-- CHECK -->
139
+ <article class="card">
140
+ <header><h2>Check</h2></header>
141
+ <section>
142
+ <ul id="checks" class="mono"></ul>
143
+ <div id="numbers" class="mono" style="margin-top: 8px; white-space: pre-wrap"></div>
144
+ <small class="muted"
145
+ >We verify z<sup>n</sup>=1, unit modulus, equal angle steps, sum/product identities, chord length
146
+ 2·sin(π/n), area formula, and DFT sums Σ z<sub>k</sub><sup>m</sup> = 0 for 1 ≤ m ≤ n−1.</small
147
+ >
148
+ </section>
149
+ </article>
150
+ </main>
151
+
152
+ <script>
153
+ (function () {
154
+ const checks = document.getElementById('checks');
155
+ const numbers = document.getElementById('numbers');
156
+ const ok = (t) => `<li><span class="ok">OK</span> — ${t}</li>`;
157
+ const bad = (t) => `<li><span class="bad">FAIL</span> — ${t}</li>`;
158
+
159
+ // ===== Parameters =====
160
+ const n = 12; // number of roots (change if you like)
161
+ const cx = 120,
162
+ cy = 120,
163
+ R = 100; // SVG center and radius (pixels)
164
+ const tol = 1e-10;
165
+
166
+ // ===== Build roots on the unit circle (math coords) =====
167
+ const roots = [];
168
+ for (let k = 0; k < n; k++) {
169
+ const theta = (2 * Math.PI * k) / n;
170
+ roots.push({ re: Math.cos(theta), im: Math.sin(theta), theta });
171
+ }
172
+
173
+ // ===== Drawing helpers (map unit circle -> SVG) =====
174
+ const X = (x) => cx + R * x;
175
+ const Y = (y) => cy - R * y; // flip y for SVG
176
+
177
+ const gGrid = document.getElementById('grid');
178
+ const gAxes = document.getElementById('axes');
179
+ const gPoly = document.getElementById('poly');
180
+ const gPts = document.getElementById('points');
181
+
182
+ // background ring and frame ticks
183
+ const ring = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
184
+ ring.setAttribute('cx', cx);
185
+ ring.setAttribute('cy', cy);
186
+ ring.setAttribute('r', R);
187
+ ring.setAttribute('fill', 'var(--circle)');
188
+ ring.setAttribute('stroke', '#c7d2e5');
189
+ ring.setAttribute('stroke-width', '1.2');
190
+ gGrid.appendChild(ring);
191
+
192
+ // axes
193
+ const axH = document.createElementNS('http://www.w3.org/2000/svg', 'line');
194
+ axH.setAttribute('x1', X(-1.1));
195
+ axH.setAttribute('y1', Y(0));
196
+ axH.setAttribute('x2', X(1.1));
197
+ axH.setAttribute('y2', Y(0));
198
+ axH.setAttribute('stroke', 'var(--axis)');
199
+ axH.setAttribute('stroke-width', '1.2');
200
+ gAxes.appendChild(axH);
201
+
202
+ const axV = document.createElementNS('http://www.w3.org/2000/svg', 'line');
203
+ axV.setAttribute('x1', X(0));
204
+ axV.setAttribute('y1', Y(-1.1));
205
+ axV.setAttribute('x2', X(0));
206
+ axV.setAttribute('y2', Y(1.1));
207
+ axV.setAttribute('stroke', 'var(--axis)');
208
+ axV.setAttribute('stroke-width', '1.2');
209
+ gAxes.appendChild(axV);
210
+
211
+ // polygon through the roots (in order)
212
+ const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
213
+ let d = `M ${X(roots[0].re)} ${Y(roots[0].im)}`;
214
+ for (let k = 1; k < n; k++) d += ` L ${X(roots[k].re)} ${Y(roots[k].im)}`;
215
+ d += ' Z';
216
+ path.setAttribute('d', d);
217
+ path.setAttribute('fill', 'none');
218
+ path.setAttribute('stroke', 'var(--edge)');
219
+ path.setAttribute('stroke-width', '1.8');
220
+ gPoly.appendChild(path);
221
+
222
+ // points
223
+ roots.forEach((z, k) => {
224
+ const c = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
225
+ c.setAttribute('cx', X(z.re));
226
+ c.setAttribute('cy', Y(z.im));
227
+ c.setAttribute('r', 2.4);
228
+ c.setAttribute('fill', 'white');
229
+ c.setAttribute('stroke', 'var(--pt)');
230
+ c.setAttribute('stroke-width', '1.4');
231
+ gPts.appendChild(c);
232
+ });
233
+
234
+ // ===== Checks =====
235
+ // 1) z^n = 1 and |z| = 1
236
+ let powOK = true,
237
+ modOK = true;
238
+ roots.forEach((z) => {
239
+ const r = Math.hypot(z.re, z.im);
240
+ if (Math.abs(r - 1) > 1e-12) modOK = false;
241
+ // z^n using angle
242
+ const zn = { re: Math.cos(n * Math.atan2(z.im, z.re)), im: Math.sin(n * Math.atan2(z.im, z.re)) };
243
+ if (Math.hypot(zn.re - 1, zn.im - 0) > 1e-9) powOK = false;
244
+ });
245
+ checks.insertAdjacentHTML(
246
+ 'beforeend',
247
+ modOK ? ok('Every root has unit modulus |z| = 1') : bad('Some root |z| ≠ 1'),
248
+ );
249
+ checks.insertAdjacentHTML(
250
+ 'beforeend',
251
+ powOK ? ok('Every root satisfies z^n = 1') : bad('Some root does not satisfy z^n = 1'),
252
+ );
253
+
254
+ // 2) Equal angle steps 2π/n
255
+ const ang = roots.map((z) => Math.atan2(z.im, z.re)).sort((a, b) => a - b);
256
+ // unwrap continuity
257
+ for (let i = 1; i < ang.length; i++) if (ang[i] - ang[i - 1] < -Math.PI) ang[i] += 2 * Math.PI;
258
+ const step = (2 * Math.PI) / n;
259
+ let spacingOK = true,
260
+ maxDev = 0;
261
+ for (let i = 0; i < n; i++) {
262
+ const a0 = ang[i],
263
+ a1 = ang[(i + 1) % n] + (i + 1 === n ? 2 * Math.PI : 0);
264
+ const dev = Math.abs(a1 - a0 - step);
265
+ if (dev > maxDev) maxDev = dev;
266
+ if (dev > 1e-10) spacingOK = false;
267
+ }
268
+ checks.insertAdjacentHTML(
269
+ 'beforeend',
270
+ spacingOK
271
+ ? ok('Equal angular spacing Δθ = 2π/n')
272
+ : bad(`Unequal spacing (max deviation ${maxDev.toExponential(2)})`),
273
+ );
274
+
275
+ // 3) Sum of roots = 0
276
+ const sum = roots.reduce((a, z) => ({ re: a.re + z.re, im: a.im + z.im }), { re: 0, im: 0 });
277
+ const sumOK = Math.hypot(sum.re, sum.im) < 1e-9;
278
+ checks.insertAdjacentHTML(
279
+ 'beforeend',
280
+ sumOK
281
+ ? ok('Sum of all roots equals 0')
282
+ : bad(`Sum of roots not 0: |Σ| = ${Math.hypot(sum.re, sum.im).toExponential(2)}`),
283
+ );
284
+
285
+ // 4) Product of roots = (−1)^(n−1)
286
+ const prodArg = roots.reduce((a, z) => a + Math.atan2(z.im, z.re), 0); // magnitude is 1^n=1
287
+ // wrap to nearest of {0, π} mod 2π
288
+ let prodSign = Math.cos(prodArg) >= 0 ? 1 : -1;
289
+ const expectedSign = (n - 1) % 2 === 0 ? 1 : -1;
290
+ const prodOK = prodSign === expectedSign;
291
+ checks.insertAdjacentHTML(
292
+ 'beforeend',
293
+ prodOK ? ok('Product of roots equals (−1)^(n−1)') : bad('Product check failed'),
294
+ );
295
+
296
+ // 5) Chord length between consecutive roots = 2 sin(π/n)
297
+ const chord = 2 * Math.sin(Math.PI / n);
298
+ let chordOK = true,
299
+ chordMaxDev = 0;
300
+ for (let k = 0; k < n; k++) {
301
+ const a = roots[k],
302
+ b = roots[(k + 1) % n];
303
+ const d = Math.hypot(a.re - b.re, a.im - b.im);
304
+ const dev = Math.abs(d - chord);
305
+ if (dev > chordMaxDev) chordMaxDev = dev;
306
+ if (dev > 1e-10) chordOK = false;
307
+ }
308
+ checks.insertAdjacentHTML(
309
+ 'beforeend',
310
+ chordOK
311
+ ? ok('Consecutive chord length is 2·sin(π/n)')
312
+ : bad(`Chord length mismatch (max deviation ${chordMaxDev.toExponential(2)})`),
313
+ );
314
+
315
+ // 6) Polygon area equals (n/2)·sin(2π/n)
316
+ function polyArea(pts) {
317
+ let s = 0;
318
+ for (let i = 0; i < pts.length; i++) {
319
+ const j = (i + 1) % pts.length;
320
+ s += pts[i].re * pts[j].im - pts[j].re * pts[i].im;
321
+ }
322
+ return Math.abs(s) / 2;
323
+ }
324
+ const A = polyArea(roots);
325
+ const Aexp = 0.5 * n * Math.sin((2 * Math.PI) / n);
326
+ const areaOK = Math.abs(A - Aexp) < 1e-10;
327
+ checks.insertAdjacentHTML(
328
+ 'beforeend',
329
+ areaOK
330
+ ? ok('Polygon area matches A = (n/2)·sin(2π/n)')
331
+ : bad(`Area mismatch: got ${A.toFixed(12)}, expected ${Aexp.toFixed(12)}`),
332
+ );
333
+
334
+ // 7) DFT property: for 1 ≤ m ≤ n−1, Σ z_k^m = 0
335
+ let dftOK = true;
336
+ let firstBad = null;
337
+ for (let m = 1; m < n; m++) {
338
+ let acc = { re: 0, im: 0 };
339
+ for (const z of roots) {
340
+ const t = m * Math.atan2(z.im, z.re);
341
+ acc.re += Math.cos(t);
342
+ acc.im += Math.sin(t);
343
+ }
344
+ if (Math.hypot(acc.re, acc.im) > 1e-9) {
345
+ dftOK = false;
346
+ firstBad = m;
347
+ break;
348
+ }
349
+ }
350
+ checks.insertAdjacentHTML(
351
+ 'beforeend',
352
+ dftOK ? ok('DFT sums vanish: Σ z_k^m = 0 for 1 ≤ m ≤ n−1') : bad(`DFT sum failed for m = ${firstBad}`),
353
+ );
354
+
355
+ numbers.textContent = `n = ${n}
356
+ Equal angle step = 2π/n = ${((2 * Math.PI) / n).toFixed(6)} rad
357
+ Chord length = ${chord.toFixed(6)}
358
+ Area (computed) = ${A.toFixed(12)}
359
+ Area (expected) = ${Aexp.toFixed(12)}`;
360
+ })();
361
+ </script>
362
+ </body>
363
+ </html>