-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathsudoku.html
executable file
·151 lines (134 loc) · 4.81 KB
/
sudoku.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#!/usr/bin/env -S deno run --allow-env
console.log(`
<html>
<head>
<meta name="robots" content="noindex,nofollow">
</head>
<body>
`);
const script = "sudoku.html"; // my $script = $ENV{SCRIPT_NAME}; $script =~ s/.*\///;
const blank = ".................................................................................";
const givensString = ((Deno.env.get('QUERY_STRING') ?? "") + blank).substr(0, 81);
const givens = Array.from(givensString);
const choices = Array.from({length:81}).map(_=>"123456789");
const subsets = [
// rows
[ 0, 1, 2, 9, 10, 11, 18, 19, 20],
[ 3, 4, 5, 12, 13, 14, 21, 22, 23],
[ 6, 7, 8, 15, 16, 17, 24, 25, 26],
[27, 28, 29, 36, 37, 38, 45, 46, 47],
[30, 31, 32, 39, 40, 41, 48, 49, 50],
[33, 34, 35, 42, 43, 44, 51, 52, 53],
[54, 55, 56, 63, 64, 65, 72, 73, 74],
[57, 58, 59, 66, 67, 68, 75, 76, 77],
[60, 61, 62, 69, 70, 71, 78, 79, 80],
// columns
[ 0, 3, 6, 27, 30, 33, 54, 57, 60],
[ 1, 4, 7, 28, 31, 34, 55, 58, 61],
[ 2, 5, 8, 29, 32, 35, 56, 59, 62],
[ 9, 12, 15, 36, 39, 42, 63, 66, 69],
[10, 13, 16, 37, 40, 43, 64, 67, 70],
[11, 14, 17, 38, 41, 44, 65, 68, 71],
[18, 21, 24, 45, 48, 51, 72, 75, 78],
[19, 22, 25, 46, 49, 52, 73, 76, 79],
[20, 23, 26, 47, 50, 53, 74, 77, 80],
// squares
[ 0, 1, 2, 3, 4, 5, 6, 7, 8],
[ 9, 10, 11, 12, 13, 14, 15, 16, 17],
[18, 19, 20, 21, 22, 23, 24, 25, 26],
[27, 28, 29, 30, 31, 32, 33, 34, 35],
[36, 37, 38, 39, 40, 41, 42, 43, 44],
[45, 46, 47, 48, 49, 50, 51, 52, 53],
[54, 55, 56, 57, 58, 59, 60, 61, 62],
[63, 64, 65, 66, 67, 68, 69, 70, 71],
[72, 73, 74, 75, 76, 77, 78, 79, 80]
];
// remove choices eliminated by the at-most-one rule
for (let subset of subsets) {
for (let i of subset) {
const d = givens[i];
if (d == ".") continue;
for (let j of subset) {
choices[j] = choices[j].replace(d, "");
}
}
}
// identify choices mandated by the at-least-one rule
const unique = {};
const digitCounts = Array.from("123456789")
.reduce((acc, d) => {acc[d] = 0; return acc}, {});
for (let subset of subsets) {
const counts = {...digitCounts};
const where = {...digitCounts};
subset
.filter(i => givens[i] == ".")
.forEach(i => {
const digits = Array.from(choices[i]);
for (let d of digits) {
counts[d] += 1;
where[d] = i;
};
});
Array.from("123456789")
.filter(d => counts[d] == 1)
.forEach(d => unique[where[d]] = d)
}
// display board as table of tables of hyperlinked choices
function table(first) {
const row = `\n<td bgcolor=#77bbff width=170 height=50 align=center>${first}`;
return `\n<table>` + Array.from({length:3}).map(_=>`<tr>${row}${row}${row}`).join('') + `</table>`;
}
let board = table(table("X"));
function nextGivens(i, digit) {
let res = Array.from(givens);
res[i] = digit;
return res.join("");
}
function choicesFn(i) {
const uniqueChoice = unique[i];
return Array.from(choices[i])
.map(digit => {
if (uniqueChoice && digit != uniqueChoice) {
return `\n<font color=gray size=-1>${digit}</font>`;
} else {
let search = nextGivens(i, digit);
return `\n<a href="${script}?${search}">${digit}</a>`;
}
}).join("");
}
for (let i=0; i <= 80; i++) {
const digit = givens[i];
const content = (digit != '.')
? `<font size=8>${digit}`
: choicesFn(i);
board = board.replace('X', content);
}
console.log(`
<style>
a {text-decoration: none;}
</style>
<center><br>
${board}
<font color=gray><br><br>
About Sudokant, the Sudoku Servant
<br><table width=400><tr><td><font color=gray>
This server helps you solve <a href=http://www.sudoku.com/>sudoku puzzles</a>
by showing choices satisfying two simple rules: <i>at-most-one</i> and <i>at-least-one</i>
of every digit must appear in every row, column and square.
Choices that violate the <i>at-most-one</i> rule are omitted.
Alternatives to digits that must be chosen by the <i>at-least-one</i> rule are grayed.
<br><br>
Empty squares are dead ends. Back up the browser
to make a new choice. The above rules are insufficent to solve the hardest
puzzles. You can guess or look for a third rule. This program will help you
find these most interesting places in the hardest puzzles without becomming a
mechanical master of the simpler logic.
<br><br>Each step has a unique url that you can bookmark or send to
friends. Use this <a href=${script}?${blank}>blank page</a> to enter new puzzles.
Contribute your insights and most diabolical puzzles to the
<a href=http://c2.com/cgi/wiki?SuDoku>SuDoku</a> page on my wiki.
</table><br>
<font color=gray size=-1>
©2005 Ward Cunningham
©2020 Ward Cunningham, Joshua Benuck, Eric Dobbs, Beth Long
`);