Skip to content

Instantly share code, notes, and snippets.

@amacleod
Forked from anonymous/index.html
Created January 4, 2016 02:48
Show Gist options
  • Save amacleod/4f73e8fefdf821d0183c to your computer and use it in GitHub Desktop.
Save amacleod/4f73e8fefdf821d0183c to your computer and use it in GitHub Desktop.
Recursive Letter Sudoku // source https://jsbin.com/gazihu
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-2.1.4.js"></script>
<meta charset="utf-8">
<title>Recursive Letter Sudoku</title>
<style id="jsbin-css">
.letter-grid-box {
width: 30px;
text-align: center;
}
.neighbor-display {
text-align: center;
}
</style>
</head>
<body>
<div id="letter-template-input-grid">
<h3>Starting Letters</h3>
<table border-width="1">
<tr>
<td><input id="letter-northwest" value="A" class="letter-grid-box"/></td>
<td><input id="letter-north" value="N" class="letter-grid-box"/></td>
<td><input id="letter-northeast" value="B" class="letter-grid-box"/></td>
</tr>
<tr>
<td><input id="letter-west" value="W" class="letter-grid-box"/></td>
<td><input id="letter-middle" value="O" class="letter-grid-box"/></td>
<td><input id="letter-east" value="E" class="letter-grid-box"/></td>
</tr>
<tr>
<td><input id="letter-southwest" value="C" class="letter-grid-box"/></td>
<td><input id="letter-south" value="S" class="letter-grid-box"/></td>
<td><input id="letter-southeast" value="D" class="letter-grid-box"/></td>
</tr>
</table>
</div>
<div id="word-input">
<h3>Word</h3>
<input id="word" value="snowed"/>
<button onClick="analyze();">Ok</button>
</div>
<div id="word-neighbor-grid">
<h3>Neighbors</h3>
<table border="true">
<tr>
<td id="neighbor-northwest" class="neighbor-display"></td>
<td id="neighbor-north" class="neighbor-display"></td>
<td id="neighbor-northeast" class="neighbor-display"></td>
</tr>
<tr>
<td id="neighbor-west" class="neighbor-display"></td>
<td id="neighbor-self" class="neighbor-display"></td>
<td id="neighbor-east" class="neighbor-display"></td>
</tr>
<tr>
<td id="neighbor-southwest" class="neighbor-display"></td>
<td id="neighbor-south" class="neighbor-display"></td>
<td id="neighbor-southeast" class="neighbor-display"></td>
</tr>
</table>
</div>
<div id="analysis-message-area">
<h3>Analysis</h3>
<ul id="analysis-messages">
<li>Waiting for input.</li>
</ul>
</div>
<script id="jsbin-javascript">
function analyze() {
var messages = new Messages();
var grid = new Grid(messages);
var word = $('#word').val().toUpperCase();
messages.log("Word is " + word + ".");
var letters = word.split("");
$('#neighbor-northwest').html(grid.neighbor(letters, -1, -1));
$('#neighbor-north').html(grid.neighbor(letters, -1, 0));
$('#neighbor-northeast').html(grid.neighbor(letters, -1, 1));
$('#neighbor-west').html(grid.neighbor(letters, 0, -1));
$('#neighbor-self').html(grid.neighbor(letters, 0, 0));
$('#neighbor-east').html(grid.neighbor(letters, 0, 1));
$('#neighbor-southwest').html(grid.neighbor(letters, 1, -1));
$('#neighbor-south').html(grid.neighbor(letters, 1, 0));
$('#neighbor-southeast').html(grid.neighbor(letters, 1, 1));
}
function Messages() {
var self = this;
self.output = $('#analysis-messages');
self.output.empty();
}
Messages.prototype.log = function(message) {
var self = this;
self.output.append("<li>" + message + "</li>");
};
function Grid(messages) {
var self = this;
self.messages = messages;
var result = [[], [], []];
result[0][0] = $('#letter-northwest').val();
result[0][1] = $('#letter-north').val();
result[0][2] = $('#letter-northeast').val();
result[1][0] = $('#letter-west').val();
result[1][1] = $('#letter-middle').val();
result[1][2] = $('#letter-east').val();
result[2][0] = $('#letter-southwest').val();
result[2][1] = $('#letter-south').val();
result[2][2] = $('#letter-southeast').val();
self.grid = result;
self.table = {};
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var letter = self.grid[row][col];
self.table[letter] = {row: row, col: col};
}
}
}
Grid.prototype.log = function(message) {
var self = this;
self.messages.log(message);
};
/**
* Find one neighbor sequence for a sequence of letters from
* the grid.
* @param {array} letters - sequence of grid letters.
* @param {number} rowDelta - row offset: negative is up, positive is down.
* @param {number} colDelta - column offset: negative is left, positive is right.
*/
Grid.prototype.neighbor = function(letters, rowDelta, colDelta) {
var self = this;
self.log("Finding neighbor at (" + rowDelta + ", " + colDelta + ").");
var sequence = neighborSequence(self, letters, rowDelta, colDelta);
if (sequence) {
return sequence.join("");
} else {
return "&oslash;";
}
};
/**
* Given a sequence of letters that specifies fractally subdivided
* grid coordinates, find its neighbors. Coordinates near the edge
* of the grossest grid might have empty neighbors, since the
* topmost grid does have actual edges.
*/
function neighborSequence(self, letters, rowDelta, colDelta) {
if (letters.length < 1) {
return null;
}
if (rowDelta === 0 && colDelta === 0) {
return letters;
}
var last = letters[letters.length - 1];
var row = self.row(last) + rowDelta;
var col = self.col(last) + colDelta;
var finial = self.letterWrap(row, col);
/* Calculate the deltas of the grosser grid. */
var grossRowDelta = gridDirection(row);
var grossColDelta = gridDirection(col);
var startingStem = letters.slice(0, -1);
var result;
if (grossRowDelta === 0 && grossColDelta === 0) {
result = startingStem.slice();
result.push(finial);
return result;
} else {
var stem = neighborSequence(self, startingStem, grossRowDelta, grossColDelta);
if (stem) {
self.log(startingStem.join("") + " => " + stem.join(""));
result = stem.slice(); // Shallow copy.
result.push(finial);
return result;
} else {
return null;
}
}
}
/**
* Tell whether a grid index would fall off the local grid, and if
* so which direction. A result of -1 indicates "up" or "left", and
* 1 indicates "down" or "right".
*/
function gridDirection(index) {
if (index < 0) {
return -1;
}
if (index >= 3) {
return 1;
}
return 0;
}
/**
* Find the letter corresponding to row and column, allowing for
* edge "wrapping" behavior due to grids lying adjacent to each
* other.
*/
Grid.prototype.letterWrap = function(row, col) {
var self = this;
// Adding three to avoid modulo on negative numbers, since I forget how that behaves in JS. ~ACM
var r = (row + 3) % 3;
var c = (col + 3) % 3;
return self.grid[r][c];
};
/**
* Look up row by letter, which must match one of the letters of
* the original grid.
*/
Grid.prototype.row = function(letter) {
var self = this;
return self.table[letter].row;
};
/**
* Look up column by letter, which must match one of the letters
* from the original grid.
*/
Grid.prototype.col = function(letter) {
var self = this;
return self.table[letter].col;
};
</script>
<script id="jsbin-source-css" type="text/css">.letter-grid-box {
width: 30px;
text-align: center;
}
.neighbor-display {
text-align: center;
}</script>
</body>
</html>
.letter-grid-box {
width: 30px;
text-align: center;
}
.neighbor-display {
text-align: center;
}
function analyze() {
var messages = new Messages();
var grid = new Grid(messages);
var word = $('#word').val().toUpperCase();
messages.log("Word is " + word + ".");
var letters = word.split("");
$('#neighbor-northwest').html(grid.neighbor(letters, -1, -1));
$('#neighbor-north').html(grid.neighbor(letters, -1, 0));
$('#neighbor-northeast').html(grid.neighbor(letters, -1, 1));
$('#neighbor-west').html(grid.neighbor(letters, 0, -1));
$('#neighbor-self').html(grid.neighbor(letters, 0, 0));
$('#neighbor-east').html(grid.neighbor(letters, 0, 1));
$('#neighbor-southwest').html(grid.neighbor(letters, 1, -1));
$('#neighbor-south').html(grid.neighbor(letters, 1, 0));
$('#neighbor-southeast').html(grid.neighbor(letters, 1, 1));
}
function Messages() {
var self = this;
self.output = $('#analysis-messages');
self.output.empty();
}
Messages.prototype.log = function(message) {
var self = this;
self.output.append("<li>" + message + "</li>");
};
function Grid(messages) {
var self = this;
self.messages = messages;
var result = [[], [], []];
result[0][0] = $('#letter-northwest').val();
result[0][1] = $('#letter-north').val();
result[0][2] = $('#letter-northeast').val();
result[1][0] = $('#letter-west').val();
result[1][1] = $('#letter-middle').val();
result[1][2] = $('#letter-east').val();
result[2][0] = $('#letter-southwest').val();
result[2][1] = $('#letter-south').val();
result[2][2] = $('#letter-southeast').val();
self.grid = result;
self.table = {};
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 3; col++) {
var letter = self.grid[row][col];
self.table[letter] = {row: row, col: col};
}
}
}
Grid.prototype.log = function(message) {
var self = this;
self.messages.log(message);
};
/**
* Find one neighbor sequence for a sequence of letters from
* the grid.
* @param {array} letters - sequence of grid letters.
* @param {number} rowDelta - row offset: negative is up, positive is down.
* @param {number} colDelta - column offset: negative is left, positive is right.
*/
Grid.prototype.neighbor = function(letters, rowDelta, colDelta) {
var self = this;
self.log("Finding neighbor at (" + rowDelta + ", " + colDelta + ").");
var sequence = neighborSequence(self, letters, rowDelta, colDelta);
if (sequence) {
return sequence.join("");
} else {
return "&oslash;";
}
};
/**
* Given a sequence of letters that specifies fractally subdivided
* grid coordinates, find its neighbors. Coordinates near the edge
* of the grossest grid might have empty neighbors, since the
* topmost grid does have actual edges.
*/
function neighborSequence(self, letters, rowDelta, colDelta) {
if (letters.length < 1) {
return null;
}
if (rowDelta === 0 && colDelta === 0) {
return letters;
}
var last = letters[letters.length - 1];
var row = self.row(last) + rowDelta;
var col = self.col(last) + colDelta;
var finial = self.letterWrap(row, col);
/* Calculate the deltas of the grosser grid. */
var grossRowDelta = gridDirection(row);
var grossColDelta = gridDirection(col);
var startingStem = letters.slice(0, -1);
var result;
if (grossRowDelta === 0 && grossColDelta === 0) {
result = startingStem.slice();
result.push(finial);
return result;
} else {
var stem = neighborSequence(self, startingStem, grossRowDelta, grossColDelta);
if (stem) {
self.log(startingStem.join("") + " => " + stem.join(""));
result = stem.slice(); // Shallow copy.
result.push(finial);
return result;
} else {
return null;
}
}
}
/**
* Tell whether a grid index would fall off the local grid, and if
* so which direction. A result of -1 indicates "up" or "left", and
* 1 indicates "down" or "right".
*/
function gridDirection(index) {
if (index < 0) {
return -1;
}
if (index >= 3) {
return 1;
}
return 0;
}
/**
* Find the letter corresponding to row and column, allowing for
* edge "wrapping" behavior due to grids lying adjacent to each
* other.
*/
Grid.prototype.letterWrap = function(row, col) {
var self = this;
// Adding three to avoid modulo on negative numbers, since I forget how that behaves in JS. ~ACM
var r = (row + 3) % 3;
var c = (col + 3) % 3;
return self.grid[r][c];
};
/**
* Look up row by letter, which must match one of the letters of
* the original grid.
*/
Grid.prototype.row = function(letter) {
var self = this;
return self.table[letter].row;
};
/**
* Look up column by letter, which must match one of the letters
* from the original grid.
*/
Grid.prototype.col = function(letter) {
var self = this;
return self.table[letter].col;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment