Created
August 21, 2018 11:56
-
-
Save timiles/a1dcc6e2922e2ecdae11202863a10477 to your computer and use it in GitHub Desktop.
KenKen is a Sudoku-like puzzle. I solved one just by lots of guessing, and was surprised that I got it perfectly right first time. I wondered if actually there were many solutions and I had found just one. So I wrote a bit of code, and actually it turns out I was just lucky. I think KenKen is a stupid puzzle that requires brute forcing rather th…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// These values are specific to the problem I was solving | |
const GRID_SIZE = 6; | |
const BLOCK_CELL_INDICES = [[0, 6], [1, 2], [3, 4], [5, 11], [7, 13], [8, 14], [9, 15], [10, 16], | |
[12, 18], [17, 23], [19, 20], [21, 22], [24, 25], [26, 32], [27, 33], [28, 29], [30, 31], [34, 35]]; | |
const BLOCK_RULES = [[1, '-'], [3, '/'], [4, '-'], [4, '-'], [4, '-'], [1, '-'], [5, '+'], [2, '-'], [10, '*'], | |
[2, '-'], [2, '/'], [2, '-'], [6, '*'], [1, '-'], [3, '-'], [2, '/'], [4, '-'], [3, '-']]; | |
// The rest of the code from here should work for any KenKen | |
const operatorFuncs = new Map(); | |
operatorFuncs.set('+', (a, b) => (a + b)); | |
operatorFuncs.set('-', (a, b) => (a - b)); | |
operatorFuncs.set('*', (a, b) => (a * b)); | |
operatorFuncs.set('/', (a, b) => (a / b)); | |
function isRuleSatisfied(a, b, c, operator) { | |
const func = operatorFuncs.get(operator); | |
return (func(a, b) === c || func(b, a) === c); | |
} | |
function isGridValid(grid) { | |
// Scan horizontally for duplicates | |
for (let y = 0; y < GRID_SIZE; y++) { | |
const numbersSeen = []; | |
for (let x = 0; x < GRID_SIZE; x++) { | |
const number = grid[x + (y * GRID_SIZE)]; | |
if (number > 0 && numbersSeen.indexOf(number) >= 0) { | |
return false; | |
} | |
numbersSeen.push(number); | |
} | |
} | |
// Scan vertically for duplicates | |
for (let x = 0; x < GRID_SIZE; x++) { | |
const numbersSeen = []; | |
for (let y = 0; y < GRID_SIZE; y++) { | |
const number = grid[x + (y * GRID_SIZE)]; | |
if (number > 0 && numbersSeen.indexOf(number) >= 0) { | |
return false; | |
} | |
numbersSeen.push(number); | |
} | |
} | |
// Scan blocks for rules | |
for (let i = 0; i < BLOCK_CELL_INDICES.length; i++) { | |
const cellIndices = BLOCK_CELL_INDICES[i]; | |
const a = grid[cellIndices[0]]; | |
const b = grid[cellIndices[1]]; | |
if (a > 0 && b > 0 && !isRuleSatisfied(a, b, BLOCK_RULES[i][0], BLOCK_RULES[i][1])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function step(grid, index) { | |
if (index >= grid.length) { | |
// We have completed the grid :) | |
return grid; | |
} | |
for (let i = 0; i < GRID_SIZE; i++) { | |
grid[index] = i + 1; | |
if (isGridValid(grid)) { | |
try { | |
return step(grid, index + 1); | |
} | |
catch { } | |
} | |
} | |
// We have hit a dead end. Reset this cell and backtrack our recursion by throwing an exception | |
grid[index] = 0; | |
throw 'up'; | |
} | |
function solve() { | |
// Initialise empty grid | |
const grid = new Array(GRID_SIZE * GRID_SIZE); | |
for (let i = 0; i < grid.length; i++) { | |
grid[i] = 0; | |
} | |
// Start filling up grid | |
const completedGrid = step(grid, 0); | |
// Write out completed grid in a nice way | |
let gridDisplay = ''; | |
for (let i = 0; i < completedGrid.length; i++) { | |
gridDisplay += completedGrid[i] + ','; | |
if ((i + 1) % GRID_SIZE === 0) { | |
gridDisplay += '\n'; | |
} | |
} | |
console.log(gridDisplay); | |
} | |
solve(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
KenKen is a Sudoku-like puzzle. I solved one just by lots of guessing, and was surprised that I got it perfectly right first time. I wondered if actually there were many solutions and I had found just one. So I wrote a bit of code, and actually it turns out I was just lucky. I think KenKen is a stupid puzzle that requires brute forcing rather than logic to solve. The code took me just over an hour to write so there may be bugs.