Skip to content

Commit e6d3f1a

Browse files
committed
Add suduku example.
1 parent 91b30d7 commit e6d3f1a

File tree

4 files changed

+238
-8
lines changed

4 files changed

+238
-8
lines changed

examples/engine.mjs

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* jshint esversion:8 */
1+
/* jshint esversion:11 */
22

33
import {
44
readFile,
@@ -18,8 +18,12 @@ import {
1818
}
1919
from "../jsds/jsds.mjs";
2020

21-
function* search(input_strings) {
22-
buffer_size(1000);
21+
function default_callback(candidate) {
22+
console.log(candidate.toString());
23+
}
24+
25+
function* search(input_strings, buffer_limit = 1024, callback = default_callback) {
26+
buffer_size(buffer_limit);
2327

2428
let rules = {};
2529
let facts = {};
@@ -38,6 +42,7 @@ function* search(input_strings) {
3842
while (true) {
3943
let temp_rules = {};
4044
let temp_facts = {};
45+
let something_new = false;
4146

4247
for (let r_hash in rules) {
4348
for (const f_hash in facts) {
@@ -64,7 +69,8 @@ function* search(input_strings) {
6469
}
6570
temp_facts[candidate_hash] = candidate;
6671
}
67-
console.log(candidate.toString());
72+
callback(candidate);
73+
something_new = true;
6874
}
6975
}
7076

@@ -77,6 +83,9 @@ function* search(input_strings) {
7783
const fact = temp_facts[f_hash];
7884
facts[fact.key()] = [fact, cycle];
7985
}
86+
if (!something_new) {
87+
return;
88+
}
8089

8190
yield;
8291
}
@@ -92,19 +101,42 @@ async function read_file_to_string_array(file_path) {
92101
}
93102

94103
async function main() {
95-
if (argv.length < 3) {
96-
console.error("Usage: node engine.mjs <file_path>");
104+
const help_message = "Usage: node engine.mjs <file_path> <buffer_limit> [callback_module]";
105+
if (argv.length != 4 && argv.length != 5) {
106+
console.error(help_message);
97107
exit(1);
98108
}
99109
const file_path = argv[2];
110+
const buffer_limit = parseInt(argv[3], 10);
111+
let callback;
112+
if (argv.length == 5) {
113+
try {
114+
const callback_module = await import(argv[4]);
115+
if (typeof callback_module.default === "function") {
116+
callback = callback_module.default;
117+
} else {
118+
console.error("Callback module must export a default function.");
119+
exit(1);
120+
}
121+
} catch (error) {
122+
console.error(`Error importing callback module: ${error.message}`);
123+
exit(1);
124+
}
125+
} else {
126+
callback = default_callback;
127+
}
128+
100129
const data = await read_file_to_string_array(file_path);
101-
const generator = search(data);
130+
const generator = search(data, buffer_limit, callback);
102131
const handle = createInterface({
103132
input: stdin,
104133
output: stdout
105134
});
106135
while (true) {
107-
generator.next();
136+
if (generator.next().done) {
137+
console.log("Search completed.");
138+
break;
139+
}
108140
await handle.question("Press Enter to continue...");
109141
}
110142
}

examples/suduku.ejs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<%# 等价关系 %>
2+
3+
<%
4+
for (let i = 1; i <= 9; i++) {
5+
for (let j = 1; j <= 9; j++) {
6+
if (i === j) {
7+
%>
8+
<%- `(${i} = ${j})` %>
9+
<%
10+
} else {
11+
%>
12+
<%- `(${i} != ${j})` %>
13+
<%
14+
}
15+
}
16+
}
17+
%>
18+
19+
<%# 相等与不等 %>
20+
21+
((Cell `x `y) = (Literal `a))
22+
(`a != `b)
23+
----------
24+
((Cell `x `y) != (Literal `b))
25+
26+
<%
27+
for (let i = 1; i <= 9; i++) {
28+
for (let j = 1; j <= 9; j++) {
29+
if (i !== j) {
30+
-%>
31+
<%- `((Cell \`x \`y) != (Literal ${j}))` %>
32+
<%
33+
}
34+
}
35+
-%>
36+
--------------------------------------
37+
<%- `((Cell \`x \`y) = (Literal ${i}))` %>
38+
39+
<%
40+
}
41+
%>
42+
43+
<%# 数独行列 %>
44+
45+
((Cell `x `y) = `n)
46+
(`x != `x')
47+
---------------------
48+
((Cell `x' `y) != `n)
49+
50+
((Cell `x `y) = `n)
51+
(`y != `y')
52+
---------------------
53+
((Cell `x `y') != `n)
54+
55+
<%
56+
for (let i = 1; i <= 9; i++) {
57+
for (let j = 1; j <= 9; j++) {
58+
if (i !== j) {
59+
-%>
60+
<%- `((Cell \`x ${j}) != \`n)` %>
61+
<%
62+
}
63+
}
64+
-%>
65+
-------------------------------------
66+
<%- `((Cell \`x ${i}) = \`n)` %>
67+
68+
<%
69+
}
70+
%>
71+
72+
<%
73+
for (let i = 1; i <= 9; i++) {
74+
for (let j = 1; j <= 9; j++) {
75+
if (i !== j) {
76+
-%>
77+
<%- `((Cell ${j} \`y) != \`n)` %>
78+
<%
79+
}
80+
}
81+
-%>
82+
-------------------------------------
83+
<%- `((Cell ${i} \`y) = \`n)` %>
84+
85+
<%
86+
}
87+
%>
88+
89+
<%# 数独分块 %>
90+
91+
<%
92+
for (let ib = 1; ib <= 3; ib++) {
93+
for (let jb = 1; jb <= 3; jb++) {
94+
for (let it = 1; it <= 3; it++) {
95+
for (let jt = 1; jt <= 3; jt++) {
96+
const xt = (ib - 1) * 3 + it;
97+
const yt = (jb - 1) * 3 + jt;
98+
for (let i = 1; i <= 3; i++) {
99+
for (let j = 1; j <= 3; j++) {
100+
const x = (ib - 1) * 3 + i;
101+
const y = (jb - 1) * 3 + j;
102+
if (i !== it || j !== jt) {
103+
%>
104+
<%- `((Cell ${x} ${y}) = \`n)` %>
105+
------------------------------------
106+
<%- `((Cell ${xt} ${yt}) != \`n)` %>
107+
<%
108+
}
109+
}
110+
}
111+
}
112+
}
113+
}
114+
}
115+
%>
116+
117+
<%
118+
for (let ib = 1; ib <= 3; ib++) {
119+
for (let jb = 1; jb <= 3; jb++) {
120+
for (let it = 1; it <= 3; it++) {
121+
for (let jt = 1; jt <= 3; jt++) {
122+
const xt = (ib - 1) * 3 + it;
123+
const yt = (jb - 1) * 3 + jt;
124+
for (let i = 1; i <= 3; i++) {
125+
for (let j = 1; j <= 3; j++) {
126+
const x = (ib - 1) * 3 + i;
127+
const y = (jb - 1) * 3 + j;
128+
if (i !== it || j !== jt) {
129+
-%>
130+
<%- `((Cell ${x} ${y}) != \`n)` %>
131+
<%
132+
}
133+
}
134+
}
135+
-%>
136+
--------------------------------------
137+
<%- `((Cell ${xt} ${yt}) = \`n)` %>
138+
139+
<%
140+
}
141+
}
142+
}
143+
}
144+
%>
145+
146+
<%# 数独棋盘 %>
147+
<%
148+
const suduku_data = (
149+
" 9 37\n" +
150+
"854397\n" +
151+
" 3\n" +
152+
"29 4\n" +
153+
" 84 5 2\n" +
154+
" 482 6\n" +
155+
" 3 4 59\n" +
156+
"4 2 13 7\n" +
157+
" 6 3\n" +
158+
"");
159+
160+
const suduku_array = suduku_data.split("\n").map(row => row.split("").map(cell => cell === " " ? 0 : parseInt(cell)));
161+
162+
for (let i = 0; i < 9; i++) {
163+
for (let j = 0; j < 9; j++) {
164+
if (suduku_array[i][j]) {
165+
%>
166+
<%- `((Cell ${i+1} ${j+1}) = (Literal ${suduku_array[i][j]}))` %>
167+
<%
168+
}
169+
}
170+
}
171+
%>

examples/suduku_callback.mjs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/* jshint esversion:6 */
2+
3+
let array = Array.from({
4+
length: 9
5+
}, () => Array.from({
6+
length: 9
7+
}, () => " "));
8+
9+
export default function callback(candidate) {
10+
if (candidate.length() === 0) {
11+
const text = candidate.toString();
12+
const match = text.match(/\(\(Cell (\d) (\d)\) = \(Literal (\d)\)\)/);
13+
if (match) {
14+
const row = parseInt(match[1], 10);
15+
const col = parseInt(match[2], 10);
16+
const value = match[3];
17+
array[row - 1][col - 1] = value;
18+
console.log("Current partial solution:");
19+
for (let i = 0; i < 9; i++) {
20+
console.log("|" + array[i].join("|") + "|");
21+
}
22+
}
23+
}
24+
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@
1111
"jest": "^30.0.4",
1212
"npm-run-all": "^4.1.5",
1313
"rollup": "^4.44.2"
14+
},
15+
"dependencies": {
16+
"ejs": "^3.1.10"
1417
}
1518
}

0 commit comments

Comments
 (0)