If someone can test this and find the problem that would be very helpful. The algorithm solves the puzzles but has some zeros in the solution which is not valid sudoku. I think the problem is if the number is possible in that cell then it assumes its correct.
export const initiate = (board) => {
const updatedBoard = board.map((i) =>
i.map((j) => (j === 0 ? (j = null) : j))
);
const validInput = validBoard(updatedBoard);
if (!validInput) {
return false;
}
return solve(updatedBoard);
};
const solve = (board) => {
if (isSolved(board)) {
return board;
}
const possibilities = findPossibilities(board);
const validBoards = keepValid(possibilities);
return searchForSolution(validBoards);
};
const searchForSolution = (boards) => {
if (boards.length < 1) {
return false;
}
const first = boards.shift();
const tryPath = solve(first);
if (tryPath) {
return tryPath;
}
return searchForSolution(boards);
};
const isSolved = (board) => {
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (board[i][j] === null) {
return false;
}
}
}
return true;
};
const findPossibilities = (board) => {
let res = [];
const firstEmptySqr = findEmptySqr(board);
if (firstEmptySqr !== undefined) {
const y = firstEmptySqr[0];
const x = firstEmptySqr[1];
for (let i = 0; i <= 9; i++) {
const newBoard = [...board];
const row = [...newBoard[y]];
row[x] = i;
newBoard[y] = row;
res.push(newBoard);
}
}
return res;
};
const findEmptySqr = (board) => {
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (board[i][j] === null) {
return [i, j];
}
}
}
};
const keepValid = (boards) => {
let res = [];
for (let i = 0; i < boards.length; i++) {
if (validBoard(boards[i])) {
res.push(boards[i]);
}
}
return res;
};
const validBoard = (board) => {
return rowsValid(board) && columnsValid(board) && boxesValid(board);
};
function rowsValid(board) {
for (let i = 0; i < 9; i++) {
let cur = [];
for (let j = 0; j < 9; j++) {
if (cur.includes(board[i][j])) {
return false;
} else if (board[i][j] !== null) {
cur.push(board[i][j]);
}
}
}
return true;
}
function columnsValid(board) {
for (let i = 0; i < 9; i++) {
let cur = [];
for (let j = 0; j < 9; j++) {
if (cur.includes(board[j][i])) {
return false;
} else if (board[j][i] !== null) {
cur.push(board[j][i]);
}
}
}
return true;
}
function boxesValid(board) {
const boxCoordinates = [
[0, 0],
[0, 1],
[0, 2],
[1, 0],
[1, 1],
[1, 2],
[2, 0],
[2, 1],
[2, 2],
];
for (let y = 0; y < 9; y += 3) {
for (let x = 0; x < 9; x += 3) {
let cur = [];
for (let i = 0; i < 9; i++) {
let coordinates = [...boxCoordinates[i]];
coordinates[0] += y;
coordinates[1] += x;
if (cur.includes(board[coordinates[0]][coordinates[1]])) {
return false;
} else if (board[coordinates[0]][coordinates[1]] !== null) {
cur.push(board[coordinates[0]][coordinates[1]]);
}
}
}
}
return true;
}
I was expecting this to solve the sudoku puzzle without returning zeros because in sudoku there are no zeros
In findPossibilities you have a bug in the loop.
In the first iteration 0 is assigned to row[x], which is not what you want to happen. So change this line:
for (let i = 0; i <= 9; i++) {
to:
for (let i = 1; i <= 9; i++) {
Related
I am iterating over the matrix object. Which I create inside the loop, then I modify its values through the increment. When the increment reaches its maximum (51), I have to go back to the outer loop and create a new object one more element. Example: {0: 0, 1: 0}. Now I iterate over the last element in the object, if it = maximum, I go to the next one, from "1" to "0", and increment "0", and "1" = 0. Then I have to iterate over "1".
But the values are not cleared when element = maximum a bug is displayed.
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
function check(maxLength) {
for (let matrixLength = 0; matrixLength < maxLength; matrixLength++) {
let a = matrix(matrixLength);
let Indx;
while (Indx!==null) {
Indx = getIndex(a,letters.length);
console.log(increment(a,Indx,Indx));
}
}
}
function matrix(length) {
let matrix = {};
for (let i = 0; i <= length; i++) {
matrix[i] = 0;
}
return matrix;
}
function getIndex(matrix, arrLength) {
for (let i = Object.values(matrix).length - 1; i >= 0; i--) {
if (matrix[i]!==arrLength - 1) {
return i;
}
}
console.log('null');
return null;
}
function increment(matrix, index, prevIndex = null) {
matrix[index]++;
if (prevIndex === null || index === prevIndex) {
return matrix;
}
for (let i = index + 1; i < Object.values(matrix).length; i++) {
matrix[i] = 0;
}
return matrix;
}
check(3);
Check whether Indx is null after calling getIndex, not before the next iteration.
const letters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
function check(maxLength) {
for (let matrixLength = 0; matrixLength < maxLength; matrixLength++) {
let a = matrix(matrixLength);
while (true) {
let Indx = getIndex(a, letters.length);
if (Indx == null) {
break;
}
console.log(increment(a, Indx, Indx));
}
}
}
function matrix(length) {
let matrix = {};
for (let i = 0; i <= length; i++) {
matrix[i] = 0;
}
return matrix;
}
function getIndex(matrix, arrLength) {
for (let i = Object.values(matrix).length - 1; i >= 0; i--) {
if (matrix[i] !== arrLength - 1) {
return i;
}
}
console.log('null');
return null;
}
function increment(matrix, index, prevIndex = null) {
matrix[index]++;
if (prevIndex === null || index === prevIndex) {
return matrix;
}
for (let i = index + 1; i < Object.values(matrix).length; i++) {
matrix[i] = 0;
}
return matrix;
}
check(3);
I am currently doing a codewars problem, and I think I almost got it however, I ran across a problem when sorting index values with the same letter. link to problem is here. https://www.codewars.com/kata/5782dd86202c0e43410001f6
function doMath(s) {
let strSplit = s.split(' ');
let clonedArr = strSplit.slice();
for (let i = 0; i < strSplit.length; i++) {
for (let j = 0; j < strSplit[i].length; j++) {
let current = strSplit[i][j];
if (isNaN(current)) {
let letter = current;
strSplit[i] = strSplit[i].replace(letter, '');
strSplit[i] = letter + strSplit[i];
}
}
}
let sortedArr = strSplit.sort();
console.log(sortedArr);
// ["b900", "y369", "z123", "z246", "z89"]
let noLetterArr = sortedArr.map(x => {
return x.slice(1);
});
let numberArr = noLetterArr.map(y => {
return +y;
})
let firstEl = numberArr[0];
for (let i = 1; i < numberArr.length; i++) {
if (numberArr.indexOf(numberArr[i]) % 4 == 1) {
firstEl += numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 2) {
firstEl -= numberArr[i];
}
if (numberArr.indexOf(numberArr[i]) % 4 == 3) {
firstEl *= numberArr[i];
}
}
return firstEl;
}
console.log(doMath('24z6 1z23 y369 89z 900b'));
I would like to sort the sortedArr the ones with the same letter by how they first appeared in string. So since "z246" appeared first in the original string. I would like to have that before "1z23". I had a hard time creating a function for that.
var al = [];
function doMath(s) {
var ar = s.split(" ");
for (let i = 0; i < ar.length; i++) {
for (let char of ar[i]) {
let temp = char.match(/[a-z]/i);
if (temp) {
al[i] = char;
ar[i] = ar[i].replace(char, '');
ar[i] = char + ar[i];
}
}
}
al = al.sort();
//New Sort Logic to pass above test case and others too
var n = [];
for (let i = 0; i < al.length; i++) {
for (let j = 0; j < ar.length; j++) {
if (ar[j].startsWith(al[i]) && !n.includes(ar[j])) {
n.push(ar[j]);
}
}
}
var result = parseInt(n[0].substr(1)),
count = 1;
for (let i = 1; i < n.length; i++) {
if (count == 1) {
result = result + parseInt(n[i].substr(1));
count++;
} else if (count == 2) {
result = result - parseInt(n[i].substr(1));
count++;
} else if (count == 3) {
result = result * parseInt(n[i].substr(1));
count++;
} else if (count == 4) {
result = result / parseInt(n[i].substr(1));
count = 1;
}
}
return Math.round(result);
}
My code currently has a bug where my 2-d array with the bool value false suddenly contains true values before it is assigned any. My current guesses is either console.log somehow is delayed and picks up the values after it is called, with the updated values or that there is some issue that I don't understand about how scope works in javascript.
As seen below console.log(visited[i][j]) results in false for all values but the
new visited line contains true values even before the following is called.
const field_size = 800;
const cells_in_row = 5;
const frames_per_second = 1;
const cell_size = field_size / cells_in_row;
class Cell {
constructor(x,y) {
this.value = 0;
this.x = x;
this.y = y;
this.coordinates = [x*cell_size,y*cell_size];
}
fill() {
this.value = 1;
}
clear() {
this.value = 0;
}
}
const get_new_grid = (random = 0) => {
const grid = new Array(cells_in_row);
for (let i = 0; i < grid.length; i++) {
grid[i] = new Array(cells_in_row);
for (let j = 0; j < grid.length; j++) {
grid[i][j] = new Cell(i,j);
v = 0;
if (random) {
v = Math.floor(Math.random() * 2);
}
grid[i][j].value = v;
}
}
return grid;
}
const get_islands = (grid) => {
// bool array to mark visited cells
let visited = new Array(cells_in_row);
for (let i = 0; i < grid.length; i++) {
visited[i] = new Array(cells_in_row);
for (let j = 0; j < grid[0].length; j++) {
visited[i][j] = false;
}
}
console.log("New Visited", visited);
let count = 0;
let islands = [];
let island_coords = [];
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid.length; j++) {
if (visited[i][j] == false && grid[i][j].value == 1) {
// visit all cells in this island and increment island count
// dfs will return array of coordinates of island
[visited, island_coords] = dfs(i, j, grid, visited, island_coords);
console.log(visited);
islands.push(island_coords);
count += 1;
}
}
}
return [count, islands];
}
const dfs = (i, j, grid, visited, island_coords) => {
let row_nbr = [-1, -1, -1, 0, 0, 1, 1, 1];
let col_nbr = [-1, 0, 1, -1, 1, -1, 0, 1];
visited[i][j] = true;
island_coords.push([i,j]);
for (let k = 0; k < 8; k++) {
if (is_safe(i + row_nbr[k], j + col_nbr[k], grid, visited)) {
console.log("DFSing " + i + "," + j);
[visited, island_coords] = dfs(i + row_nbr[k], j + col_nbr[k],
grid, visited, island_coords);
}
}
return [visited, island_coords];
}
const is_safe = (i, j, grid, visited) => {
return (i >= 0 && i < grid.length &&
j >= 0 && j < grid.length &&
!(visited[i][j]) && grid[i][j].value === 1);
}
(function () {
var old = console.log;
var logger = document.getElementById('log');
console.log = function () {
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] == 'object') {
logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(arguments[i], undefined, 2) : arguments[i]) + '<br />';
} else {
logger.innerHTML += arguments[i] + '<br />';
}
}
}
})();
window.onload = () => {
const canvas = document.getElementById('canvas');
const grid = get_new_grid(random = 0);
grid[0][0].value = true;
grid[0][1].value = true;
grid[1][0].value = true;
grid[1][1].value = true;
const islands = get_islands(grid);
console.log(grid);
console.log(islands);
}
<!DOCTYPE html>
<html>
<body>
<script src="gameoflife.js"></script>
<pre id="log"></pre>
</body>
</html>
EDIT:
So I updated the snippet but it looks like it works on this end, however it shows the behavior I mentioned before on my own browser even with the exact same javascript code and html in the snippet.
Mentioned in the comments by Niet, objects logged to the console are live.
I am trying to debug one online coding platform problem. The problem I am facing is to return element occurring most often in array. I am interested in correcting my current code than trying other methods.
function findMostOccured(M, A) { //value of elements in A should not be greater than M
var N = A.length;
var count = new Array(M + 1);
var i;
for (i = 0; i <= M; i++)
count[i] = 0;
var maxOccurence = 1;
var index = -1;
for (i = 0; i < N; i++) {
if (count[A[i]] > 0) {
var tmp = count[A[i]];
if (tmp > maxOccurence) {
maxOccurence = tmp;
index = i;
}
count[A[i]] = tmp + 1;
} else {
count[A[i]] = 1;
}
}
return A[index];
}
Given M = 3 and A = [1, 2, 3, 3, 1, 3, 1]. It should return 3 or 1.
var arr = [1, 2, 3, 3, 1, 3, 1];
var M = 3;
function findMostOccured(M, arr) {
var obj = {};
var result = [];
for (let i = 0; i < arr.length; i++) {
if (obj[arr[i]]) {
obj[arr[i]] = obj[arr[i]] + 1;
} else {
obj[arr[i]] = 1;
}
}
for (var key in obj) {
if (obj[key] === M) {
result.push(parseInt(key));
}
}
return result;
}
console.log(findMostOccured(3, arr));
I'm coding a sudoku solver by backtrack algorithm.
Why does the slice() method in my code return a reference? I know that slice method will return a reference if the array is not Number, String or Boolean. But in my code, the array is filled with 0, how it's possible?
backtrack() {
if (this.state.IsEnd === true)
return true;
const board = this.state.squares.slice(); //board array is the reference of this.state.squares array;
let row, col;
if (!this.findvalid()) {
this.setState({
IsEnd: true
});
return true;
}
let ok = false;
for (let i = 0; i < 9; i++) {
if (ok)
break;
for (let j = 0; j < 9; j++) {
if (board[i][j] === 0 || isNaN(board[i][j])) {
row = i;
col = j;
ok = true;
break;
}
}
}
for (let num = 1; num <= 9; num++) {
if (this.isSafe(row, col, num)) {
board[row][col] = num; /*when board changes,the state squares also changes.*/
this.setState({
squares: board
}); /*when I delete this line,every thing is still the same.*/
if (this.backtrack()) {
return true;
}
board[row][col] = 0;
this.setState({
squares: board
});
}
}
return false;
}
this is my full code
//this function create a board
function createBoard() {
let board = Array(9);
for (let i = 0; i < 9; i++) {
let subarray = Array(9).fill(0);
board[i] = subarray;
}
return board;
}
class App_sudoku_solver extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: createBoard(),
IsEnd: false
}
this.handleChange = this.handleChange.bind(this);
this.SafeBox = this.SafeBox.bind(this);
this.SafeCol = this.SafeCol.bind(this);
this.SafeRow = this.SafeRow.bind(this);
this.isSafe = this.isSafe.bind(this);
this.findvalid = this.findvalid.bind(this);
this.backtrack = this.backtrack.bind(this);
this.solve = this.solve.bind(this);
this.check = this.check.bind(this);
this.restart = this.restart.bind(this);
}
//check if any cell is empty
findvalid() {
const board = this.state.squares.slice();
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (board[i][j] === 0 || isNaN(board[i][j]))
return true;
}
}
return false;
}
// check valid 3x3 squares
SafeBox(startrow, startcol, num) {
const board = this.state.squares.slice();
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (board[startrow + i][startcol + j] === num)
return false;
}
}
return true;
}
//check valid row
SafeRow(row, num) {
const board = this.state.squares.slice();
for (let i = 0; i < 9; i++) {
if (board[row][i] === num)
return false;
}
return true;
}
//check valid column
SafeCol(col, num) {
const board = this.state.squares.slice();
for (let i = 0; i < 9; i++) {
if (board[i][col] === num)
return false;
}
return true;
}
//check if this number is valid in the cell
isSafe(row, col, num) {
return (this.SafeRow(row, num) === true && this.SafeCol(col, num) === true && this.SafeBox(row - row % 3, col - col % 3, num) === true);
}
//solve sudoku by backtrack
backtrack() {
if (this.state.IsEnd === true)
return true;
const board = this.state.squares.slice();
let row, col;
if (!this.findvalid()) {
this.setState({
IsEnd: true
});
return true;
}
let ok = false;
for (let i = 0; i < 9; i++) {
if (ok)
break;
for (let j = 0; j < 9; j++) {
if (board[i][j] === 0 || isNaN(board[i][j])) {
row = i;
col = j;
ok = true;
break;
}
}
}
for (let num = 1; num <= 9; num++) {
if (this.isSafe(row, col, num)) {
board[row][col] = num;
this.setState({
squares: board
});
if (this.backtrack()) {
return true;
}
board[row][col] = 0;
this.setState({
squares: board
});
}
}
return false;
}
this.state.squares is an array of arrays, it is not filled with 0
If the array you are running slice on contains any objects, the method will only copy a reference to them. Since your array contains arrays - and thus, objects, all it's elements are copied only by reference.
function createBoard() {
let board = new Array(9);
for (let i = 0; i < 9; i++) {
let subarray = Array(9).fill(0);
board[i] = subarray;
}
return board;
}
// 2d array containing 9 arrays
let board = createBoard();
console.log("Board: ", board);
const modifiedSlicedBoard = board.slice()[0][2] = 9999999; // I'm modifying the contents of one of the sub-arrays. Because the arrays are copied shallowly, this will also modify the original board
console.log(board, modifiedSlicedBoard);