// The following code contains unit test function that test the functionality
// of the above classes and functions.
// Test 1 runs the NextLocation on a map with some occupied locations and checks
// if it returns the index of the first empty location.
function test1() {
let map = new Map_Backtracking.Map([[1, 2, 3, 4, 0, 0, 0, 0]], 8);
let actual = new EightQueens(map).domain.getNextLocation().getIndices().i;
let expected = 4;
compareAndReport('Test 1', actual, expected);
}
// Test 2 runs the NextLocation on a map with all locations occupied and checks
// if it returns null.
function test2() {
let map = new Map_Backtracking.Map([[1, 2, 3, 4, 5, 6, 7, 8]], 8);
let actual = new EightQueens(map).domain.getNextLocation();
let expected = null;
compareAndReport('Test 2', actual, expected);
}
// Test 3 runs the NextCandidate on a map with some occupied locations and checks
// if it returns the next valid candidate for a specified location. The test also
// checks if the returned candidate does not violate the rules of the Eight Queens
// puzzle (i.e., no two queens threaten each other).
function test3() {
let map = new Map_Backtracking.Map([[1, 3, 0, 0, 0, 0, 0, 0]], 8);
let actual = new EightQueens(map).domain.getNextCandidate(
new EightQueens.Domain.Location(map, 2));
let expected = 5;
// 1 3 5 0 0 0 0 0
// Q 0 0 0 0 0 0 0 1
// 0 0 0 0 0 0 0 0 2
// 0 Q 0 0 0 0 0 0 3
// 0 0 0 0 0 0 0 0 4
// 0 0 Q 0 0 0 0 0 5
compareAndReport('Test 3', actual, expected);
}
// Test 4 runs the NextCandidate on a map where the specified location has no
// valid candidates and checks if it returns AI::Map<int>::EMPTY to indicate
// that no candidate is found.
function test4() {
let map = new Map_Backtracking.Map([[1, 2, 4, 8, 0, 0, 0, 0]], 8);
let actual = new EightQueens(map).domain.getNextCandidate(
new EightQueens.Domain.Location(map, 3));
let expected = 0;
compareAndReport('Test 4', actual, expected);
}
// Test 5 runs the Backtracking algorithm on an empty map and checks if it
// finds a valid solution.
function test5() {
let map = new Map_Backtracking.Map([[0, 0, 0, 0, 0, 0, 0, 0]], 8);
new EightQueens(map).run();
let actual = map.toString();
let expected = '1,5,8,6,3,7,2,4';
// 1 5 8 6 3 7 2 4
// Q • • • • • • • 1
// • • • • • • Q • 2
// • • • • Q • • • 3
// • • • • • • • Q 4
// • Q • • • • • • 5
// • • • Q • • • • 6
// • • • • • Q • • 7
// • • Q • • • • • 8
compareAndReport('Test 5', actual, expected);
}
// Test 6 runs the Backtracking algorithm twice on the same map. The first run
// should find a solution and fill the map with it. The second run should find
// the next solution and fill the map with it. The test checks if the second
// solution is different from the first one.
function test6() {
let map = new Map_Backtracking.Map([[0, 0, 0, 0, 0, 0, 0, 0]], 8);
let eightQueens = new EightQueens(map);
eightQueens.run();
eightQueens.run();
let actual = map.toString();
let expected = '1,6,8,3,7,4,2,5';
// 1 6 8 3 7 4 2 5
// Q • • • • • • • 1
// • • • • • • Q • 2
// • • • Q • • • • 3
// • • • • • Q • • 4
// • • • • • • • Q 5
// • Q • • • • • • 6
// • • • • Q • • • 7
// • • Q • • • • • 8
compareAndReport('Test 6', actual, expected);
}
// Test 7 runs the Backtracking algorithm multiple times to checks if it finds
// 10 first solutions of the Eight Queens puzzle.
function test7() {
let map = new Map_Backtracking.Map([[0, 0, 0, 0, 0, 0, 0, 0]], 8);
let eightQueens = new EightQueens(map);
let actual = '';
let i = 0;
while (eightQueens.run() && ++i <= 10)
actual += '' + (i-1) + ': ' + map.toString() + '\n';
let expected =
`0: 1,5,8,6,3,7,2,4
1: 1,6,8,3,7,4,2,5
2: 1,7,4,6,8,2,5,3
3: 1,7,5,8,2,4,6,3
4: 2,4,6,8,3,1,7,5
5: 2,5,7,1,3,8,6,4
6: 2,5,7,4,1,8,6,3
7: 2,6,1,7,4,8,3,5
8: 2,6,8,3,1,4,7,5
9: 2,7,3,6,8,5,1,4
`;
compareAndReport('Test 7', actual, expected);
}
// Test 8 runs the NextLocation for Sudoku on a 9x9 map with one empty cell and
// checks if it returns the index of that empty cell.
function test8() {
let size = 9;
let map = new Map_Backtracking.Map([
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 0, 1, 1, 1, 1], // <--
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1]
], size, size);
let indices = new Sudoku(map).domain.getNextLocation().getIndices();
let actual = indices.i + ',' + indices.j;
let expected = '4,5';
compareAndReport('Test 8', actual, expected);
}
// Test 9 runs the NextCandidate on a 9x9 map with one empty cell and checks if it
// returns the next valid candidate for that cell. The test also checks if the
// returned candidate does not violate the rules of Sudoku (i.e., no duplicate
// numbers in the same row, column, or 3x3 subgrid).
function test9() {
let size = 9;
let map = new Map_Backtracking.Map([
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 5, 1, 1, 1],
[1, 1, 1, 1, 6, 1, 1, 1, 1],
[1, 4, 1, 1, 1, 3, 1, 2, 1], // <--
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1]
], size, size);
let actual = new Sudoku(map).domain.getNextCandidate(
new Sudoku.Domain.Location(map, 5, 4));
let expected = 7;
compareAndReport('Test 9', actual, expected);
}
// Test 10 runs the Backtracking algorithm on an empty 9x9 map and checks if it
// finds a valid solution that satisfies the rules of Sudoku. The test also checks
// if the solution is correct by comparing the output with a known valid solution.
function test10() {
let size = 9;
let map = new Map_Backtracking.Map([
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0]
], size, size);
new Sudoku(map).run();
let actual = map.toString();
let expected = '\
1,2,3,4,5,6,7,8,9\n\
4,5,6,7,8,9,1,2,3\n\
7,8,9,1,2,3,4,5,6\n\
2,1,4,3,6,5,8,9,7\n\
3,6,5,8,9,7,2,1,4\n\
8,9,7,2,1,4,3,6,5\n\
5,3,1,6,4,2,9,7,8\n\
6,4,2,9,7,8,5,3,1\n\
9,7,8,5,3,1,6,4,2';
compareAndReport('Test 10', actual, expected);
}