Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert server-side javascript to run client-side #1

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions sudokant.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@

<html>
<head>
<meta name="robots" content="noindex,nofollow">
</head>
<body>
<script>

const script = "sudoku.html"; // my $script = $ENV{SCRIPT_NAME}; $script =~ s/.*\///;
const blank = ".................................................................................";
const givensString = (location.search.replace('?','') + 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="?${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);
}

</script>
<style>
a {text-decoration: none;}
</style>
<center><br>
<div id=output></div>
<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=?>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>
&copy;2005 Ward Cunningham
&copy;2020 Ward Cunningham, Joshua Benuck, Eric Dobbs, Beth Long
<script>
output.innerHTML = board
</script>
</body>
</html>