Last active
September 28, 2020 13:34
-
-
Save Lumexralph/8705843450b31f75f727316956747d8b to your computer and use it in GitHub Desktop.
Write a sudoku validator: // 1. The `solution_valid(board)` function should return True when the // solution is True, False otherwise. The cells of the sudoku board may // also contain 0's, which represent empty cells. Boards with empty cells // are invalid of course. For the standard rules see // https://en.wikipedia.org/wiki/Sudoku // 2. Divid…
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
// SETUP! DO NOT TOUCH! | |
const Mocha = require('mocha') | |
const chai = require('chai') | |
const { expect } = chai | |
const mocha = new Mocha() | |
mocha.suite.emit('pre-require', this, 'solution', mocha) | |
// END OF SETUP | |
// =========================================================================== | |
// PUZZLE 2 | |
// Write a sudoku validator: | |
// 1. The `solution_valid(board)` function should return True when the | |
// solution is True, False otherwise. The cells of the sudoku board may | |
// also contain 0's, which represent empty cells. Boards with empty cells | |
// are invalid of course. For the standard rules see | |
// https://en.wikipedia.org/wiki/Sudoku | |
// 2. Divide the problem into subproblems, write separate functions for | |
// these. | |
// 3. Make sure to write some tests for these functions. | |
const rowCheck = (board) => { | |
if (board.length === 0) return false; | |
for (let row = 0; row < board.length; row += 1) { | |
if (board[row].length === 0) return false; | |
const uniqueRow = new Set(board[row]); | |
if (uniqueRow.size !== board[row].length) return false; | |
} | |
return true; | |
}; | |
const checkUniqueCol = (col) => { | |
const uniqueCol = new Set(col); | |
return uniqueCol.size === col.length; | |
}; | |
const colCheck = (board) => { | |
if (board.length === 0) return false; | |
let unique = false; | |
let colIndex = 0; | |
let rowIndex = 0; | |
let col = []; | |
while (colIndex < board.length) { | |
if (rowIndex >= board.length) { | |
// do a unique column check, reset rowIndex | |
// move to next column and empty the initial col | |
if (checkUniqueCol(col) === false) return false; | |
rowIndex = 0; | |
colIndex += 1; | |
col = []; | |
} | |
if (board[rowIndex].length === 0) return false; | |
col.push(board[rowIndex][colIndex]); | |
rowIndex += 1; | |
} | |
return true; | |
}; | |
const generateSubGridMap = (boardLength) => { | |
const subGridMap = {}; | |
for (let row = 0; row < boardLength; row += 1) { | |
const gridLabel = `subGrid${row+1}`; | |
if (subGridMap.gridLabel === undefined) { | |
subGridMap[gridLabel] = []; | |
} | |
} | |
return subGridMap; | |
}; | |
const fillSubGridMap = (board, subGridMap) => { | |
for (let row = 0; row < board.length; row += 1) { | |
if (row < 3) { | |
subGridMap.subGrid1 = [...subGridMap.subGrid1, ...board[row].slice(0, 3)]; | |
subGridMap.subGrid2 = [...subGridMap.subGrid2, ...board[row].slice(3, 6)]; | |
subGridMap.subGrid3 = [...subGridMap.subGrid3, ...board[row].slice(6, 9)]; | |
} else if (row < 6) { | |
subGridMap.subGrid4 = [...subGridMap.subGrid4, ...board[row].slice(0, 3)]; | |
subGridMap.subGrid5 = [...subGridMap.subGrid5, ...board[row].slice(3, 6)]; | |
subGridMap.subGrid6 = [...subGridMap.subGrid6, ...board[row].slice(6, 9)]; | |
} else { | |
subGridMap.subGrid7 = [...subGridMap.subGrid7, ...board[row].slice(0, 3)]; | |
subGridMap.subGrid8 = [...subGridMap.subGrid8, ...board[row].slice(3, 6)]; | |
subGridMap.subGrid9 = [...subGridMap.subGrid9, ...board[row].slice(6, 9)]; | |
} | |
} | |
return subGridMap; | |
}; | |
const checkSubGrid = (board) => { | |
const subGridMap = generateSubGridMap(board.length); | |
const filledSubGridMap = fillSubGridMap(board, subGridMap); | |
// check all the generated subGrids | |
for (const subGrid in filledSubGridMap) { | |
if (checkUniqueCol(subGridMap[subGrid]) === false) return false; | |
} | |
return true; | |
} | |
const validateSudoku = (board) => { | |
// Your solution | |
return colCheck(board) && rowCheck(board) && checkSubGrid(board) | |
} | |
// TESTS PUZZLE 2 | |
describe('Sudoku', () => { | |
it('should return true for a valid solution', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 5, 3, 4, 8], | |
[1, 9, 8, 3, 4, 2, 5, 6, 7], | |
[8, 5, 9, 7, 6, 1, 4, 2, 3], | |
[4, 2, 6, 8, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 8, 5, 6], | |
[9, 6, 1, 5, 3, 7, 2, 8, 4], | |
[2, 8, 7, 4, 1, 9, 6, 3, 5], | |
[3, 4, 5, 2, 8, 6, 1, 7, 9], | |
] | |
expect(validateSudoku(board)).to.equal(true) | |
}) | |
it('should return false when there are empty fields', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 0, 3, 4, 9], | |
[1, 0, 0, 3, 4, 2, 5, 6, 0], | |
[8, 5, 9, 7, 6, 1, 0, 2, 0], | |
[4, 2, 6, 8, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 8, 5, 6], | |
[9, 0, 1, 5, 3, 7, 2, 1, 4], | |
[2, 8, 7, 4, 1, 9, 6, 3, 5], | |
[3, 0, 0, 4, 8, 1, 1, 7, 9], | |
] | |
expect(validateSudoku(board)).to.equal(false) | |
}) | |
it('should return false when a column is invalid', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 5, 3, 4, 8], | |
[1, 9, 8, 3, 4, 2, 5, 6, 7], | |
[8, 5, 9, 7, 6, 1, 4, 2, 3], | |
[4, 2, 6, 8, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 5, 8, 6], | |
[9, 6, 1, 5, 3, 7, 2, 8, 4], | |
[2, 8, 7, 4, 1, 9, 6, 3, 5], | |
[3, 4, 5, 2, 8, 6, 1, 7, 9], | |
] | |
expect(validateSudoku(board)).to.equal(false) | |
}) | |
it('should return false when a row is invalid', () => { | |
const board = [ | |
[5, 3, 4, 8, 7, 6, 9, 1, 2], | |
[8, 7, 2, 1, 9, 5, 3, 4, 6], | |
[1, 9, 6, 3, 4, 2, 5, 8, 7], | |
[6, 4, 9, 7, 8, 1, 5, 2, 3], | |
[4, 2, 8, 6, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 6, 5, 8], | |
[9, 8, 1, 5, 3, 7, 2, 6, 4], | |
[2, 6, 7, 4, 1, 9, 8, 3, 5], | |
[3, 4, 5, 2, 6, 8, 1, 7, 9], | |
] | |
expect(validateSudoku(board)).to.equal(false) | |
}) | |
it('should return false when a block is invalid', () => { | |
const board = [ | |
[1, 2, 3, 4, 5, 6, 7, 8, 9], | |
[2, 3, 4, 5, 6, 7, 8, 9, 1], | |
[3, 4, 5, 6, 7, 8, 9, 1, 2], | |
[4, 5, 6, 7, 8, 9, 1, 2, 3], | |
[5, 6, 7, 8, 9, 1, 2, 3, 4], | |
[6, 7, 8, 9, 1, 2, 3, 4, 5], | |
[7, 8, 9, 1, 2, 3, 4, 5, 6], | |
[8, 9, 1, 2, 3, 4, 5, 6, 7], | |
[9, 1, 2, 3, 4, 5, 6, 7, 8], | |
] | |
expect(validateSudoku(board)).to.equal(false) | |
}) | |
}) | |
describe('rowCheck', () => { | |
it('should return true for a valid row', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 5, 3, 4, 8], | |
[1, 9, 8, 3, 4, 2, 5, 6, 7], | |
] | |
expect(rowCheck(board)).to.equal(true) | |
}) | |
it('should return false when there are empty blocks', () => { | |
const board = []; | |
expect(rowCheck(board)).to.equal(false) | |
}) | |
it('should return false when there are empty sub blocks', () => { | |
const board = [[], []]; | |
expect(rowCheck(board)).to.equal(false) | |
}) | |
it('should return false for a invalid row check', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 5, 8, 4, 8], | |
[1, 9, 8, 3, 4, 2, 5, 6, 7], | |
[8, 5, 9, 7, 6, 1, 4, 2, 3], | |
[4, 2, 6, 8, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 5, 8, 6], | |
[9, 6, 1, 5, 3, 7, 2, 8, 4], | |
[2, 8, 7, 4, 4, 9, 6, 3, 5], | |
[3, 4, 5, 2, 8, 6, 1, 7, 9], | |
]; | |
expect(rowCheck(board)).to.equal(false) | |
}) | |
}) | |
describe('colCheck', () => { | |
it('should return true for a valid column', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 5, 3, 4, 8], | |
[1, 9, 8, 3, 4, 2, 5, 6, 7], | |
[8, 5, 9, 7, 6, 1, 4, 2, 3], | |
[4, 2, 6, 8, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 8, 5, 6], | |
[9, 6, 1, 5, 3, 7, 2, 8, 4], | |
[2, 8, 7, 4, 1, 9, 6, 3, 5], | |
[3, 4, 5, 2, 8, 6, 1, 7, 9], | |
]; | |
expect(colCheck(board)).to.equal(true); | |
}) | |
it('should return false when there are empty blocks', () => { | |
const board = []; | |
expect(colCheck(board)).to.equal(false) | |
}) | |
it('should return false when there are empty sub blocks', () => { | |
const board = [[], []]; | |
expect(colCheck(board)).to.equal(false) | |
}) | |
it('should return false for a invalid column check', () => { | |
const board = [ | |
[5, 3, 4, 6, 7, 8, 9, 1, 2], | |
[6, 7, 2, 1, 9, 5, 3, 4, 8], | |
[1, 9, 8, 3, 4, 2, 5, 6, 7], | |
[8, 5, 9, 7, 6, 1, 4, 2, 3], | |
[4, 2, 6, 8, 5, 3, 7, 9, 1], | |
[7, 1, 3, 9, 2, 4, 5, 8, 6], | |
[9, 6, 1, 5, 3, 7, 2, 8, 4], | |
[2, 8, 7, 4, 1, 9, 6, 3, 5], | |
[3, 4, 5, 2, 8, 6, 1, 7, 9], | |
]; | |
expect(colCheck(board)).to.equal(false) | |
}) | |
}) | |
mocha.run() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment