eyeprolog 1.3.18 → 1.3.20
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 +1 -1
- package/examples/clpz-n-queens.pl +10 -3
- package/examples/observability-log-correlation.pl +9 -2
- package/examples/output/clpz-n-queens.pl +3 -4
- package/package.json +1 -1
- package/playground.html +0 -2
- package/test/run-interop.mjs +8 -8
- package/test/run-regression.mjs +24 -12
- package/the-art-of-eyeprolog.md +8 -10
- package/examples/n-queens.pl +0 -36
- package/examples/output/n-queens.pl +0 -92
- package/examples/output/sudoku.pl +0 -1
- package/examples/sudoku.pl +0 -113
package/README.md
CHANGED
|
@@ -292,7 +292,7 @@ npm run test:interop
|
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
The GitHub interoperability workflow builds both implementations and runs the
|
|
295
|
-
same portable
|
|
295
|
+
same portable Towers of Hanoi source under EyeProlog, Trealla, and Scryer.
|
|
296
296
|
|
|
297
297
|
## Development
|
|
298
298
|
|
|
@@ -4,11 +4,19 @@
|
|
|
4
4
|
% The list position is a column and its value is a row. Domains, global
|
|
5
5
|
% distinctness, and delayed diagonal constraints describe the puzzle before
|
|
6
6
|
% labeling searches the remaining finite alternatives.
|
|
7
|
+
%
|
|
8
|
+
% The main example records one witness for the classic eight-queens problem.
|
|
9
|
+
% A smaller four-queens query also checks that queens/2 still enumerates
|
|
10
|
+
% multiple solutions without carrying a 92-answer golden file.
|
|
7
11
|
|
|
8
|
-
%% goal:
|
|
12
|
+
%% goal: queens8_solution(X0)
|
|
13
|
+
%% goal: queens(4, X0)
|
|
14
|
+
|
|
15
|
+
queens8_solution(Rows) :-
|
|
16
|
+
queens(8, Rows),
|
|
17
|
+
!.
|
|
9
18
|
|
|
10
19
|
queens(Size, Rows) :-
|
|
11
|
-
Size = 6,
|
|
12
20
|
length(Rows, Size),
|
|
13
21
|
Rows ins 1..Size,
|
|
14
22
|
all_distinct(Rows),
|
|
@@ -26,4 +34,3 @@ safe_from(Row, [Other|Rows], Distance) :-
|
|
|
26
34
|
Row #\= Other - Distance,
|
|
27
35
|
NextDistance is Distance + 1,
|
|
28
36
|
safe_from(Row, Rows, NextDistance).
|
|
29
|
-
|
|
@@ -20,10 +20,17 @@ raw_log(l2, 'ts=2026-06-18T10:00:03Z level=error event=payment_denied user=alice
|
|
|
20
20
|
raw_log(l3, 'ts=2026-06-18T10:01:12Z level=info event=login_success user=bob ip=198.51.100.4 traceparent=00-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-bbbbbbbbbbbbbbbb-01').
|
|
21
21
|
raw_log(noise, 'healthcheck ok').
|
|
22
22
|
|
|
23
|
+
% Walk the batch recursively so EyeProlog can table parsed_logs/3 and reuse
|
|
24
|
+
% each regex parse across the captured-field, event, and alert queries.
|
|
23
25
|
parsed(Log, Context) :-
|
|
24
|
-
raw_log(
|
|
26
|
+
findall(raw(Log0, Text), raw_log(Log0, Text), Logs),
|
|
27
|
+
parsed_logs(Logs, Log, Context).
|
|
28
|
+
|
|
29
|
+
parsed_logs([raw(Log, Text)|_], Log, Context) :-
|
|
25
30
|
log_pattern(Pattern),
|
|
26
31
|
matches(Text, Pattern, Context).
|
|
32
|
+
parsed_logs([_|Logs], Log, Context) :-
|
|
33
|
+
parsed_logs(Logs, Log, Context).
|
|
27
34
|
|
|
28
35
|
context_member((Left, _right), Member) :- context_member(Left, Member).
|
|
29
36
|
context_member((_left, Right), Member) :- context_member(Right, Member).
|
|
@@ -46,4 +53,4 @@ parsed_event(Log, Event, User, Ip, Traceid) :-
|
|
|
46
53
|
trace_alert(User, Traceid, Ip) :-
|
|
47
54
|
parsed_event(Loginlog, 'login_failed', User, Ip, Traceid),
|
|
48
55
|
parsed_event(Paymentlog, 'payment_denied', User, Ip, Traceid),
|
|
49
|
-
|
|
56
|
+
Loginlog \= Paymentlog.
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
queens(
|
|
3
|
-
queens(
|
|
4
|
-
queens(6, [5, 3, 1, 6, 4, 2]).
|
|
1
|
+
queens8_solution([1, 5, 8, 6, 3, 7, 2, 4]).
|
|
2
|
+
queens(4, [2, 4, 1, 3]).
|
|
3
|
+
queens(4, [3, 1, 4, 2]).
|
package/package.json
CHANGED
package/playground.html
CHANGED
|
@@ -577,7 +577,6 @@
|
|
|
577
577
|
"modal-logic-kripke",
|
|
578
578
|
"modular-exponentiation",
|
|
579
579
|
"monkey-bananas",
|
|
580
|
-
"n-queens",
|
|
581
580
|
"network-sla",
|
|
582
581
|
"newton-raphson",
|
|
583
582
|
"nixon-diamond",
|
|
@@ -629,7 +628,6 @@
|
|
|
629
628
|
"stable-marriage",
|
|
630
629
|
"statistics-summary",
|
|
631
630
|
"stirling-bell-numbers",
|
|
632
|
-
"sudoku",
|
|
633
631
|
"superdense-coding",
|
|
634
632
|
"symbolic-derivative",
|
|
635
633
|
"takeuchi",
|
package/test/run-interop.mjs
CHANGED
|
@@ -11,25 +11,25 @@ import { fileURLToPath } from 'node:url';
|
|
|
11
11
|
|
|
12
12
|
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
13
13
|
const allowMissing = process.argv.includes('--allow-missing');
|
|
14
|
-
const
|
|
15
|
-
const goal = '
|
|
16
|
-
const expected = '[[
|
|
14
|
+
const hanoi = path.join(root, 'examples', 'hanoi.pl');
|
|
15
|
+
const goal = 'hanoi(3,left,right,center,Moves), write(Moves), nl, halt';
|
|
16
|
+
const expected = '[[left,right],[left,center],[right,center],[left,right],[center,left],[center,right],[left,right]]';
|
|
17
17
|
|
|
18
18
|
const engines = [
|
|
19
19
|
{
|
|
20
20
|
name: 'EyeProlog',
|
|
21
21
|
command: process.execPath,
|
|
22
|
-
args: [path.join(root, 'bin', 'eyeprolog.js'), '--portable', '-g', goal,
|
|
22
|
+
args: [path.join(root, 'bin', 'eyeprolog.js'), '--portable', '-g', goal, hanoi],
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
name: 'Trealla',
|
|
26
26
|
command: process.env.TPL ?? 'tpl',
|
|
27
|
-
args: ['-q', '-g', goal,
|
|
27
|
+
args: ['-q', '-g', goal, hanoi],
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
name: 'Scryer',
|
|
31
31
|
command: process.env.SCRYER_PROLOG ?? 'scryer-prolog',
|
|
32
|
-
args: ['-f', '-g', goal,
|
|
32
|
+
args: ['-f', '-g', goal, hanoi],
|
|
33
33
|
},
|
|
34
34
|
];
|
|
35
35
|
|
|
@@ -64,13 +64,13 @@ for (const engine of engines) {
|
|
|
64
64
|
}
|
|
65
65
|
const lines = String(result.stdout ?? '').split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
66
66
|
if (!lines.includes(expected)) {
|
|
67
|
-
console.error(`FAIL ${engine.name}:
|
|
67
|
+
console.error(`FAIL ${engine.name}: Hanoi output mismatch`);
|
|
68
68
|
console.error(`stdout: ${JSON.stringify(result.stdout)}`);
|
|
69
69
|
if (result.stderr) console.error(`stderr: ${result.stderr.trim()}`);
|
|
70
70
|
failed = true;
|
|
71
71
|
continue;
|
|
72
72
|
}
|
|
73
|
-
console.log(`OK ${engine.name}: portable
|
|
73
|
+
console.log(`OK ${engine.name}: portable Hanoi`);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
if (failed) process.exitCode = 1;
|
package/test/run-regression.mjs
CHANGED
|
@@ -2189,7 +2189,7 @@ child.stdin.write(\`consult(${consultedAtom}).\\n\`);
|
|
|
2189
2189
|
{
|
|
2190
2190
|
name: 'npm exec can run package CLI bin from checkout',
|
|
2191
2191
|
run: () => {
|
|
2192
|
-
const result = spawnSync('npm', ['exec', '--loglevel=silent', '--yes', '--package=.', '--', 'eyeprolog', '--version'], {
|
|
2192
|
+
const result = spawnSync('npm', ['exec', '--offline', '--loglevel=silent', '--yes', '--package=.', '--', 'eyeprolog', '--version'], {
|
|
2193
2193
|
cwd: packageRoot,
|
|
2194
2194
|
encoding: 'utf8',
|
|
2195
2195
|
env: { ...process.env, npm_config_update_notifier: 'false' },
|
|
@@ -3797,30 +3797,30 @@ answer(ok) :-
|
|
|
3797
3797
|
`;
|
|
3798
3798
|
const script = `
|
|
3799
3799
|
import { Program, Solver, Env, parseGoalText, getEyePrologRegistry } from ${JSON.stringify(engineUrl)};
|
|
3800
|
-
const program = Program.parse(${JSON.stringify(programText)}, { autoloadGoals: ['ti(R,
|
|
3800
|
+
const program = Program.parse(${JSON.stringify(programText)}, { autoloadGoals: ['ti(R,1,0)'] });
|
|
3801
3801
|
const listTailGroup = program.findGroup('...', 2, 'user');
|
|
3802
3802
|
if (listTailGroup?.listTailRecursive !== true) {
|
|
3803
3803
|
throw new Error('recursive DCG tail-consumption was not recognized');
|
|
3804
3804
|
}
|
|
3805
3805
|
const solver = new Solver(program, { registry: getEyePrologRegistry(), maxMemoryBytes: Infinity });
|
|
3806
|
-
const goal = parseGoalText('ti(R,
|
|
3806
|
+
const goal = parseGoalText('ti(R,1,0)', {
|
|
3807
3807
|
doubleQuotes: 'chars',
|
|
3808
3808
|
operatorDefinitions: [...program.operators.values()],
|
|
3809
3809
|
});
|
|
3810
3810
|
let count = 0;
|
|
3811
3811
|
for (const _ of solver.solve([goal], new Env(), 0)) {
|
|
3812
|
-
if (++count ===
|
|
3812
|
+
if (++count === 10) break;
|
|
3813
3813
|
}
|
|
3814
|
-
if (count !==
|
|
3814
|
+
if (count !== 10) throw new Error('unexpected checkpoint count: ' + count);
|
|
3815
3815
|
const scope = solver.innerTableScopes.get('phrase');
|
|
3816
3816
|
if (scope == null) throw new Error('missing phrase table scope');
|
|
3817
3817
|
if (scope.memo.size !== 0) throw new Error('distinct tail-DCG inputs should not retain phrase tables: ' + scope.memo.size);
|
|
3818
3818
|
process.stdout.write(count + ':' + scope.memo.size);
|
|
3819
3819
|
`;
|
|
3820
3820
|
const result = spawnSync(process.execPath, [
|
|
3821
|
-
// This
|
|
3822
|
-
//
|
|
3823
|
-
//
|
|
3821
|
+
// This covers 100 accepted number candidates, enough to exercise
|
|
3822
|
+
// many distinct recursive DCG inputs while keeping this a focused
|
|
3823
|
+
// bounded-cache regression rather than a memory stress benchmark.
|
|
3824
3824
|
'--max-old-space-size=32',
|
|
3825
3825
|
'--input-type=module',
|
|
3826
3826
|
'--eval',
|
|
@@ -3829,7 +3829,7 @@ answer(ok) :-
|
|
|
3829
3829
|
if (result.error) throw result.error;
|
|
3830
3830
|
assertEqual(result.status, 0, `bounded phrase-table child status; stderr=${result.stderr}`);
|
|
3831
3831
|
const [countText, cacheText] = result.stdout.trim().split(':');
|
|
3832
|
-
assertEqual(countText, '
|
|
3832
|
+
assertEqual(countText, '10', 'recursive phrase checkpoints');
|
|
3833
3833
|
assertEqual(cacheText, '0', 'distinct tail-DCG phrase cache');
|
|
3834
3834
|
},
|
|
3835
3835
|
},
|
|
@@ -4886,10 +4886,22 @@ path(X, Z) :- edge(X, Y), path(Y, Z).
|
|
|
4886
4886
|
},
|
|
4887
4887
|
},
|
|
4888
4888
|
{
|
|
4889
|
-
name: '
|
|
4889
|
+
name: 'recursive search pattern keeps scan and search predicates tabled',
|
|
4890
4890
|
run: () => {
|
|
4891
|
-
const text =
|
|
4892
|
-
|
|
4891
|
+
const text = `
|
|
4892
|
+
queens([], Qs, Qs).
|
|
4893
|
+
queens(Us, Ps, Qs) :-
|
|
4894
|
+
select(Q, Us, Us1),
|
|
4895
|
+
\+ attack(Q, 1, Ps),
|
|
4896
|
+
queens(Us1, [Q|Ps], Qs).
|
|
4897
|
+
|
|
4898
|
+
attack(X, N, [Y|_]) :- X is Y + N.
|
|
4899
|
+
attack(X, N, [Y|_]) :- X is Y - N.
|
|
4900
|
+
attack(X, N, [_|Ys]) :-
|
|
4901
|
+
N1 is N + 1,
|
|
4902
|
+
attack(X, N1, Ys).
|
|
4903
|
+
`;
|
|
4904
|
+
const program = Program.parseSources([{ text, filename: 'recursive-search.pl' }]);
|
|
4893
4905
|
const attack = program.findGroup('attack', 3);
|
|
4894
4906
|
assertEqual(Boolean(attack), true, 'attack/3 group exists');
|
|
4895
4907
|
assertEqual(attack.tabled, true, 'attack/3 tabled');
|
package/the-art-of-eyeprolog.md
CHANGED
|
@@ -4076,8 +4076,8 @@ generation contains `n^k` leaves. If order does not matter, permutations may
|
|
|
4076
4076
|
be redundant. If partial choices already violate a constraint, pruning saves
|
|
4077
4077
|
an entire subtree.
|
|
4078
4078
|
|
|
4079
|
-
This is why combinatorial examples are not toys. `n-queens.pl` exposes
|
|
4080
|
-
|
|
4079
|
+
This is why combinatorial examples are not toys. `clpz-n-queens.pl` exposes
|
|
4080
|
+
the classic eight-queens search through finite-domain constraints. Together with `send-more-money.pl`,
|
|
4081
4081
|
`integer-partitions.pl`, `stirling-bell-numbers.pl`,
|
|
4082
4082
|
and `weighted-interval-scheduling.pl`, they show different geometries of
|
|
4083
4083
|
choice: permutations, digit assignments, recursive decompositions, set
|
|
@@ -6301,7 +6301,7 @@ library autoloading.
|
|
|
6301
6301
|
calls to non-profile predicates from otherwise common modules. `--portable`
|
|
6302
6302
|
turns those diagnostics into a failing run, making the conservative profile
|
|
6303
6303
|
suitable for continuous integration. `npm run test:interop` executes the same
|
|
6304
|
-
portable
|
|
6304
|
+
portable Towers of Hanoi source under EyeProlog, Trealla, and Scryer when those commands
|
|
6305
6305
|
are installed; the repository interoperability workflow installs them and runs
|
|
6306
6306
|
that check.
|
|
6307
6307
|
|
|
@@ -6769,7 +6769,7 @@ For example:
|
|
|
6769
6769
|
eyeprolog --goal 'ancestor(X, Y)' examples/ancestor.pl
|
|
6770
6770
|
eyeprolog --proof --goal 'type(X, Y)' examples/socrates.pl
|
|
6771
6771
|
eyeprolog --warnings --goal 'answer(X)' test/conformance/warnings/negation/unstratified_mutual.pl
|
|
6772
|
-
eyeprolog --portable --goal '
|
|
6772
|
+
eyeprolog --portable --goal 'sudoku9_solution(S)' examples/clpz-sudoku-9x9.pl
|
|
6773
6773
|
eyeprolog --stats --goal 'path(a, X)' examples/path-discovery.pl > answers.pl 2> run.stats
|
|
6774
6774
|
```
|
|
6775
6775
|
|
|
@@ -6951,7 +6951,7 @@ Review questions:
|
|
|
6951
6951
|
</figure>
|
|
6952
6952
|
|
|
6953
6953
|
The [examples directory](https://github.com/eyereasoner/eyeprolog/tree/main/examples/) is the book's executable companion. The
|
|
6954
|
-
top-level directory contains **
|
|
6954
|
+
top-level directory contains **210 self-contained runnable programs**. Every
|
|
6955
6955
|
source program has an exact answer file under
|
|
6956
6956
|
[examples/output](https://github.com/eyereasoner/eyeprolog/tree/main/examples/output/), and **61 selected programs** have a checked
|
|
6957
6957
|
explanation under [examples/proof](https://github.com/eyereasoner/eyeprolog/tree/main/examples/proof/). The thematic tables below link every top-level program and open the program
|
|
@@ -7001,7 +7001,7 @@ mode at a time.
|
|
|
7001
7001
|
| --- | --- | --- |
|
|
7002
7002
|
| [CLP(Z) factorial](https://github.com/eyereasoner/eyeprolog/blob/main/examples/clpz-factorial.pl) | Declarative predecessor and product constraints propagate a factorial without mode-sensitive `is/2`. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/clpz-factorial.pl) |
|
|
7003
7003
|
| [CLP(Z) global constraints](https://github.com/eyereasoner/eyeprolog/blob/main/examples/clpz-global-constraints.pl) | Compatibility tables, lexicographic and serialized schedules, global cardinality with costs, circuits, value counting, and integer comparison. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/clpz-global-constraints.pl) |
|
|
7004
|
-
| [CLP(Z) N-queens](https://github.com/eyereasoner/eyeprolog/blob/main/examples/clpz-n-queens.pl) |
|
|
7004
|
+
| [CLP(Z) N-queens](https://github.com/eyereasoner/eyeprolog/blob/main/examples/clpz-n-queens.pl) | Eight-queens using finite domains, delayed diagonal constraints, `all_distinct/1`, and first-fail labeling, plus a small multi-solution enumeration check. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/clpz-n-queens.pl) |
|
|
7005
7005
|
| [CLP(Z) resource allocation](https://github.com/eyereasoner/eyeprolog/blob/main/examples/clpz-resource-allocation.pl) | Resource assignment using `element/3`, `sum/3`, `scalar_product/4`, reification, labeling options, and domain reflection. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/clpz-resource-allocation.pl) |
|
|
7006
7006
|
| [CLP(Z) Sudoku 9×9](https://github.com/eyereasoner/eyeprolog/blob/main/examples/clpz-sudoku-9x9.pl) | The difficult AI Escargot puzzle modeled with finite domains, 27 all-distinct constraints, and first-fail labeling. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/clpz-sudoku-9x9.pl) |
|
|
7007
7007
|
| [Combinatorics Findall Sort](https://github.com/eyereasoner/eyeprolog/blob/main/examples/combinatorics-findall-sort.pl) | Eyelet-inspired combinations example using `findall/3` and ISO `sort/2`. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/combinatorics-findall-sort.pl) |
|
|
@@ -7097,11 +7097,9 @@ finite search space, and which constraint removes which branches?
|
|
|
7097
7097
|
| [Map Four Color Search](https://github.com/eyereasoner/eyeprolog/blob/main/examples/map-four-color-search.pl) | Four-colour search for the European Union neighbour graph. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/map-four-color-search.pl) |
|
|
7098
7098
|
| [Markov Logic Network](https://github.com/eyereasoner/eyeprolog/blob/main/examples/markov-logic-network.pl) | Markov Logic Network style scoring over a tiny finite domain. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/markov-logic-network.pl) |
|
|
7099
7099
|
| [Matrix Chain Order](https://github.com/eyereasoner/eyeprolog/blob/main/examples/matrix-chain-order.pl) | Matrix-chain multiplication order by automatically tabled interval dynamic programming. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/matrix-chain-order.pl) |
|
|
7100
|
-
| [N-Queens enumeration](https://github.com/eyereasoner/eyeprolog/blob/main/examples/n-queens.pl) | `select/3` chooses each row and diagonal checks prune partial placements; the query enumerates all 92 eight-queen solutions in the default runtime. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/n-queens.pl) |
|
|
7101
7100
|
| [Register allocation](https://github.com/eyereasoner/eyeprolog/blob/main/examples/register-allocation.pl) | Interference constraints turn compiler allocation into graph coloring. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/register-allocation.pl) |
|
|
7102
7101
|
| [SEND + MORE = MONEY](https://github.com/eyereasoner/eyeprolog/blob/main/examples/send-more-money.pl) | Digit assignments are generated under distinctness, leading-zero, and column constraints. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/send-more-money.pl) |
|
|
7103
7102
|
| [Stable marriage](https://github.com/eyereasoner/eyeprolog/blob/main/examples/stable-marriage.pl) | Preference data, matching generation, and the absence of blocking pairs define stability. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/stable-marriage.pl) |
|
|
7104
|
-
| [Sudoku 9×9](https://github.com/eyereasoner/eyeprolog/blob/main/examples/sudoku.pl) | Minimum-remaining-values search fills a standard grid while enforcing row, column, and 3×3 block constraints. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/sudoku.pl) |
|
|
7105
7103
|
| [Weighted interval scheduling](https://github.com/eyereasoner/eyeprolog/blob/main/examples/weighted-interval-scheduling.pl) | Compatibility constraints and an ordered objective select a maximum-value schedule. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/weighted-interval-scheduling.pl) · [proof](https://github.com/eyereasoner/eyeprolog/blob/main/examples/proof/weighted-interval-scheduling.pl) |
|
|
7106
7104
|
| [Zebra puzzle](https://github.com/eyereasoner/eyeprolog/blob/main/examples/zebra.pl) | House records, adjacency relations, and clue constraints jointly determine the famous solution. | [answers](https://github.com/eyereasoner/eyeprolog/blob/main/examples/output/zebra.pl) |
|
|
7107
7105
|
|
|
@@ -7354,7 +7352,7 @@ hand.
|
|
|
7354
7352
|
|
|
7355
7353
|
#### Running and extending the corpus
|
|
7356
7354
|
|
|
7357
|
-
Run all
|
|
7355
|
+
Run all 210 normal answer goldens and the 61 selected proof goldens with:
|
|
7358
7356
|
|
|
7359
7357
|
```sh
|
|
7360
7358
|
npm run test:examples
|
|
@@ -7418,7 +7416,7 @@ The complete suite must pass before release. The file-based conformance corpus
|
|
|
7418
7416
|
contains 791 cases, including 386 focused ISO
|
|
7419
7417
|
cases derived from the success, failure, mode, and error behavior in
|
|
7420
7418
|
ISO/IEC 13211-1 clauses 7 and 8, Part 2 modules, and Part 3 grammar rules.
|
|
7421
|
-
Separate exact-output suites check
|
|
7419
|
+
Separate exact-output suites check 210 normal
|
|
7422
7420
|
examples and 61 proof examples; all extracted book programs are parsed and
|
|
7423
7421
|
their declared goals are executed. The eight-case
|
|
7424
7422
|
playground contract suite imports the production worker, sends real reasoning
|
package/examples/n-queens.pl
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
:- use_module(library(lists)).
|
|
2
|
-
|
|
3
|
-
% N-Queens puzzle
|
|
4
|
-
% See https://en.wikipedia.org/wiki/Eight_queens_puzzle
|
|
5
|
-
% Original code at https://hanslen.github.io/2016/05/02/AI-problem-N-queens-problem-%E2%80%93-solved-in-prolog/
|
|
6
|
-
|
|
7
|
-
queens(N, Qs) :-
|
|
8
|
-
range(1, N, Us),
|
|
9
|
-
queens(Us, [], Qs).
|
|
10
|
-
|
|
11
|
-
% queens(+Unplaced, ?Placed, ?Queens)
|
|
12
|
-
queens([], Qs, Qs).
|
|
13
|
-
queens(Us, Ps, Qs) :-
|
|
14
|
-
select(Q, Us, Us1),
|
|
15
|
-
\+attack(Q, 1, Ps),
|
|
16
|
-
queens(Us1, [Q|Ps], Qs).
|
|
17
|
-
|
|
18
|
-
% range(+I, +J, -Ns): Ns is the list of integers between I and J inclusive
|
|
19
|
-
range(J, J, [J]).
|
|
20
|
-
range(I, J, [I|Ns]) :-
|
|
21
|
-
I < J,
|
|
22
|
-
I1 is I+1,
|
|
23
|
-
range(I1, J, Ns).
|
|
24
|
-
|
|
25
|
-
% attack(+Q, +N, +Qs): queen in row Q attacks from distance N one or more of the queens in rows Qs on a diagonal
|
|
26
|
-
attack(X, N, [Y|_]) :-
|
|
27
|
-
X is Y+N.
|
|
28
|
-
attack(X, N, [Y|_]) :-
|
|
29
|
-
X is Y-N.
|
|
30
|
-
attack(X, N, [_|Ys]) :-
|
|
31
|
-
N1 is N+1,
|
|
32
|
-
attack(X, N1, Ys).
|
|
33
|
-
|
|
34
|
-
% query
|
|
35
|
-
%% goal: queens(8, _)
|
|
36
|
-
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
queens(8, [4, 2, 7, 3, 6, 8, 5, 1]).
|
|
2
|
-
queens(8, [5, 2, 4, 7, 3, 8, 6, 1]).
|
|
3
|
-
queens(8, [3, 5, 2, 8, 6, 4, 7, 1]).
|
|
4
|
-
queens(8, [3, 6, 4, 2, 8, 5, 7, 1]).
|
|
5
|
-
queens(8, [5, 7, 1, 3, 8, 6, 4, 2]).
|
|
6
|
-
queens(8, [4, 6, 8, 3, 1, 7, 5, 2]).
|
|
7
|
-
queens(8, [3, 6, 8, 1, 4, 7, 5, 2]).
|
|
8
|
-
queens(8, [5, 3, 8, 4, 7, 1, 6, 2]).
|
|
9
|
-
queens(8, [5, 7, 4, 1, 3, 8, 6, 2]).
|
|
10
|
-
queens(8, [4, 1, 5, 8, 6, 3, 7, 2]).
|
|
11
|
-
queens(8, [3, 6, 4, 1, 8, 5, 7, 2]).
|
|
12
|
-
queens(8, [4, 7, 5, 3, 1, 6, 8, 2]).
|
|
13
|
-
queens(8, [6, 4, 2, 8, 5, 7, 1, 3]).
|
|
14
|
-
queens(8, [6, 4, 7, 1, 8, 2, 5, 3]).
|
|
15
|
-
queens(8, [1, 7, 4, 6, 8, 2, 5, 3]).
|
|
16
|
-
queens(8, [6, 8, 2, 4, 1, 7, 5, 3]).
|
|
17
|
-
queens(8, [6, 2, 7, 1, 4, 8, 5, 3]).
|
|
18
|
-
queens(8, [4, 7, 1, 8, 5, 2, 6, 3]).
|
|
19
|
-
queens(8, [5, 8, 4, 1, 7, 2, 6, 3]).
|
|
20
|
-
queens(8, [4, 8, 1, 5, 7, 2, 6, 3]).
|
|
21
|
-
queens(8, [2, 7, 5, 8, 1, 4, 6, 3]).
|
|
22
|
-
queens(8, [1, 7, 5, 8, 2, 4, 6, 3]).
|
|
23
|
-
queens(8, [2, 5, 7, 4, 1, 8, 6, 3]).
|
|
24
|
-
queens(8, [4, 2, 7, 5, 1, 8, 6, 3]).
|
|
25
|
-
queens(8, [5, 7, 1, 4, 2, 8, 6, 3]).
|
|
26
|
-
queens(8, [6, 4, 1, 5, 8, 2, 7, 3]).
|
|
27
|
-
queens(8, [5, 1, 4, 6, 8, 2, 7, 3]).
|
|
28
|
-
queens(8, [5, 2, 6, 1, 7, 4, 8, 3]).
|
|
29
|
-
queens(8, [6, 3, 7, 2, 8, 5, 1, 4]).
|
|
30
|
-
queens(8, [2, 7, 3, 6, 8, 5, 1, 4]).
|
|
31
|
-
queens(8, [7, 3, 1, 6, 8, 5, 2, 4]).
|
|
32
|
-
queens(8, [5, 1, 8, 6, 3, 7, 2, 4]).
|
|
33
|
-
queens(8, [1, 5, 8, 6, 3, 7, 2, 4]).
|
|
34
|
-
queens(8, [3, 6, 8, 1, 5, 7, 2, 4]).
|
|
35
|
-
queens(8, [6, 3, 1, 7, 5, 8, 2, 4]).
|
|
36
|
-
queens(8, [7, 5, 3, 1, 6, 8, 2, 4]).
|
|
37
|
-
queens(8, [7, 3, 8, 2, 5, 1, 6, 4]).
|
|
38
|
-
queens(8, [5, 3, 1, 7, 2, 8, 6, 4]).
|
|
39
|
-
queens(8, [2, 5, 7, 1, 3, 8, 6, 4]).
|
|
40
|
-
queens(8, [3, 6, 2, 5, 8, 1, 7, 4]).
|
|
41
|
-
queens(8, [6, 1, 5, 2, 8, 3, 7, 4]).
|
|
42
|
-
queens(8, [8, 3, 1, 6, 2, 5, 7, 4]).
|
|
43
|
-
queens(8, [2, 8, 6, 1, 3, 5, 7, 4]).
|
|
44
|
-
queens(8, [5, 7, 2, 6, 3, 1, 8, 4]).
|
|
45
|
-
queens(8, [3, 6, 2, 7, 5, 1, 8, 4]).
|
|
46
|
-
queens(8, [6, 2, 7, 1, 3, 5, 8, 4]).
|
|
47
|
-
queens(8, [3, 7, 2, 8, 6, 4, 1, 5]).
|
|
48
|
-
queens(8, [6, 3, 7, 2, 4, 8, 1, 5]).
|
|
49
|
-
queens(8, [4, 2, 7, 3, 6, 8, 1, 5]).
|
|
50
|
-
queens(8, [7, 1, 3, 8, 6, 4, 2, 5]).
|
|
51
|
-
queens(8, [1, 6, 8, 3, 7, 4, 2, 5]).
|
|
52
|
-
queens(8, [3, 8, 4, 7, 1, 6, 2, 5]).
|
|
53
|
-
queens(8, [6, 3, 7, 4, 1, 8, 2, 5]).
|
|
54
|
-
queens(8, [7, 4, 2, 8, 6, 1, 3, 5]).
|
|
55
|
-
queens(8, [4, 6, 8, 2, 7, 1, 3, 5]).
|
|
56
|
-
queens(8, [2, 6, 1, 7, 4, 8, 3, 5]).
|
|
57
|
-
queens(8, [2, 4, 6, 8, 3, 1, 7, 5]).
|
|
58
|
-
queens(8, [3, 6, 8, 2, 4, 1, 7, 5]).
|
|
59
|
-
queens(8, [6, 3, 1, 8, 4, 2, 7, 5]).
|
|
60
|
-
queens(8, [8, 4, 1, 3, 6, 2, 7, 5]).
|
|
61
|
-
queens(8, [4, 8, 1, 3, 6, 2, 7, 5]).
|
|
62
|
-
queens(8, [2, 6, 8, 3, 1, 4, 7, 5]).
|
|
63
|
-
queens(8, [7, 2, 6, 3, 1, 4, 8, 5]).
|
|
64
|
-
queens(8, [3, 6, 2, 7, 1, 4, 8, 5]).
|
|
65
|
-
queens(8, [4, 7, 3, 8, 2, 5, 1, 6]).
|
|
66
|
-
queens(8, [4, 8, 5, 3, 1, 7, 2, 6]).
|
|
67
|
-
queens(8, [3, 5, 8, 4, 1, 7, 2, 6]).
|
|
68
|
-
queens(8, [4, 2, 8, 5, 7, 1, 3, 6]).
|
|
69
|
-
queens(8, [5, 7, 2, 4, 8, 1, 3, 6]).
|
|
70
|
-
queens(8, [7, 4, 2, 5, 8, 1, 3, 6]).
|
|
71
|
-
queens(8, [8, 2, 4, 1, 7, 5, 3, 6]).
|
|
72
|
-
queens(8, [7, 2, 4, 1, 8, 5, 3, 6]).
|
|
73
|
-
queens(8, [5, 1, 8, 4, 2, 7, 3, 6]).
|
|
74
|
-
queens(8, [4, 1, 5, 8, 2, 7, 3, 6]).
|
|
75
|
-
queens(8, [5, 2, 8, 1, 4, 7, 3, 6]).
|
|
76
|
-
queens(8, [3, 7, 2, 8, 5, 1, 4, 6]).
|
|
77
|
-
queens(8, [3, 1, 7, 5, 8, 2, 4, 6]).
|
|
78
|
-
queens(8, [8, 2, 5, 3, 1, 7, 4, 6]).
|
|
79
|
-
queens(8, [3, 5, 2, 8, 1, 7, 4, 6]).
|
|
80
|
-
queens(8, [3, 5, 7, 1, 4, 2, 8, 6]).
|
|
81
|
-
queens(8, [5, 2, 4, 6, 8, 3, 1, 7]).
|
|
82
|
-
queens(8, [6, 3, 5, 8, 1, 4, 2, 7]).
|
|
83
|
-
queens(8, [5, 8, 4, 1, 3, 6, 2, 7]).
|
|
84
|
-
queens(8, [4, 2, 5, 8, 6, 1, 3, 7]).
|
|
85
|
-
queens(8, [4, 6, 1, 5, 2, 8, 3, 7]).
|
|
86
|
-
queens(8, [6, 3, 1, 8, 5, 2, 4, 7]).
|
|
87
|
-
queens(8, [5, 3, 1, 6, 8, 2, 4, 7]).
|
|
88
|
-
queens(8, [4, 2, 8, 6, 1, 3, 5, 7]).
|
|
89
|
-
queens(8, [6, 3, 5, 7, 1, 4, 2, 8]).
|
|
90
|
-
queens(8, [6, 4, 7, 1, 3, 5, 2, 8]).
|
|
91
|
-
queens(8, [4, 7, 5, 2, 6, 1, 3, 8]).
|
|
92
|
-
queens(8, [5, 7, 2, 6, 3, 1, 4, 8]).
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
sudoku_solution([[5, 3, 4, 6, 7, 8, 9, 1, 2], [6, 7, 2, 1, 9, 5, 3, 4, 8], [1, 9, 8, 3, 4, 2, 5, 6, 7], [8, 5, 9, 7, 6, 1, 4, 2, 3], [4, 2, 6, 8, 5, 3, 7, 9, 1], [7, 1, 3, 9, 2, 4, 8, 5, 6], [9, 6, 1, 5, 3, 7, 2, 8, 4], [2, 8, 7, 4, 1, 9, 6, 3, 5], [3, 4, 5, 2, 8, 6, 1, 7, 9]]).
|
package/examples/sudoku.pl
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
:- use_module(library(lists)).
|
|
2
|
-
|
|
3
|
-
% A deterministic 9x9 Sudoku solver.
|
|
4
|
-
%
|
|
5
|
-
% Zero marks an empty cell. The solver first takes any forced move; otherwise
|
|
6
|
-
% it selects the cell with the fewest candidates (minimum remaining values).
|
|
7
|
-
%% goal: sudoku_solution(_)
|
|
8
|
-
|
|
9
|
-
puzzle([
|
|
10
|
-
[0,3,4,6,7,8,9,1,0],
|
|
11
|
-
[6,0,2,1,9,5,3,0,8],
|
|
12
|
-
[1,9,0,3,4,2,0,6,7],
|
|
13
|
-
[8,5,9,0,6,1,4,0,3],
|
|
14
|
-
[4,2,6,8,0,3,7,9,0],
|
|
15
|
-
[0,1,3,9,2,0,8,5,6],
|
|
16
|
-
[9,6,0,5,3,7,0,8,4],
|
|
17
|
-
[2,0,7,4,1,9,6,0,5],
|
|
18
|
-
[0,4,5,2,8,6,1,7,0]
|
|
19
|
-
]).
|
|
20
|
-
|
|
21
|
-
sudoku_solution(Solution) :-
|
|
22
|
-
puzzle(Puzzle),
|
|
23
|
-
solve(Puzzle, Solution),
|
|
24
|
-
!.
|
|
25
|
-
|
|
26
|
-
solve(Grid, Grid) :-
|
|
27
|
-
\+ empty_cell(Grid, _Row, _Column),
|
|
28
|
-
!.
|
|
29
|
-
solve(Grid, Solution) :-
|
|
30
|
-
best_choice(Grid, Row, Column, Candidates),
|
|
31
|
-
member(Digit, Candidates),
|
|
32
|
-
set_cell(Grid, Row, Column, Digit, Next),
|
|
33
|
-
solve(Next, Solution).
|
|
34
|
-
|
|
35
|
-
% A singleton candidate is already optimal, so take it immediately.
|
|
36
|
-
best_choice(Grid, Row, Column, Candidates) :-
|
|
37
|
-
empty_cell(Grid, Row, Column),
|
|
38
|
-
candidates(Grid, Row, Column, Candidates),
|
|
39
|
-
Candidates = [_Only],
|
|
40
|
-
!.
|
|
41
|
-
best_choice(Grid, Row, Column, Candidates) :-
|
|
42
|
-
findall(
|
|
43
|
-
choice(Count, R, C, Values),
|
|
44
|
-
(
|
|
45
|
-
empty_cell(Grid, R, C),
|
|
46
|
-
candidates(Grid, R, C, Values),
|
|
47
|
-
length(Values, Count)
|
|
48
|
-
),
|
|
49
|
-
Choices
|
|
50
|
-
),
|
|
51
|
-
sort(Choices, [choice(_Count, Row, Column, Candidates)|_]).
|
|
52
|
-
|
|
53
|
-
empty_cell(Grid, Row, Column) :-
|
|
54
|
-
between(0, 8, Row),
|
|
55
|
-
nth0(Row, Grid, Cells),
|
|
56
|
-
between(0, 8, Column),
|
|
57
|
-
nth0(Column, Cells, 0).
|
|
58
|
-
|
|
59
|
-
candidates(Grid, Row, Column, Candidates) :-
|
|
60
|
-
findall(
|
|
61
|
-
Digit,
|
|
62
|
-
(
|
|
63
|
-
between(1, 9, Digit),
|
|
64
|
-
allowed(Grid, Row, Column, Digit)
|
|
65
|
-
),
|
|
66
|
-
Candidates
|
|
67
|
-
).
|
|
68
|
-
|
|
69
|
-
allowed(Grid, Row, Column, Digit) :-
|
|
70
|
-
row_unused(Grid, Row, Digit),
|
|
71
|
-
column_unused(Grid, Column, Digit),
|
|
72
|
-
block_unused(Grid, Row, Column, Digit).
|
|
73
|
-
|
|
74
|
-
row_unused(Grid, Row, Digit) :-
|
|
75
|
-
nth0(Row, Grid, Cells),
|
|
76
|
-
\+ member(Digit, Cells).
|
|
77
|
-
|
|
78
|
-
column_unused([], _Column, _Digit).
|
|
79
|
-
column_unused([Row|Rows], Column, Digit) :-
|
|
80
|
-
nth0(Column, Row, Existing),
|
|
81
|
-
Digit \= Existing,
|
|
82
|
-
column_unused(Rows, Column, Digit).
|
|
83
|
-
|
|
84
|
-
block_unused(Grid, Row, Column, Digit) :-
|
|
85
|
-
StartRow is (Row // 3) * 3,
|
|
86
|
-
EndRow is StartRow + 2,
|
|
87
|
-
StartColumn is (Column // 3) * 3,
|
|
88
|
-
block_rows_unused(Grid, StartRow, EndRow, StartColumn, Digit).
|
|
89
|
-
|
|
90
|
-
block_rows_unused(_Grid, Row, EndRow, _StartColumn, _Digit) :-
|
|
91
|
-
Row > EndRow,
|
|
92
|
-
!.
|
|
93
|
-
block_rows_unused(Grid, Row, EndRow, StartColumn, Digit) :-
|
|
94
|
-
nth0(Row, Grid, Cells),
|
|
95
|
-
segment_unused(Cells, StartColumn, Digit),
|
|
96
|
-
NextRow is Row + 1,
|
|
97
|
-
block_rows_unused(Grid, NextRow, EndRow, StartColumn, Digit).
|
|
98
|
-
|
|
99
|
-
segment_unused(Cells, StartColumn, Digit) :-
|
|
100
|
-
nth0(StartColumn, Cells, A),
|
|
101
|
-
Middle is StartColumn + 1,
|
|
102
|
-
nth0(Middle, Cells, B),
|
|
103
|
-
End is StartColumn + 2,
|
|
104
|
-
nth0(End, Cells, C),
|
|
105
|
-
Digit \= A,
|
|
106
|
-
Digit \= B,
|
|
107
|
-
Digit \= C.
|
|
108
|
-
|
|
109
|
-
set_cell(Grid, Row, Column, Digit, Result) :-
|
|
110
|
-
nth0(Row, Grid, Cells, OtherRows),
|
|
111
|
-
nth0(Column, Cells, _Old, OtherCells),
|
|
112
|
-
nth0(Column, UpdatedCells, Digit, OtherCells),
|
|
113
|
-
nth0(Row, Result, UpdatedCells, OtherRows).
|