Skip to content

Commit

Permalink
Require candidates, cols, rows to be in range and otherwise throw error
Browse files Browse the repository at this point in the history
  • Loading branch information
melusc committed Feb 8, 2022
1 parent 8ca2d0e commit 569c648
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 74 deletions.
22 changes: 19 additions & 3 deletions src/sudoku.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,28 @@ export class Sudoku {
const s = new Sudoku(size);

for (const [rowIndex, row] of cells.entries()) {
// Even though it would also throw in s.getCell
// this throws a more useful error
inRangeIncl(0, size - 1, rowIndex);

if (!row) {
continue;
}

for (const [colIndex, content] of row.entries()) {
inRangeIncl(0, size - 1, colIndex);

// prettier-ignore
const cellIndex = (rowIndex * size) + colIndex;
const cell = s.getCell(cellIndex);
if (isReadonlyArray(content)) {
for (const candidate of content) {
inRangeIncl(0, size - 1, candidate);
}

cell.candidates = new Set(content);
} else if (content !== undefined) {
s.setContent(cellIndex, content);
s.setContent(cell, content);
}
}
}
Expand Down Expand Up @@ -104,6 +114,10 @@ export class Sudoku {
throw new TypeError('Expected size to be a square of an integer.');
}

if (size <= 0) {
throw new TypeError(`Expected size (${size}) to be greater than 0.`);
}

this.blockWidth = blockWidth;

const amountCells = size ** 2;
Expand All @@ -116,14 +130,16 @@ export class Sudoku {

if (typeof content === 'number') {
if (Number.isInteger(content)) {
inRangeIncl(0, this.size - 1, content);

cell.setContent(content);
} else {
cell.clear();
throw new TypeError(`content was not an integer: ${content}`);
}
} else {
const index = Sudoku.alphabet.indexOf(content.toUpperCase());
if (index === -1) {
cell.clear();
throw new Error(`content was not in alphabet: "${content}"`);
} else {
cell.setContent(index);
}
Expand Down
98 changes: 49 additions & 49 deletions test/plugins/naked-pairs.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ test('nakedPairs should not change an empty sudoku.', t => {
test('nakedPairs should correctly find the pairs of "1" and "6".', t => {
const s = Sudoku.fromPrefilled(
[
[4, [1, 6], [1, 6], [7, 8], 3, 2, [1, 7, 8], 9, 5],
[4, [1, 6], [1, 6], [7, 8], 3, 2, [1, 7, 8], 0, 5],
// ^ ^ , ^ ^ ^ Remove this
],
9,
Expand All @@ -40,10 +40,10 @@ test('nakedPairs should not change anything upon finding ("1", "2", "5") across
const candidates = [
[1, 2, 5], // #1
[3, 6, 7, 8],
[1, 4, 6, 9],
[1, 4, 6, 0],
[1, 2, 5], // #2
[1, 2, 5, 6],
[4, 5, 9],
[4, 5, 0],
[1, 5, 7, 8],
[3, 5, 7],
[1, 4, 8],
Expand All @@ -69,13 +69,13 @@ test('nakedPairs should find an incomplete naked pair', t => {
[
[1, 2, 4], // #1
[1, 2, 4], // #2
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 4], // #3, missing 2, though
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
],
],
9,
Expand All @@ -88,13 +88,13 @@ test('nakedPairs should find an incomplete naked pair', t => {
[
[1, 2, 4], // #1
[1, 2, 4], // #2
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[1, 4], // #3
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
],
);
});
Expand All @@ -106,14 +106,14 @@ test('nakedPairs should find an incomplete naked pair with incomplete cell as fi
[
[
[1, 4], // #1, missing 2, though
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 4], // #2
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 4], // #3
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
],
],
9,
Expand All @@ -125,14 +125,14 @@ test('nakedPairs should find an incomplete naked pair with incomplete cell as fi
s.getRow(0).map(({candidates}) => [...candidates]),
[
[1, 4], // #1
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[1, 2, 4], // #2
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[1, 2, 4], // #3
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
],
);
});
Expand All @@ -144,14 +144,14 @@ test('nakedPairs should find an incomplete naked pair with multiple incomplete c
[
[
[1, 4], // #1, missing 2
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2], // #2, missing 4
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[2, 4], // #3, missing 1
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
],
],
9,
Expand All @@ -163,14 +163,14 @@ test('nakedPairs should find an incomplete naked pair with multiple incomplete c
s.getRow(0).map(({candidates}) => [...candidates]),
[
[1, 4], // #1
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[1, 2], // #2
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[2, 4], // #3
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 9],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
[3, 5, 6, 7, 8, 0],
],
);
});
Expand All @@ -182,14 +182,14 @@ test('nakedPairs with incomplete cells that do not overlap much', t => {
[
[
[1, 4], // #1, missing 2, 3; doesn't overlap with #2
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[2, 3], // #2, missing 1, 4
[1, 3], // #3, missing 2, 4
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[2, 4], // #4, missing 1, 3
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
[1, 2, 3, 4, 5, 6, 7, 8, 0],
],
],
9,
Expand All @@ -200,14 +200,14 @@ test('nakedPairs with incomplete cells that do not overlap much', t => {
s.getRow(0).map(({candidates}) => [...candidates]),
[
[1, 4], // #1
[5, 6, 7, 8, 9],
[5, 6, 7, 8, 0],
[2, 3], // #2
[1, 3], // #3
[5, 6, 7, 8, 9],
[5, 6, 7, 8, 0],
[2, 4], // #4
[5, 6, 7, 8, 9],
[5, 6, 7, 8, 9],
[5, 6, 7, 8, 9],
[5, 6, 7, 8, 0],
[5, 6, 7, 8, 0],
[5, 6, 7, 8, 0],
],
);
});
32 changes: 16 additions & 16 deletions test/plugins/pointing-arrows.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ test('pointingArrows should not change an empty sudoku.', t => {
test('pointingArrows should find a pointing arrow of 3s.', t => {
const s = Sudoku.fromPrefilled(
[
[[2, 4, 5, 8], 1, 7, 9, [2, 4, 5], 3, 6, [4, 8], [2, 4, 8]],
[[2, 4, 5, 8], 1, 7, 0, [2, 4, 5], 3, 6, [4, 8], [2, 4, 8]],
[
[2, 3, 4, 5, 6], // Remove "3" from here
[2, 3, 4, 5], // And here
[3, 6], // And here
[1, 2, 5, 7],
8,
[5, 7],
[1, 3, 9], // Pointing arrow here
[1, 4, 9],
[1, 2, 3, 4, 9], // And here
[1, 3, 0], // Pointing arrow here
[1, 4, 0],
[1, 2, 3, 4, 0], // And here
],
[9, [2, 3, 4, 8], [3, 6, 8], [1, 2], [2, 4, 6], [4, 6], 5, [1, 4, 8], 7],
[0, [2, 3, 4, 8], [3, 6, 8], [1, 2], [2, 4, 6], [4, 6], 5, [1, 4, 8], 7],
],
9,
);
Expand All @@ -53,33 +53,33 @@ test('pointingArrows should find a pointing arrow of 2s.', t => {
[
[
7,
[2, 3, 4, 8, 9], // Remove "2" from here
[2, 3, 4, 8, 0], // Remove "2" from here
1,
[2, 8], // Pointing arrow here
[2, 4, 9], // And here
[4, 8, 9],
[3, 8, 9],
[2, 4, 0], // And here
[4, 8, 0],
[3, 8, 0],
6,
5,
],
[
[2, 4, 6, 8],
[2, 4, 8, 9],
[6, 8, 9],
[2, 4, 8, 0],
[6, 8, 0],
[5, 7],
3,
[5, 7, 8],
[1, 8, 9],
[1, 4, 8, 9],
[1, 4, 8, 9],
[1, 8, 0],
[1, 4, 8, 0],
[1, 4, 8, 0],
],
[[3, 4, 8], [3, 4, 8, 9], 5, 6, [4, 9], 1, 7, 2, [3, 4, 8, 9]],
[[3, 4, 8], [3, 4, 8, 0], 5, 6, [4, 0], 1, 7, 2, [3, 4, 8, 0]],
],
9,
);

pointingArrows(s);
t.true(s.anyChanged);

t.deepEqual([...s.getCell(1).candidates], [3, 4, 8, 9]);
t.deepEqual([...s.getCell(1).candidates], [3, 4, 8, 0]);
});
Loading

0 comments on commit 569c648

Please sign in to comment.