Sudoku solver in Javascript using backtracking and recursion - javascript
I try to write a sudoku solver in Javascript but can't seem to make it work.
Every time my solve function returns undefined, it seems that when the code meets a dead end, it does not try another z in the previous function called and just gives up at some point after multiple tries on the same case
var solve = () => {
//iterate through the lines of the grid
for (y = 0; y < 9; y++) {
//iterate through each column of the grid
for (x = 0; x < 9; x++) {
//if a case is empty, we can try some numbers
if (grid[y][x] === "") {
//our answer must be between 1 to 9 to be correct
for (z = 1; z < 10; z++) {
if (possible(x, y, z)) {
grid[y][x] = z.toString();
solve();
if (isComplete()) {
return grid;
}
else {
grid[y][x] = "";
}
}
}
//if there is no answer, we go back to our precedent function call and try another number
return;
}
}
}
}
//get all the values of the vertical line of a particular value
var getVerticalLine = (x, y) => {
let verticalLine = [];
//iterate through every line of the grid and add the value at the index except the one from the line where the value is taken from
for (let line of grid) {
if (line != grid[y]) {
verticalLine.push(line[x]);
}
}
return verticalLine;
}
var getSquareValues = (x, y) => {
let squareValue = [];
//check in which square our value is and create an array with each value from the square except our own
if (x < 3 && y < 3) {
//iterate through line 1 to 3
for (let line = 0; line < 3; line++) {
//iterate through columns 1 to 3
for (let column = 0; column < 3; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 6 && y < 3) {
//iterate through line 1 to 3
for (let line = 0; line < 3; line++) {
//iterate through columns 4 to 6
for (let column = 3; column < 6; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 9 && y < 3) {
//iterate through line 1 to 3
for (let line = 0; line < 3; line++) {
//iterate through columns 6 to 9
for (let column = 6; column < 9; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 3 && y < 6) {
//iterate through line 4 to 6
for (let line = 4; line < 7; line++) {
//iterate through columns 1 to 3
for (let column = 0; column < 3; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 6 && y < 6) {
//iterate through line 4 to 6
for (let line = 3; line < 6; line++) {
//iterate through columns 4 to 6
for (let column = 4; column < 6; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 9 && y < 6) {
//iterate through line 4 to 6
for (let line = 3; line < 6; line++) {
//iterate through columns 6 to 9
for (let column = 6; column < 9; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 3 && y < 9) {
//iterate through line 6 to 9
for (let line = 6; line < 9; line++) {
//iterate through columns 1 to 3
for (let column = 0; column < 3; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 6 && y < 9) {
//iterate through line 6 to 9
for (let line = 6; line < 9; line++) {
//iterate through columns 1 to 3
for (let column = 3; column < 6; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else if (x < 9 && y < 9) {
//iterate through line 6 to 9
for (let line = 6; line < 9; line++) {
//iterate through columns 1 to 3
for (let column = 6; column < 9; column++) {
//check that we don't include our own value
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
} else {
return "Some fuckery went there";
}
}
var possible = (x, y, z) => {
x = x.toString();
y = y.toString();
z = z.toString();
if (!(grid[y].includes(z)) && !(getVerticalLine(x, y).includes(z)) && !(getSquareValues(x, y).includes(z))) {
return true;
}
else {
return false;
}
}
var isComplete = () => {
for (let y = 0; y < 9; y++) {
//iterate through each column of the grid
for (let x = 0; x < 9; x++) {
if (grid[y][x] === "") {
return false;
}
}
}
return true;
}
var setExemple1 = () => {
grid = [["3", "", "6", "5", "", "8", "4", "", ""],
["5", "2", "", "", "", "", "", "", ""],
["", "8", "7", "", "", "", "", "3", "1"],
["", "", "3", "", "1", "", "", "8", ""],
["9","", "", "8", "6", "3", "", "", "5"],
["", "", "", "", "9", "", "6", "", ""],
["1", "3", "", "", "", "", "2", "5", ""],
["", "", "", "", "", "", "", "7", 4],
["", "", "5", "2", "", "6", "3", "", ""]];
}
Thank you for your help !
EDIT : One of the problems was just that I forgot to declare my variables in my for loops ... I can't say how much time I spend looking at my code trying to understand where I did made a mistake when it was just this, thank you really much it seems to work better. I'm now able to complete the empty grid, there seems to be another problem trying to solve my example, I'll take a look into it
LAST EDIT : Finally made my code work ! There was a problem with my getSquareValues, at some point I made a mistake in the values used, there was a 4 and a 7 that I forgot instead of a 3 and a 6 and it made the function goes wrong :
//get all the values of the vertical line of a particular value
let getVerticalLine = (x, y) => {
let verticalLine = [];
//iterate through every line of the grid and add the value at the index except the one from the line where the value is taken from
for (let line of grid) {
if (line != grid[y]) {
verticalLine.push(line[x]);
}
}
return verticalLine;
}
let getSquareValues = (x, y) => {
let squareValue = [];
let bx = Math.floor(x / 3);
let by = Math.floor(y / 3);
for (let line = by * 3; line < by * 3 + 3; line++) {
for (let column = bx * 3; column < bx * 3 + 3; column++) {
if (!(line === y && column === x)) {
squareValue.push(grid[line][column]);
}
}
}
return squareValue;
}
let possible = (x, y, z) => {
x = x.toString();
y = y.toString();
z = z.toString();
if (!(grid[y].includes(z)) && !(getVerticalLine(x, y).includes(z)) && !(getSquareValues(x, y).includes(z))) {
return true;
}
else {
return false;
}
}
let isComplete = () => {
for (let y = 0; y < 9; y++) {
//iterate through each column of the grid
for (let x = 0; x < 9; x++) {
if (grid[y][x] === "") {
return false;
}
}
}
return true;
}
let solve = () => {
//iterate through the lines of the grid
for (let y = 0; y < 9; y++) {
//iterate through each column of the grid
for (let x = 0; x < 9; x++) {
//if a case is empty, we can try some numbers
if (grid[y][x] === "") {
//our answer must be between 1 to 9 to be correct
for (let z = 1; z < 10; z++) {
if (possible(x, y, z)) {
grid[y][x] = z.toString();
solve();
if (isComplete()) {
return grid;
}
else {
grid[y][x] = "";
}
}
}
//if there is no answer, we go back to our precedent function call and try another number
return;
}
}
}
}
let setExemple1 = () => {
grid = [
["3", "", "6", "5", "", "8", "4", "", ""],
["5", "2", "", "", "", "", "", "", ""],
["", "8", "7", "", "", "", "", "3", "1"],
["", "", "3", "", "1", "", "", "8", ""],
["9","", "", "8", "6", "3", "", "", "5"],
["", "5", "", "", "9", "", "6", "", ""],
["1", "3", "", "", "", "", "2", "5", ""],
["", "", "", "", "", "", "", "7", "4"],
["", "", "5", "2", "", "6", "3", "", ""]
];
}
let setExemple2 = () => {
grid = [
["", "", "", "2", "6", "", "7", "", "1"],
["6", "8", "", "", "7", "", "", "9", ""],
["1", "9", "", "", "", "4", "5", "", ""],
["8", "2", "", "1", "", "", "", "4", ""],
["", "", "4", "6", "", "2", "9", "", ""],
["", "5", "", "", "", "3", "", "2", "8"],
["", "", "9", "3", "", "", "", "7", "4"],
["", "4", "", "", "5", "", "", "3", "6"],
["7", "", "3", "", "1", "8", "", "", ""]
];
}
Related
Trying to find the index values of an array which consist of objects
why is it that i am unable to find the index values of the 'deck' array using deck[0] but this notation works for suits[0] I am trying to find the index values of my 'deck' array but i am unsure why i keep getting 'undefined'. var deck = []; var suits = ["diamonds","hearts","clubs","spades"]; var value = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]; function genDeck() { for(var i = 0; i < suits.length; i++) { for(var x = 0; x < value.length; x++){ var card = {Value:value[x], Suit:suits[i]}; deck.push(card); } } return deck; } window.onload = function () { genDeck(); }; var randomNum = Math.floor(Math.random() * 52);
You aren't adding anything to the deck array. You need to call deck.push(card) EDIT: Here's the working example code: var deck = []; var suits = ["diamonds","hearts","clubs","spades"]; var value = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"]; function genDeck() { for(var i = 0; i < suits.length; i++) { for(var x = 0; x < value.length; x++){ var card = {Value:value[x], Suit:suits[i]}; deck.push(card); } } return deck; } window.onload = function () { genDeck(); console.log('First Item: ', deck[0]) }; var randomNum = Math.floor(Math.random() * 52); Note that you have to call console.log after you've called genDeck in your window.onload function.
Concat multiple arrays into one array without duplicates [duplicate]
This question already has answers here: Get all unique values in a JavaScript array (remove duplicates) (91 answers) Closed 6 years ago. I want to push values of 3 arrays in a new array without repeating the same values var a = ["1", "2", "3"]; var b = ["3", "4", "5"]; var c = ["4", "5", "6"]; var d = []; function newArray(x, y, z) { for(var i = 0; i < d.length; i++) { if(d.length == -1) { d[i].push(a[i]) } } for(var i = 0; i < d.length; i++) { if(d.length == -1) { d[i].push(y[i]) } } for(var i = 0; i < d.length; i++) { if(d.length == -1) { d[i].push(z[i]) } } } newArray(a, b, c); d = ["1", "2", "3", "4", "5", "6"];
You can use concat() and Set together as below, var a = ["1","2","3"]; var b = ["3","4","5"]; var c = ["4","5","6"]; var d = a.concat(b).concat(c); var set = new Set(d); d = Array.from(set); console.log(d);
If your goal is to remove duplicates, you can use a set, var arr = [1, 2, 3, 4, 5, 5, 6, 6, 6, 7] var mySet = new Set(arr) var filteredArray = Array.from(mySet) console.log(filteredArray.sort()) // [1,2,3,4,5,6,7]
var a = ["1","2","3"] , b = ["3","4","5"] , c = ["4","5","6"] , d = []; function newArray(x,y,z) { x.concat(y,z).forEach(item =>{ if (d.indexOf(item) == -1) d.push(item); }); return d; } console.log(newArray(a,b,c));
You could save yourself some time and effort with the very useful utility library Lodash. The function you're looking for is Union As stated by Lodash: Creates an array of unique values, in order, from all given arrays using SameValueZero for equality comparisons. Example _.union([2], [1, 2]); // => [2, 1]
var a = ["1", "2", "3"]; var b = ["3", "4", "5"]; var c = ["4", "5", "6"]; var d = []; var hash = []; AddToHash(a); AddToHash(b); AddToHash(c); function AddToHash(arr) { for (var i = 0; i < arr.length; i++) { if (!hash[arr[i]]) { hash[arr[i]] = 1; } else hash[arr[i]] += 1; } } for (var i = 0; i < hash.length; i++) { d.push(i); } console.log(d); Hope this helps
Here is another version: var d = b.concat(c); d.forEach(function(el) { if (a.indexOf(el) === -1) { a.push(el) } }) ES6 version: let d = b.concat(c); d.forEach(el => { if (a.indexOf(el) === -1) { a.push(el) } })
loop minute in javascript
I have code like this: var hour = 7; for (var i = 0;i <= 1; i++ ){ var minute = 0; console.log((i + hour) % 24); } when I run it, I get result like this: 7 8 my question: how to add the value in format minute ex: 0-59 so I wanna loop the data like this: 7:0 7:1 7:2 s.d 7:59 8:0
You could use a new array to store all your unique values. You will need to look into the new "uniques" array, if the value alreay exists and then use the default value: var number= ["1", "2", "3", "4", "5", "6", "6"]; var default = 0; var uniques = []; var result = []; for(var i=0; i < number.length; i++) { if(!inArray(number[i], uniques) { uniques.push(number[i]); result.push(number[i]); console.log(number[i]); } else { console.log(default); result.push(default); } } function inArray(needle, haystack) { var length = haystack.length; for(var i = 0; i < length; i++) { if(haystack[i] == needle) return true; } return false; }
You could use Array#indexOf and check against the actual index. If you get the same index, then show the element, otherwise use a default value instead. var number= ["1", "2", "3", "4", "5", "6", "6"]; for (var i = 0; i < number.length;i++) { console.log(number.indexOf(number[i]) === i ? number[i] : undefined); }
Use map to get the new array, and in the callback store each item in a set to know if it's a duplicate or not. var number = ["1", "2", "3", "4", "5", "6", "6"]; var s = new Set(); console.log(number.map(n => s.has(n) ? undefined : s.add(n) && n)); If the non-equality of your values is respected by stringification, you can use a plain object, without needing ES6 features: var number = ["1", "2", "3", "4", "5", "6", "6"]; var s = Object.create(null); console.log(number.map(function(n) { if (n in s) return undefined; s[n] = true; return n; }));
Invalid left-hand side expression
I'm trying to figure out why the bottom function I've written isn't working properly. Whenever I try to test it out, I get the following error: Uncaught ReferenceError: Invalid left-hand side expression in postfix operation. I'm assuming it's because the code is failing to recognize the "x" string as being the same as the variable x once it's been stripped of it quotation marks when adding to the value of x. Can someone help me finesse this in a way to make it work? If not, can you suggest some alternate approach? Thanks in advance! var grid = [[null, null, null], [null, null, null], [null, null, null]]; function checkWin() { vals = ["x", "o"]; var x = 0; var o = 0; for (var k = 0; k < vals.length; k++) { var value = vals[k]; for (var i = 0; i < 3; i++) { if (grid[i][i] === value) { (value.replace(/['"]+/g, '')) ++; } if (grid[2 - i][i] === value) { (value.replace(/['"]+/g, '')) ++; } for (var j = 0; j < 3; j++) { if (grid[i][j] === value) { (value.replace(/['"]+/g, '')) ++; } if (grid[j][i] === value) { (value.replace(/['"]+/g, '')) ++; } } } } if (x === 3) { alert("X wins!"); } else if (o === 3) { alert("O wins!"); } }
The following uses objects. The different grid definitions were tested var grid = [ ["o", "x", "x"], ["o", "x", "x"], ["o", "", "o"]]; var grid = [ ["o", "x", ""], ["x", "x", "x"], ["o", "o", ""]]; var grid = [ ["x", "x", ""], ["o", "x", "o"], ["o", "o", "x"]]; var grid = [ ["x", "x", "o"], ["x", "o", "x"], ["o", "x", "x"]]; checkWin(grid) function checkWin(grid) { var vals = [{player: "x", value: 0}, {player: "o", value: 0}]; for (var k = 0; k < vals.length; k++) { for (var i = 0; i < 3; i++) { // check win by row vals[k].value = 0; // check win by col for (var j = 0; j < 3; j++) { if (grid[i][j] === vals[k].player) { vals[k].value++; } } if (vals[k].value === 3) { alert(vals[k].player + " wins by row " + (i+1)); return vals[k].player; } // check win by col vals[k].value = 0; for (var j = 0; j < 3; j++) { // check col if (grid[j][i] === vals[k].player) { vals[k].value++; if (vals[k].value === 3) { // break if you want to know what column won by break; } } } if (vals[k].value === 3) { alert(vals[k].player + " wins by col " + (i+1)); return vals[k].player; } } } // check win by diag l to r for (var k = 0; k < vals.length; k++) { vals[k].value = 0; for (var i = 0; i < 3; i++) { if (grid[i][i] === vals[k].player) { vals[k].value++; } } if (vals[k].value === 3) { alert(vals[k].player + " wins by diag left to right!"); return vals[k].player; } } // check win by diag r to l for (var k = 0; k < vals.length; k++) { vals[k].value = 0; for (var i = 0; i < 3; i++) { if (grid[i][2-i] === vals[k].player) { vals[k].value++; } } if (vals[k].value === 3) { alert(vals[k].player + " wins by diag right to left!"); return vals[k].player; } } }
What about put your data in a object like this: var _ = { x : 0, o : 0 }; and change the value like this: _[value]++; I hope this helps.
how can i compare two arrays in Javascript by using binarysearch?
How can i use a binary search to compare two arrays and count the number of times it matched, i did find some here where one item was compared to an array..follwing is regular one for example ..thanx for the help. var a = ["1", "2", "3", "4", "5", "6", "7"]; var b = ["8", "1", "3", "9", "4", "6", "8"]; var count = 0; for (i = 0; i < a.length; i++) { for (j = 0; j < b.length; j++) { if (a[i] == b[j]) count += 1; } } document.write(count); I tried to do this .. for (i = 0; i < a.length; i++) { var left = 0; var right = b.length - 1; while (left <= right) { var mid = parseInt((left + right) / 2); if (b[mid] == a[i]) { count += 1; } else if (b[mid] < a[i]) { left = mid + 1; } else { right = mid - 1; } } } document.write(count);
Linearly go through the b array and use a binary search of the a array. function binarySearch(a, value) { var left = 0; var right = a.length - 1; while (left <= right) { var mid = (left + right) >> 1; if (a[mid] === value) { return mid; } else if (a[mid] < value) { left = mid + 1; } else { right = mid - 1; } } return -1; } var a = ["1", "2", "3", "4", "5", "6", "7"]; var b = ["8", "1", "3", "9", "4", "6", "8"]; var count = 0; b.forEach(function(value) { if (binarySearch(a, value) >= 0) ++count; });