eyeling 1.19.5 → 1.19.6
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/examples/deck/extra.md +169 -0
- package/examples/extra/collatz-1000.js +138 -0
- package/examples/extra/control-system.js +68 -0
- package/examples/extra/deep-taxonomy-100000.js +95 -0
- package/examples/extra/delfour.js +110 -0
- package/examples/extra/euler-identity.js +41 -0
- package/examples/extra/fibonacci.js +81 -0
- package/examples/extra/goldbach-1000.js +112 -0
- package/examples/extra/gps.js +274 -0
- package/examples/extra/kaprekar-6174.js +112 -0
- package/examples/extra/matrix-mechanics.js +69 -0
- package/examples/extra/odrl-dpv-ehds-risk-ranked.js +255 -0
- package/examples/extra/output/collatz-1000.txt +18 -0
- package/examples/extra/output/control-system.txt +14 -0
- package/examples/extra/output/deep-taxonomy-100000.txt +15 -0
- package/examples/extra/output/delfour.txt +20 -0
- package/examples/extra/output/euler-identity.txt +12 -0
- package/examples/extra/output/fibonacci.txt +21 -0
- package/examples/extra/output/goldbach-1000.txt +17 -0
- package/examples/extra/output/gps.txt +33 -0
- package/examples/extra/output/kaprekar-6174.txt +17 -0
- package/examples/extra/output/matrix-mechanics.txt +14 -0
- package/examples/extra/output/odrl-dpv-ehds-risk-ranked.txt +48 -0
- package/examples/extra/output/path-discovery.txt +28 -0
- package/examples/extra/output/pn-junction-tunneling.txt +15 -0
- package/examples/extra/output/polynomial.txt +20 -0
- package/examples/extra/output/sudoku.txt +47 -0
- package/examples/extra/output/transistor-switch.txt +16 -0
- package/examples/extra/path-discovery.js +45114 -0
- package/examples/extra/pn-junction-tunneling.js +69 -0
- package/examples/extra/polynomial.js +181 -0
- package/examples/extra/sudoku.js +330 -0
- package/examples/extra/transistor-switch.js +93 -0
- package/package.json +3 -2
- package/test/extra.test.js +100 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Exact Fibonacci benchmark using BigInt throughout.
|
|
6
|
+
* The main path is iterative, while fast doubling is used as an independent cross-check.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
function fibonacciIterative(n) {
|
|
10
|
+
let a = 0n;
|
|
11
|
+
let b = 1n;
|
|
12
|
+
for (let i = 0; i < n; i += 1) {
|
|
13
|
+
const t = a + b;
|
|
14
|
+
a = b;
|
|
15
|
+
b = t;
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Independent cross-check based on the fast-doubling identities.
|
|
21
|
+
function fastDoubling(n) {
|
|
22
|
+
if (n === 0) return [0n, 1n];
|
|
23
|
+
const [a, b] = fastDoubling(Math.floor(n / 2));
|
|
24
|
+
const c = a * (2n * b - a);
|
|
25
|
+
const d = a * a + b * b;
|
|
26
|
+
if (n % 2 === 0) return [c, d];
|
|
27
|
+
return [d, c + d];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Compute the requested values, then verify a few known identities and size facts.
|
|
31
|
+
function main() {
|
|
32
|
+
const targets = [0, 1, 10, 100, 1000, 10000];
|
|
33
|
+
const vals = targets.map((n) => fibonacciIterative(n));
|
|
34
|
+
|
|
35
|
+
const f10Ok = vals[2] === 55n;
|
|
36
|
+
const f1000Str = vals[4].toString();
|
|
37
|
+
const f10000Str = vals[5].toString();
|
|
38
|
+
const f1000Digits = f1000Str.length;
|
|
39
|
+
const f10000Digits = f10000Str.length;
|
|
40
|
+
|
|
41
|
+
let fastOk = true;
|
|
42
|
+
for (let i = 0; i < targets.length; i += 1) {
|
|
43
|
+
const [a] = fastDoubling(targets[i]);
|
|
44
|
+
if (a !== vals[i]) fastOk = false;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const f99 = fibonacciIterative(99);
|
|
48
|
+
const f100 = fibonacciIterative(100);
|
|
49
|
+
const f101 = fibonacciIterative(101);
|
|
50
|
+
const cassiniOk = f101 * f99 === f100 * f100 + 1n;
|
|
51
|
+
const f10000Last3Ok = f10000Str.endsWith('875');
|
|
52
|
+
|
|
53
|
+
const ok = f10Ok && fastOk && cassiniOk && f1000Digits === 209 && f10000Digits === 2090 && f10000Last3Ok;
|
|
54
|
+
|
|
55
|
+
const lines = [];
|
|
56
|
+
lines.push('=== Answer ===');
|
|
57
|
+
lines.push('The requested Fibonacci values are computed exactly, up to F(10000).');
|
|
58
|
+
lines.push('');
|
|
59
|
+
lines.push('=== Reason Why ===');
|
|
60
|
+
lines.push(
|
|
61
|
+
'The main computation uses the defining recurrence F(n+1)=F(n)+F(n-1), and the results are cross-checked with fast doubling.',
|
|
62
|
+
);
|
|
63
|
+
for (let i = 0; i < targets.length; i += 1) {
|
|
64
|
+
lines.push(`value[${i}] : F(${targets[i]}) = ${vals[i].toString()}`);
|
|
65
|
+
}
|
|
66
|
+
lines.push(`digits in F(1000) : ${f1000Digits}`);
|
|
67
|
+
lines.push(`digits in F(10000) : ${f10000Digits}`);
|
|
68
|
+
lines.push('');
|
|
69
|
+
lines.push('=== Check ===');
|
|
70
|
+
lines.push(`F(10) = 55 : ${f10Ok ? 'yes' : 'no'}`);
|
|
71
|
+
lines.push(`fast doubling agrees : ${fastOk ? 'yes' : 'no'}`);
|
|
72
|
+
lines.push(`Cassini at n=100 : ${cassiniOk ? 'yes' : 'no'}`);
|
|
73
|
+
lines.push(`F(1000) has 209 digits: ${f1000Digits === 209 ? 'yes' : 'no'}`);
|
|
74
|
+
lines.push(`F(10000) has 2090 digits: ${f10000Digits === 2090 ? 'yes' : 'no'}`);
|
|
75
|
+
lines.push(`F(10000) ends in 875 : ${f10000Last3Ok ? 'yes' : 'no'}`);
|
|
76
|
+
|
|
77
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
78
|
+
process.exit(ok ? 0 : 1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
main();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Goldbach sweep for all even targets up to 1000.
|
|
6
|
+
* A sieve provides the prime table; the report summarizes sparse, rich, and balanced decompositions.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const LIMIT = 1000;
|
|
10
|
+
|
|
11
|
+
function sieve(limit) {
|
|
12
|
+
const prime = new Array(limit + 1).fill(true);
|
|
13
|
+
prime[0] = false;
|
|
14
|
+
prime[1] = false;
|
|
15
|
+
for (let p = 2; p * p <= limit; p += 1) {
|
|
16
|
+
if (!prime[p]) continue;
|
|
17
|
+
for (let m = p * p; m <= limit; m += p) prime[m] = false;
|
|
18
|
+
}
|
|
19
|
+
return prime;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function collectPrimes(prime, limit) {
|
|
23
|
+
const out = [];
|
|
24
|
+
for (let i = 2; i <= limit; i += 1) if (prime[i]) out.push(i);
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function goldbachPairs(target, primes, prime) {
|
|
29
|
+
let count = 0;
|
|
30
|
+
for (const p of primes) {
|
|
31
|
+
if (p > Math.floor(target / 2)) break;
|
|
32
|
+
const q = target - p;
|
|
33
|
+
if (prime[q]) count += 1;
|
|
34
|
+
}
|
|
35
|
+
return count;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Sweep the entire range and summarize the decomposition counts.
|
|
39
|
+
function main() {
|
|
40
|
+
const prime = sieve(LIMIT);
|
|
41
|
+
const primes = collectPrimes(prime, LIMIT);
|
|
42
|
+
|
|
43
|
+
let totalDecompositions = 0;
|
|
44
|
+
let fewest = Number.MAX_SAFE_INTEGER;
|
|
45
|
+
let most = 0;
|
|
46
|
+
let richestTarget = 4;
|
|
47
|
+
const hardest = [];
|
|
48
|
+
let allRepresented = true;
|
|
49
|
+
|
|
50
|
+
for (let target = 4; target <= LIMIT; target += 2) {
|
|
51
|
+
const count = goldbachPairs(target, primes, prime);
|
|
52
|
+
totalDecompositions += count;
|
|
53
|
+
if (count === 0) allRepresented = false;
|
|
54
|
+
if (count < fewest) {
|
|
55
|
+
fewest = count;
|
|
56
|
+
hardest.length = 0;
|
|
57
|
+
hardest.push(target);
|
|
58
|
+
} else if (count === fewest) {
|
|
59
|
+
hardest.push(target);
|
|
60
|
+
}
|
|
61
|
+
if (count > most) {
|
|
62
|
+
most = count;
|
|
63
|
+
richestTarget = target;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let bestA = 0;
|
|
68
|
+
let bestB = 0;
|
|
69
|
+
let bestDiff = Number.MAX_SAFE_INTEGER;
|
|
70
|
+
for (const p of primes) {
|
|
71
|
+
if (p > LIMIT / 2) break;
|
|
72
|
+
const q = LIMIT - p;
|
|
73
|
+
if (prime[q] && q >= p) {
|
|
74
|
+
const diff = q - p;
|
|
75
|
+
if (diff < bestDiff) {
|
|
76
|
+
bestDiff = diff;
|
|
77
|
+
bestA = p;
|
|
78
|
+
bestB = q;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const primeCountOk = primes.length === 168;
|
|
84
|
+
const balancedPairOk = bestA + bestB === LIMIT && prime[bestA] && prime[bestB];
|
|
85
|
+
const ok = allRepresented && primeCountOk && balancedPairOk;
|
|
86
|
+
|
|
87
|
+
const lines = [];
|
|
88
|
+
lines.push('=== Answer ===');
|
|
89
|
+
lines.push('Every even integer from 4 through 1000 has at least one Goldbach decomposition in the tested range.');
|
|
90
|
+
lines.push('');
|
|
91
|
+
lines.push('=== Reason Why ===');
|
|
92
|
+
lines.push(
|
|
93
|
+
'The program builds a prime table, enumerates unordered pairs p+q=n for each even target, and summarizes sparse and rich cases.',
|
|
94
|
+
);
|
|
95
|
+
lines.push(`even targets checked : ${(LIMIT - 4) / 2 + 1}`);
|
|
96
|
+
lines.push(`total decompositions : ${totalDecompositions}`);
|
|
97
|
+
lines.push(`fewest decompositions: ${fewest}`);
|
|
98
|
+
lines.push(`hardest targets : ${hardest.join(', ')}`);
|
|
99
|
+
lines.push(`most decompositions : ${most}`);
|
|
100
|
+
lines.push(`richest target : ${richestTarget}`);
|
|
101
|
+
lines.push(`balanced pair(1000) : ${bestA} + ${bestB}`);
|
|
102
|
+
lines.push('');
|
|
103
|
+
lines.push('=== Check ===');
|
|
104
|
+
lines.push(`all represented : ${allRepresented ? 'yes' : 'no'}`);
|
|
105
|
+
lines.push(`prime count known : ${primeCountOk ? 'yes' : 'no'}`);
|
|
106
|
+
lines.push(`balanced pair valid : ${balancedPairOk ? 'yes' : 'no'}`);
|
|
107
|
+
|
|
108
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
main();
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Small route-planning case with fixed legs, costs, and trust-style metrics.
|
|
6
|
+
* Routes are composed forward from the primitive descriptions and then filtered by the goal constraints.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const CITY = {
|
|
10
|
+
GENT: 0,
|
|
11
|
+
BRUGGE: 1,
|
|
12
|
+
KORTRIJK: 2,
|
|
13
|
+
OOSTENDE: 3,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const ACTION = {
|
|
17
|
+
DRIVE_GENT_BRUGGE: 0,
|
|
18
|
+
DRIVE_GENT_KORTRIJK: 1,
|
|
19
|
+
DRIVE_KORTRIJK_BRUGGE: 2,
|
|
20
|
+
DRIVE_BRUGGE_OOSTENDE: 3,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Primitive route descriptions: each one is a direct edge with its accumulated metrics.
|
|
24
|
+
const DESCRIPTIONS = [
|
|
25
|
+
{
|
|
26
|
+
from: CITY.GENT,
|
|
27
|
+
to: CITY.BRUGGE,
|
|
28
|
+
action: ACTION.DRIVE_GENT_BRUGGE,
|
|
29
|
+
durationSeconds: 1500,
|
|
30
|
+
costMilli: 6,
|
|
31
|
+
beliefPpm: 960000,
|
|
32
|
+
comfortPpm: 990000,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
from: CITY.GENT,
|
|
36
|
+
to: CITY.KORTRIJK,
|
|
37
|
+
action: ACTION.DRIVE_GENT_KORTRIJK,
|
|
38
|
+
durationSeconds: 1600,
|
|
39
|
+
costMilli: 7,
|
|
40
|
+
beliefPpm: 960000,
|
|
41
|
+
comfortPpm: 990000,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
from: CITY.KORTRIJK,
|
|
45
|
+
to: CITY.BRUGGE,
|
|
46
|
+
action: ACTION.DRIVE_KORTRIJK_BRUGGE,
|
|
47
|
+
durationSeconds: 1600,
|
|
48
|
+
costMilli: 7,
|
|
49
|
+
beliefPpm: 960000,
|
|
50
|
+
comfortPpm: 990000,
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
from: CITY.BRUGGE,
|
|
54
|
+
to: CITY.OOSTENDE,
|
|
55
|
+
action: ACTION.DRIVE_BRUGGE_OOSTENDE,
|
|
56
|
+
durationSeconds: 900,
|
|
57
|
+
costMilli: 4,
|
|
58
|
+
beliefPpm: 980000,
|
|
59
|
+
comfortPpm: 1000000,
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const GOAL = {
|
|
64
|
+
maxDurationSeconds: 5000,
|
|
65
|
+
maxCostMilli: 5000,
|
|
66
|
+
minBeliefPpm: 200000,
|
|
67
|
+
minComfortPpm: 400000,
|
|
68
|
+
maxStages: 1,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function multiplyPpm(left, right) {
|
|
72
|
+
return Math.floor((left * right) / 1000000);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function actionName(action) {
|
|
76
|
+
switch (action) {
|
|
77
|
+
case ACTION.DRIVE_GENT_BRUGGE:
|
|
78
|
+
return 'drive_gent_brugge';
|
|
79
|
+
case ACTION.DRIVE_GENT_KORTRIJK:
|
|
80
|
+
return 'drive_gent_kortrijk';
|
|
81
|
+
case ACTION.DRIVE_KORTRIJK_BRUGGE:
|
|
82
|
+
return 'drive_kortrijk_brugge';
|
|
83
|
+
case ACTION.DRIVE_BRUGGE_OOSTENDE:
|
|
84
|
+
return 'drive_brugge_oostende';
|
|
85
|
+
default:
|
|
86
|
+
return '?';
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function stageCount(route) {
|
|
91
|
+
return route.actions.length > 0 ? 1 : 0;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function routeSatisfies(route, c) {
|
|
95
|
+
return (
|
|
96
|
+
route.durationSeconds <= c.maxDurationSeconds &&
|
|
97
|
+
route.costMilli <= c.maxCostMilli &&
|
|
98
|
+
route.beliefPpm >= c.minBeliefPpm &&
|
|
99
|
+
route.comfortPpm >= c.minComfortPpm &&
|
|
100
|
+
stageCount(route) <= c.maxStages
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function routeEquals(a, b) {
|
|
105
|
+
return (
|
|
106
|
+
a.from === b.from &&
|
|
107
|
+
a.to === b.to &&
|
|
108
|
+
a.actions.length === b.actions.length &&
|
|
109
|
+
a.durationSeconds === b.durationSeconds &&
|
|
110
|
+
a.costMilli === b.costMilli &&
|
|
111
|
+
a.beliefPpm === b.beliefPpm &&
|
|
112
|
+
a.comfortPpm === b.comfortPpm &&
|
|
113
|
+
a.actions.every((action, i) => action === b.actions[i])
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function compareRoutes(left, right) {
|
|
118
|
+
if (left.actions.length < right.actions.length) return -1;
|
|
119
|
+
if (left.actions.length > right.actions.length) return 1;
|
|
120
|
+
for (let i = 0; i < left.actions.length && i < right.actions.length; i += 1) {
|
|
121
|
+
if (left.actions[i] < right.actions[i]) return -1;
|
|
122
|
+
if (left.actions[i] > right.actions[i]) return 1;
|
|
123
|
+
}
|
|
124
|
+
return 0;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function routeMatchesDescriptions(route) {
|
|
128
|
+
let current = route.from;
|
|
129
|
+
let durationSeconds = 0;
|
|
130
|
+
let costMilli = 0;
|
|
131
|
+
let beliefPpm = 1000000;
|
|
132
|
+
let comfortPpm = 1000000;
|
|
133
|
+
|
|
134
|
+
for (const action of route.actions) {
|
|
135
|
+
let found = false;
|
|
136
|
+
for (const d of DESCRIPTIONS) {
|
|
137
|
+
if (d.from === current && d.action === action) {
|
|
138
|
+
current = d.to;
|
|
139
|
+
durationSeconds += d.durationSeconds;
|
|
140
|
+
costMilli += d.costMilli;
|
|
141
|
+
beliefPpm = multiplyPpm(beliefPpm, d.beliefPpm);
|
|
142
|
+
comfortPpm = multiplyPpm(comfortPpm, d.comfortPpm);
|
|
143
|
+
found = true;
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (!found) return false;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return (
|
|
151
|
+
current === route.to &&
|
|
152
|
+
durationSeconds === route.durationSeconds &&
|
|
153
|
+
costMilli === route.costMilli &&
|
|
154
|
+
beliefPpm === route.beliefPpm &&
|
|
155
|
+
comfortPpm === route.comfortPpm
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Compose longer routes from the primitive descriptions until no new route appears.
|
|
160
|
+
function inferGoalRoutes() {
|
|
161
|
+
const known = [];
|
|
162
|
+
let agendaHead = 0;
|
|
163
|
+
|
|
164
|
+
for (const d of DESCRIPTIONS) {
|
|
165
|
+
known.push({
|
|
166
|
+
from: d.from,
|
|
167
|
+
to: d.to,
|
|
168
|
+
actions: [d.action],
|
|
169
|
+
durationSeconds: d.durationSeconds,
|
|
170
|
+
costMilli: d.costMilli,
|
|
171
|
+
beliefPpm: d.beliefPpm,
|
|
172
|
+
comfortPpm: d.comfortPpm,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
while (agendaHead < known.length) {
|
|
177
|
+
const rest = known[agendaHead++];
|
|
178
|
+
for (const d of DESCRIPTIONS) {
|
|
179
|
+
if (d.to === rest.from) {
|
|
180
|
+
const route = {
|
|
181
|
+
from: d.from,
|
|
182
|
+
to: rest.to,
|
|
183
|
+
actions: [d.action, ...rest.actions],
|
|
184
|
+
durationSeconds: d.durationSeconds + rest.durationSeconds,
|
|
185
|
+
costMilli: d.costMilli + rest.costMilli,
|
|
186
|
+
beliefPpm: multiplyPpm(d.beliefPpm, rest.beliefPpm),
|
|
187
|
+
comfortPpm: multiplyPpm(d.comfortPpm, rest.comfortPpm),
|
|
188
|
+
};
|
|
189
|
+
let duplicate = false;
|
|
190
|
+
for (const knownRoute of known) {
|
|
191
|
+
if (routeEquals(knownRoute, route)) {
|
|
192
|
+
duplicate = true;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (!duplicate) known.push(route);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
return known
|
|
202
|
+
.filter((route) => route.from === CITY.GENT && route.to === CITY.OOSTENDE && routeSatisfies(route, GOAL))
|
|
203
|
+
.sort(compareRoutes);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function formatDecimal(value, scale, digits) {
|
|
207
|
+
const fractionalScale = 10 ** digits;
|
|
208
|
+
const scaled = value * fractionalScale;
|
|
209
|
+
const rounded = Math.floor((scaled + Math.floor(scale / 2)) / scale);
|
|
210
|
+
const whole = Math.floor(rounded / fractionalScale);
|
|
211
|
+
const fractional = rounded % fractionalScale;
|
|
212
|
+
return `${whole}.${String(fractional).padStart(digits, '0')}`;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function routeLines(index, route) {
|
|
216
|
+
const lines = [];
|
|
217
|
+
lines.push(`Route #${index}`);
|
|
218
|
+
lines.push(` Steps : ${route.actions.length}`);
|
|
219
|
+
lines.push(` Duration : ${route.durationSeconds} s (≤ ${GOAL.maxDurationSeconds})`);
|
|
220
|
+
lines.push(` Cost : ${formatDecimal(route.costMilli, 1000, 3)} (≤ ${formatDecimal(GOAL.maxCostMilli, 1000, 1)})`);
|
|
221
|
+
lines.push(
|
|
222
|
+
` Belief : ${formatDecimal(route.beliefPpm, 1000000, 3)} (≥ ${formatDecimal(GOAL.minBeliefPpm, 1000000, 1)})`,
|
|
223
|
+
);
|
|
224
|
+
lines.push(
|
|
225
|
+
` Comfort : ${formatDecimal(route.comfortPpm, 1000000, 3)} (≥ ${formatDecimal(GOAL.minComfortPpm, 1000000, 1)})`,
|
|
226
|
+
);
|
|
227
|
+
lines.push(` Stages : ${stageCount(route)} (≤ ${GOAL.maxStages})`);
|
|
228
|
+
for (let i = 0; i < route.actions.length; i += 1) {
|
|
229
|
+
lines.push(` ${i + 1}. ${actionName(route.actions[i])}`);
|
|
230
|
+
}
|
|
231
|
+
return lines;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Emit every route that satisfies the fixed Gent -> Oostende goal.
|
|
235
|
+
function main() {
|
|
236
|
+
const routes = inferGoalRoutes();
|
|
237
|
+
|
|
238
|
+
let allRoutesSatisfyConstraints = true;
|
|
239
|
+
let allRoutesHitGoalEndpoints = true;
|
|
240
|
+
let allMetricsRecompute = true;
|
|
241
|
+
for (const route of routes) {
|
|
242
|
+
allRoutesSatisfyConstraints &&= routeSatisfies(route, GOAL);
|
|
243
|
+
allRoutesHitGoalEndpoints &&= route.from === CITY.GENT && route.to === CITY.OOSTENDE;
|
|
244
|
+
allMetricsRecompute &&= routeMatchesDescriptions(route);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const ok = routes.length === 2 && allRoutesSatisfyConstraints && allRoutesHitGoalEndpoints && allMetricsRecompute;
|
|
248
|
+
|
|
249
|
+
const lines = [];
|
|
250
|
+
lines.push('=== Answer ===');
|
|
251
|
+
lines.push('The GPS case finds all goal routes from Gent to Oostende that satisfy the route constraints.');
|
|
252
|
+
lines.push('case : gps');
|
|
253
|
+
lines.push(`routes : ${routes.length}`);
|
|
254
|
+
lines.push('');
|
|
255
|
+
lines.push('=== Reason Why ===');
|
|
256
|
+
lines.push(
|
|
257
|
+
'Routes are built compositionally from direct descriptions, with duration and cost added and belief and comfort combined multiplicatively.',
|
|
258
|
+
);
|
|
259
|
+
for (let i = 0; i < routes.length; i += 1) {
|
|
260
|
+
lines.push(...routeLines(i + 1, routes[i]));
|
|
261
|
+
if (i + 1 !== routes.length) lines.push('');
|
|
262
|
+
}
|
|
263
|
+
lines.push('');
|
|
264
|
+
lines.push('=== Check ===');
|
|
265
|
+
lines.push(`all routes satisfy constraints : ${allRoutesSatisfyConstraints ? 'yes' : 'no'}`);
|
|
266
|
+
lines.push(`all routes hit goal endpoints : ${allRoutesHitGoalEndpoints ? 'yes' : 'no'}`);
|
|
267
|
+
lines.push(`metrics recompute from steps : ${allMetricsRecompute ? 'yes' : 'no'}`);
|
|
268
|
+
lines.push(`expected route count (= 2) : ${routes.length === 2 ? 'yes' : 'no'}`);
|
|
269
|
+
|
|
270
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
271
|
+
process.exit(ok ? 0 : 1);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
main();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Kaprekar 6174 exploration over all admissible four-digit starts.
|
|
6
|
+
* The script records traces, a convergence histogram, and a few representative witnesses.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
function digits4(n) {
|
|
10
|
+
return [Math.floor(n / 1000) % 10, Math.floor(n / 100) % 10, Math.floor(n / 10) % 10, n % 10];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function sort4(digits, descending) {
|
|
14
|
+
digits.sort((a, b) => (descending ? b - a : a - b));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function build4(d) {
|
|
18
|
+
return d[0] * 1000 + d[1] * 100 + d[2] * 10 + d[3];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function hasTwoDistinctDigits(n) {
|
|
22
|
+
const d = digits4(n);
|
|
23
|
+
for (let i = 1; i < 4; i += 1) if (d[i] !== d[0]) return true;
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function kaprekarStep(n) {
|
|
28
|
+
const hi = digits4(n);
|
|
29
|
+
const lo = [...hi];
|
|
30
|
+
sort4(hi, true);
|
|
31
|
+
sort4(lo, false);
|
|
32
|
+
return build4(hi) - build4(lo);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function kaprekarTrace(start, cap) {
|
|
36
|
+
const out = [];
|
|
37
|
+
let cur = start;
|
|
38
|
+
while (out.length < cap) {
|
|
39
|
+
out.push(cur);
|
|
40
|
+
if (cur === 6174) break;
|
|
41
|
+
cur = kaprekarStep(cur);
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function fmt4(n) {
|
|
47
|
+
return String(n).padStart(4, '0');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Explore the full start space and then print a compact convergence summary.
|
|
51
|
+
function main() {
|
|
52
|
+
let validStarts = 0;
|
|
53
|
+
let repdigits = 0;
|
|
54
|
+
let maxIterations = 0;
|
|
55
|
+
let worstCaseStarts = 0;
|
|
56
|
+
const hist = new Array(8).fill(0);
|
|
57
|
+
let worstTrace = [];
|
|
58
|
+
const leadingTrace = kaprekarTrace(2111, 16);
|
|
59
|
+
let allReach = true;
|
|
60
|
+
let boundOk = true;
|
|
61
|
+
|
|
62
|
+
for (let start = 0; start <= 9999; start += 1) {
|
|
63
|
+
if (!hasTwoDistinctDigits(start)) {
|
|
64
|
+
repdigits += 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const trace = kaprekarTrace(start, 16);
|
|
68
|
+
const steps = trace.length ? trace.length - 1 : 0;
|
|
69
|
+
validStarts += 1;
|
|
70
|
+
if (trace[trace.length - 1] !== 6174) allReach = false;
|
|
71
|
+
if (steps > 7) boundOk = false;
|
|
72
|
+
if (steps < 8) hist[steps] += 1;
|
|
73
|
+
if (steps > maxIterations) {
|
|
74
|
+
maxIterations = steps;
|
|
75
|
+
worstCaseStarts = 1;
|
|
76
|
+
worstTrace = trace.slice();
|
|
77
|
+
} else if (steps === maxIterations) {
|
|
78
|
+
worstCaseStarts += 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const fixedPointOk = kaprekarStep(6174) === 6174;
|
|
83
|
+
const histTotal = hist.reduce((sum, n) => sum + n, 0);
|
|
84
|
+
const histogramOk = histTotal === validStarts;
|
|
85
|
+
const ok = fixedPointOk && allReach && boundOk && histogramOk;
|
|
86
|
+
|
|
87
|
+
const lines = [];
|
|
88
|
+
lines.push('=== Answer ===');
|
|
89
|
+
lines.push('Every valid four-digit start tested reaches 6174, and all of them do so within seven iterations.');
|
|
90
|
+
lines.push('');
|
|
91
|
+
lines.push('=== Reason Why ===');
|
|
92
|
+
lines.push(
|
|
93
|
+
"The program applies Kaprekar's routine to every non-repdigit start, records the iteration count, and keeps witness traces.",
|
|
94
|
+
);
|
|
95
|
+
lines.push(`valid starts checked: ${validStarts}`);
|
|
96
|
+
lines.push(`repdigits excluded : ${repdigits}`);
|
|
97
|
+
lines.push(`max iterations : ${maxIterations}`);
|
|
98
|
+
lines.push(`worst-case starts : ${worstCaseStarts}`);
|
|
99
|
+
lines.push(`worst trace : ${worstTrace.map(fmt4).join(' -> ')}`);
|
|
100
|
+
lines.push(`leading-zero trace : ${leadingTrace.map(fmt4).join(' -> ')}`);
|
|
101
|
+
lines.push('');
|
|
102
|
+
lines.push('=== Check ===');
|
|
103
|
+
lines.push(`6174 fixed point : ${fixedPointOk ? 'yes' : 'no'}`);
|
|
104
|
+
lines.push(`all starts reach it : ${allReach ? 'yes' : 'no'}`);
|
|
105
|
+
lines.push(`bound <= 7 verified : ${boundOk ? 'yes' : 'no'}`);
|
|
106
|
+
lines.push(`histogram total ok : ${histogramOk ? 'yes' : 'no'}`);
|
|
107
|
+
|
|
108
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
109
|
+
process.exit(ok ? 0 : 1);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
main();
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Toy matrix-mechanics example over 2x2 matrices.
|
|
6
|
+
* It highlights spectrum, involution, and a non-zero commutator in a compact exact model.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
function m2(a11, a12, a21, a22) {
|
|
10
|
+
return { a11, a12, a21, a22 };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function mul(a, b) {
|
|
14
|
+
return m2(
|
|
15
|
+
a.a11 * b.a11 + a.a12 * b.a21,
|
|
16
|
+
a.a11 * b.a12 + a.a12 * b.a22,
|
|
17
|
+
a.a21 * b.a11 + a.a22 * b.a21,
|
|
18
|
+
a.a21 * b.a12 + a.a22 * b.a22,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function sub(a, b) {
|
|
23
|
+
return m2(a.a11 - b.a11, a.a12 - b.a12, a.a21 - b.a21, a.a22 - b.a22);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function trace(a) {
|
|
27
|
+
return a.a11 + a.a22;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function det(a) {
|
|
31
|
+
return a.a11 * a.a22 - a.a12 * a.a21;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Evaluate the tiny model exactly, then verify the expected algebraic properties.
|
|
35
|
+
function main() {
|
|
36
|
+
const H = m2(1, 0, 0, 2);
|
|
37
|
+
const X = m2(0, 1, 1, 0);
|
|
38
|
+
const HX = mul(H, X);
|
|
39
|
+
const XH = mul(X, H);
|
|
40
|
+
const C = sub(HX, XH);
|
|
41
|
+
const commutatorNonzero = !!(C.a11 || C.a12 || C.a21 || C.a22);
|
|
42
|
+
const spectrumOk = trace(H) === 3 && det(H) === 2;
|
|
43
|
+
const XX = mul(X, X);
|
|
44
|
+
const involution = XX.a11 === 1 && XX.a12 === 0 && XX.a21 === 0 && XX.a22 === 1;
|
|
45
|
+
const ok = spectrumOk && involution && commutatorNonzero;
|
|
46
|
+
|
|
47
|
+
const lines = [];
|
|
48
|
+
lines.push('=== Answer ===');
|
|
49
|
+
lines.push(
|
|
50
|
+
'In this toy matrix-mechanics model, the Hamiltonian has two discrete energy levels and does not commute with a second observable.',
|
|
51
|
+
);
|
|
52
|
+
lines.push('');
|
|
53
|
+
lines.push('=== Reason Why ===');
|
|
54
|
+
lines.push(`H = [[${H.a11},${H.a12}],[${H.a21},${H.a22}]]`);
|
|
55
|
+
lines.push(`X = [[${X.a11},${X.a12}],[${X.a21},${X.a22}]]`);
|
|
56
|
+
lines.push(`HX = [[${HX.a11},${HX.a12}],[${HX.a21},${HX.a22}]]`);
|
|
57
|
+
lines.push(`XH = [[${XH.a11},${XH.a12}],[${XH.a21},${XH.a22}]]`);
|
|
58
|
+
lines.push(`[H,X] = [[${C.a11},${C.a12}],[${C.a21},${C.a22}]]`);
|
|
59
|
+
lines.push('');
|
|
60
|
+
lines.push('=== Check ===');
|
|
61
|
+
lines.push(`trace/determinant match energy levels: ${spectrumOk ? 'yes' : 'no'}`);
|
|
62
|
+
lines.push(`X^2 = I : ${involution ? 'yes' : 'no'}`);
|
|
63
|
+
lines.push(`[H,X] != 0 : ${commutatorNonzero ? 'yes' : 'no'}`);
|
|
64
|
+
|
|
65
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
66
|
+
process.exit(ok ? 0 : 1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main();
|