Related
So i have been trying to write a sudoku solver and i had to complet methods inside an extend class here's the head of the code:
class Board extends EventEmitter {
constructor(board) {
super();
this.board = board || [
[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],
];
}
getRow(index) {
return this.board[index];
}
here i have to check if all the rows inside that board are valid (from 1 to 9 no repet):
allrowsValid() {
for (let c = 0; c < 9; ++c) {
**var row = this.getRow(c)** ***//what i need to fix***
for ( let num = 1; num <= 9; ++num){
if (this.board[row][c] === num) {
return false;
}
}
}
return true;
}
How can i solve it ?
thanks !
It depends whether "valid" means "full house" (all numbers in range [1-9]), or not invalid (some numbers in range [1-9] without repetition). I've used bit arithmetic to specifically address this in Sudoku in the past:
// class methods...
validHouse( array) {
// no non zero repetitions
let allowed = 0b1111111110;
for( let index = 9; index--;) {
if( array[index]) {
let position = 1 << array[index];
if( !(allowed & position)) {
return false; // repetition
}
allowed &= ~position;
}
}
return true;
}
fullHouse(array) {
// all house numbers completed
let required = 0b1111111110;
for( let index = 9; index--;) {
if( array[index]) {
let position = 1 << array[index];
required &= ~position;
}
}
return required == 0;
}
So if you wanted to know if all rows were complete or valid you could use
allRowsFull() {
return this.board.every(row => this.fullHouse(row));
}
allRowsValid() {
return this.board.every(row => this.validHouse(row));
}
The point here is not to push you into using binary arithmetic (it's an acquired taste1) but to point out that a row is only one of the three types of Sudoku houses (row, column and box) that need to be considered.
1 Answer updated to use the bit-wise complement operator (~) instead of the logical not operator (!) in bit clearing operations. They are not interchangeable.
if (this.board[row][c] === num)
The problem is at this line, you are trying to get the row by using the row. The row variable is already referencing the row.
So the solution is to replace this.board[row][c] with row[c]
for ( let num = 1; num <= 9; ++num){
if (row[c] === num) {
return false;
}
}
I have an array of arrays that looks like this:
var grid = [
[0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0],
[0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
[0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0]
];
I want to count the number of 1s in a row until we hit a zero. And then if we hit a 1 again, count the sequential occurrences again.
So for grid[0], it should return 9.
For grid[1], it should return [3,3].
grid[2], [2,1,1,2].
As an extra layer of fun, I'm also trying to do this for "columns." I.e. How many times "1" appears in the 1st column, which would consist of grid[0][1], grid[1][1], grid[2][1] and so on. If there's a better way to organize the data to achieve this, I'm open to suggestions as in total I have 25 rows/arrays within the array.
I'm unsure if there is a way that doesn't involve looping through the data over and over. Currently I'm doing this:
var guides = [];
for ( var i = 0; i < grid.length; i++ ) {
var row = grid[i];
var chunks = [];
var count = 0;
for (var j = 0; j < row.length; j++ ) {
if ( j === 1 ) {
count++;
} else {
chunks.push(count);
count = 0;
}
}
guides.push(chunks);
}
Here's one example how you can use recursion to check those number 1 strikes. For the columns, you can transpose the original Grid and re-use the same function.
var grid = [
[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
]
// Returns the array of 1 strikes in the given arr
const occurrenceOfOne = (arr, strike = 0, final = []) => {
// Recursive calls until the array is empty
if (arr.length === 0) {
return strike === 0 ? final : final.concat([strike])
}
// If the item is 0, the strike ends.
if (arr[0] === 0) {
if (strike !== 0) {
return occurrenceOfOne(arr.slice(1), 0, final.concat([strike]))
}
}
// If the item is 1, the strike continues
if (arr[0] === 1) {
return occurrenceOfOne(arr.slice(1), strike + 1, final)
}
// Default value 0 found and strike is 0 as well.
return occurrenceOfOne(arr.slice(1), 0, final)
}
// Copied transpose function from this gist:
// https://gist.github.com/femto113/1784503
function transpose(a) {
return a[0].map((_, c) => a.map((r) => r[c]))
}
console.log(occurrenceOfOne(grid[0]))
console.log(occurrenceOfOne(grid[1]))
console.log(occurrenceOfOne(grid[2]))
const transposedGrid = transpose(grid)
console.log(occurrenceOfOne(transposedGrid[6]))
console.log(occurrenceOfOne(transposedGrid[7]))
I'm trying to make a small game similar to minesweeper or battleship and I need to use some kind of 10x10 grid. To store information for this grid I was planning to use a 10x10 2d array. My problem so far is that I can't figure out how to access, check, and change the contents of the individual locations of the array. My questions is this. How, or what is the best way to create an array or something else to store the series of integers I need and later access them as necessary?
I've tried some different ways to do this, with my last attempt being:
var row1 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row3 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row5 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row6 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row7 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row8 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row9 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var row10= [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var coords = [row1, row2, row3, row4, row5, row6, row7, row8, row9, row10];
I intended to have 0 signify an unclicked space, 1 signify a clicked space that didn't contain anything, and 2 signify a space that contained an object.
Here's a way to initialize a 10x10 2D array with the number 0.
Create a single array and push 10 arrays into it. For each of those inner-arrays, push the number 0 (or whatever value you like).
var grid = [];
for (var i = 0; i < 10; i++) {
grid.push([]);
for (var j = 0; j < 10; j++) {
grid[i].push(0);
}
}
document.write(grid.join("<br>"));
I intended to have 0 signify an unclicked space, 1 signify a clicked space that didn't contain anything, and 2 signify a space that contained an object.
You need two MD arrays: one for storing values 0 1 or 2, and one for storing your objects - null or otherwise.
My problem so far is that I can't figure out how to access, check, and change the contents of the individual locations of the array.
Below is an example that uses two arrays: one to store the state of the user clicks, and another to store the related objects. When a user clicks zero to update its state, it's up to you to do something with the objs array. All I've done is change the clicked element's innerHTML to 2 when the associated object exists in the objs array, or 1 when it doesn't.
//all elements are unclicked
var ints = [
[0,0,0,0],
[0,0,0,0],
[0,0,0,0],
[0,0,0,0]
];
//objects exist where not null
var objs = [
[7,null,null,1],
[null,7,null,null],
[1,null,8,8],
[2,null,2,null]
];
//the game is the parent container
var game = $('#game');
//fill the game with rows and columns of clickable html
for(var i = 0; i < objs.length; i++) {
$(game).append('<div class="row">');
for(var j = 0; j < objs[i].length; j++) {
//store i and j indices in data attributes - used in click event
$(game).append('<div data-i="' + i + '" data-j="' + j + '" class="column">' + ints[i][j] + '</div>');
}
$(game).append('</div>');
}
//onclick - look for object in objs array (they are not null when present)
$('.column').click(function() {
var i = $(this).data('i');
var j = $(this).data('j')
//update inner html
if(objs[i][j] !== null) {
$(this).html('2');
} else {
$(this).html('1');
}
});
.column {
display: inline-block;
width: 20px;
padding: 5px;
margin: 3px;
cursor: pointer;
cursor: hand;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="game"></div>
Try this. It will create two dimensional array with 3 rows and 3 columns. It will also assign all elements with 0 as I used fill(). And you can access any element using row and column index. In the following example I have printed first row.
var arr = new Array(3).fill(new Array(3).fill(0));
document.write(JSON.stringify(arr[0]));
You can use new Array() to create an array.
var coords = new Array(10);
for (var row = 0; row < 10; row++) {
coords[row] = new Array(10);
for (var col = 0; col < 10; col++) {
coords[row][col] = 0;
}
}
I am going through an exercise to recreate Conway's Game of Life and I have a basic strategy and I'm still very much in the "making it work" stage, so I know this looks pretty funny.
The problem I'm running up against right now is that I'm trying iterate through the 2-D array and each time, call the functions that determine whether the cells live or die. This is the last block of code which is returning 'undefined' for 'col'.
The functions work when called outside the loop (with variables assigned to row and col).
However, when I try and call the functions inside the loop, I get undefined values. I'm assuming this is an issue of scope, but I'm not sure exactly how to fix it.
Here is the code:
// this is the world that is being calculated
var world = [
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 1, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0]
];
// this is where the new calculated values are stored until they are ready to
// be transferred back to the first array: world
var tempWorld = [
[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]
];
function getNeighbors(row, col) {
// variables that get the values of the 8 neighboring cells
var currentCell = world[row][col];
var upperLeftCorner = world[row - 1][col - 1];
var above = world[row - 1][col];
var upperRightCorner = world[row - 1][col + 1];
var left = world[row][col - 1];
var right = world[row][col + 1];
var bottomLeft = world[row + 1][col - 1];
var bottom = world[row + 1][col];
var bottomRight = world[row + 1][col + 1];
// this variable adds the neighboring cells together
var totalNumberOfNeighbors = upperLeftCorner + above + upperRightCorner + left + right + bottomLeft + bottom + bottomRight
return totalNumberOfNeighbors;
};
// test to confirm that getNeighbors is working
console.log("value of getNeighbors is: " + getNeighbors(row, col));
function deadCellsLiveOrDie (row, col) {
// Rule to make dead cells living
if (world[row][col] === 0) {
if (getNeighbors(row, col) === 3) {
tempWorld[row][col] = 1;
}
}
};
deadCellsLiveOrDie(row, col);
livingCellsLiveOrDie(row, col);
function livingCellsLiveOrDie (row, col) {
// Rule to determine if living cells die or live
if (world[row][col] === 1) {
if ((getNeighbors(row, col) === 2) || (getNeighbors(row, col) === 3)) {
tempWorld[row][col] = 1;
} else tempWorld[row][col] = 0
}
};
// test to confirm that rules of life work for a cell
console.log("tempWorld row, col is: " + tempWorld[row][col]);
// iterate over the 2-D array
for (row = 0; row < world.length; ++ row)
{
var col;
for (col = 0; col < world[row].length; ++ col) {
deadCellsLiverOrDie(row, col);
livingCellsLiveOrDie(row, col);
}
}
There were a few problems with your code:
Several calls throughout the code refence undeclared variables row and col.
The loop declares row as global (not an "error", but not good practice)
The method call to deadCellsLiveOrDie is mistyped.
The getNeighbors method does not make boundary checks, so you will run out of range.
A (quickly) fixed version can be found here: http://jsfiddle.net/Eakcm/
I want to create a two dimensional array in Javascript where I'm going to store coordinates (x,y). I don't know yet how many pairs of coordinates I will have because they will be dynamically generated by user input.
Example of pre-defined 2d array:
var Arr=[[1,2],[3,4],[5,6]];
I guess I can use the PUSH method to add a new record at the end of the array.
How do I declare an empty two dimensional array so that when I use my first Arr.push() it will be added to the index 0, and every next record written by push will take the next index?
This is probably very easy to do, I'm just a newbie with JS, and I would appreciate if someone could write a short working code snippet that I could examine. Thanks
You can just declare a regular array like so:
var arry = [];
Then when you have a pair of values to add to the array, all you need to do is:
arry.push([value_1, value2]);
And yes, the first time you call arry.push, the pair of values will be placed at index 0.
From the nodejs repl:
> var arry = [];
undefined
> arry.push([1,2]);
1
> arry
[ [ 1, 2 ] ]
> arry.push([2,3]);
2
> arry
[ [ 1, 2 ], [ 2, 3 ] ]
Of course, since javascript is dynamically typed, there will be no type checker enforcing that the array remains 2 dimensional. You will have to make sure to only add pairs of coordinates and not do the following:
> arry.push(100);
3
> arry
[ [ 1, 2 ],
[ 2, 3 ],
100 ]
If you want to initialize along with the creation, you can use fill and map.
const matrix = new Array(5).fill(0).map(() => new Array(4).fill(0));
5 is the number of rows and 4 is the number of columns.
ES6
Matrix m with size 3 rows and 5 columns (remove .fill(0) to not init by zero)
[...Array(3)].map(_=>Array(5).fill(0))
let Array2D = (r,c) => [...Array(r)].map(_=>Array(c).fill(0));
let m = Array2D(3,5);
m[1][0] = 2; // second row, first column
m[2][4] = 8; // last row, last column
// print formated array
console.log(JSON.stringify(m)
.replace(/(\[\[)(.*)(\]\])/g,'[\n [$2]\n]').replace(/],/g,'],\n ')
);
If you want to be able access the matrix like so:
matrix[i][j]
I find it the most convenient to init it in a loop.
var matrix = [],
cols = 3;
//init the grid matrix
for ( var i = 0; i < cols; i++ ) {
matrix[i] = [];
}
This will give you
[ [], [], [] ]
so
matrix[0][0]
matrix[1][0]
returns undefined and not the error "Uncaught TypeError: Cannot set property '0' of undefined".
You can nest one array within another using the shorthand syntax:
var twoDee = [[]];
You can try something like this:-
var arr = new Array([]);
Push data:
arr[0][0] = 'abc xyz';
An empty array is defined by omitting values, like so:
v=[[],[]]
a=[]
b=[1,2]
a.push(b)
b==a[0]
You can fill an array with arrays using a function:
var arr = [];
var rows = 11;
var columns = 12;
fill2DimensionsArray(arr, rows, columns);
function fill2DimensionsArray(arr, rows, columns){
for (var i = 0; i < rows; i++) {
arr.push([0])
for (var j = 0; j < columns; j++) {
arr[i][j] = 0;
}
}
}
The result is:
Array(11)
0:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
3:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
4:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
5:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
6:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
7:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
8:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
9:(12) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
10:(12)[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
One Liner
let m = 3 // rows
let n = 3 // columns
let array2D = Array(m).fill().map(entry => Array(n))
This implementation creates a unique subarray for each entry. So setting array2D[0][1] = 'm' does not set each entry's [1] index to 'm'
I know this is an old thread but I'd like to suggest using an array of objects rather than an array of arrays. I think it make the code simpler to understand and update.
// Use meaningful variable names like 'points',
// anything better than a bad pirate joke, 'arr'!
var points = [];
// Create an object literal, then add it to the array
var point = {x: 0, y: 0};
points.push(point);
// Create and add the object to the array in 1 line
points.push({x:5, y:5});
// Create the object from local variables
var x = 10;
var y = 8;
points.push({x, y});
// Ask the user for a point too
var response = prompt("Please enter a coordinate point. Example: 3,8");
var coords = response.split(",").map(Number);
points.push({x: coords[0], y: coords[1]});
// Show the results
var canvas = document.getElementById('graph');
var painter = canvas.getContext("2d");
var width = canvas.width, height = canvas.height;
var scale = 10, radius = 3.5, deg0 = 0, deg360 = 2 * Math.PI;
painter.beginPath();
for (var point of points) {
var x = point.x * scale + scale;
var y = height - point.y * scale - scale;
painter.moveTo(x + radius, y);
painter.arc(x, y, radius, deg0, deg360);
painter.fillText(`${point.x}, ${point.y}`, x + radius + 1, y + radius + 1);
}
painter.stroke();
<canvas id="graph" width="150" height="150" style="border: 1px solid red;"></canvas>
This one should work:
const arr = new Array(5).fill().map(_ => new Array(5).fill(0)) // ✅
You may ask why did I use map instead of:
const badArr = new Array(5).fill(new Array(5).fill(0)) // ❌
The problem with the example above is that it adds references to the array that was passed into the fill method:
While this one works fine:
const grid = Array.from(Array(3), e => Array(4));
Array.from(arrayLike, mapfn)
mapfn is called, being passed the value undefined, returning new Array(4).
An iterator is created and the next value is repeatedly called. The value returned from next, next().value is undefined. This value, undefined, is then passed to the newly-created array's iterator. Each iteration's value is undefined, which you can see if you log it.
var grid2 = Array.from(Array(3), e => {
console.log(e); // undefined
return Array(4); // a new Array.
});
ES6
const rows = 2;
const columns = 3;
const matrix = [...Array(rows)].map(() => [...Array(columns)].fill(0));
console.log(matrix);
Create an object and push that object into an array
var jSONdataHolder = function(country, lat, lon) {
this.country = country;
this.lat = lat;
this.lon = lon;
}
var jSONholderArr = [];
jSONholderArr.push(new jSONdataHolder("Sweden", "60", "17"));
jSONholderArr.push(new jSONdataHolder("Portugal", "38", "9"));
jSONholderArr.push(new jSONdataHolder("Brazil", "23", "-46"));
var nObj = jSONholderArr.length;
for (var i = 0; i < nObj; i++) {
console.log(jSONholderArr[i].country + "; " + jSONholderArr[i].lat + "; " +
jSONholderArr[i].lon);
}
var arr = [];
var rows = 3;
var columns = 2;
for (var i = 0; i < rows; i++) {
arr.push([]); // creates arrays in arr
}
console.log('elements of arr are arrays:');
console.log(arr);
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
arr[i][j] = null; // empty 2D array: it doesn't make much sense to do this
}
}
console.log();
console.log('empty 2D array:');
console.log(arr);
for (var i = 0; i < rows; i++) {
for (var j = 0; j < columns; j++) {
arr[i][j] = columns * i + j + 1;
}
}
console.log();
console.log('2D array filled with values:');
console.log(arr);
The most simple way to create an empty matrix is just define it as an empty array:
// Empty data structure
const matrix = []
However, we want to represent something similar to a grid with n and m parameters know ahead then we can use this instead.
// n x m data structure
const createGrid = (n, m) => [...Array(n)].map(() => [...Array(m)].fill(0))
const grid = createGrid(3, 5)
Here is a simple snippet showing how to use them.
const createGrid = (n, m) => [...Array(n)].map(() => [...Array(m)].fill(0))
const toString = m => JSON.stringify(m)
.replace(/(\[\[)(.*)(]])/g, '[\n [$2]\n]')
.replace(/],/g, '],\n ')
// Empty data structure
const matrix = []
console.log(toString(matrix))
matrix.push([1,2,3])
matrix.push([4,5,6])
matrix.push([7,8,9])
console.log(toString(matrix))
// n x m data structure
const grid = createGrid(3, 5)
console.log(toString(grid))
No need to do so much of trouble! Its simple
This will create 2 * 3 matrix of string.
var array=[];
var x = 2, y = 3;
var s = 'abcdefg';
for(var i = 0; i<x; i++){
array[i]=new Array();
for(var j = 0; j<y; j++){
array[i].push(s.charAt(counter++));
}
}
If we don’t use ES2015 and don’t have fill(), just use .apply()
See https://stackoverflow.com/a/47041157/1851492
let Array2D = (r, c, fill) => Array.apply(null, new Array(r))
.map(function() {
return Array.apply(null, new Array(c))
.map(function() {return fill})
})
console.log(JSON.stringify(Array2D(3,4,0)));
console.log(JSON.stringify(Array2D(4,5,1)));
We usually know the number of columns but maybe not rows (records). Here is an example of my solution making use of much of the above here. (For those here more experienced in JS than me - pretty much everone - any code improvement suggestions welcome)
var a_cols = [null,null,null,null,null,null,null,null,null];
var a_rxc = [[a_cols]];
// just checking var arr = a_rxc.length ; //Array.isArray(a_rxc);
// alert ("a_rxc length=" + arr) ; Returned 1
/* Quick test of array to check can assign new rows to a_rxc.
i can be treated as the rows dimension and j the columns*/
for (i=0; i<3; i++) {
for (j=0; j<9; j++) {
a_rxc[i][j] = i*j;
alert ("i=" + i + "j=" + j + " " + a_rxc[i][j] );
}
if (i+1<3) { a_rxc[i+1] = [[a_cols]]; }
}
And if passing this array to the sever the ajax that works for me is
$.post("../ajax/myservercode.php",
{
jqArrArg1 : a_onedimarray,
jqArrArg2 : a_rxc
},
function(){ },"text" )
.done(function(srvresp,status) { $("#id_PageContainer").html(srvresp);} )
.fail(function(jqXHR,status) { alert("jqXHR AJAX error " + jqXHR + ">>" + status );} );
What's wrong with
var arr2 = new Array(10,20);
arr2[0,0] = 5;
arr2[0,1] = 2
console.log("sum is " + (arr2[0,0] + arr2[0,1]))
should read out "sum is 7"
const dp=new Array(3).fill(new Array(3).fill(-1))
It will create below array:
[ [ -1, -1, -1 ], [ -1, -1, -1 ], [ -1, -1, -1 ] ]
You can nest a new array as you fill the first one:
let ROWS = 2,
COLS = 6;
let arr = new Array(ROWS).fill(new Array(COLS).fill(-1));
Output:
arr =
[
[-1, -1, -1, -1, -1, -1],
[-1, -1, -1, -1, -1, -1]
]
If you're confused, lets break this down with declaring/filling 1 array:
Make a new array size d, filled with any initial value
let arr1d = new Array(d).fill(<whatever_fill_val>);
Now, instead of filling your first array with a int/string/etc, you can fill it with ANOTHER array, as you fill the nested one!
let arr = new Array(d).fill(new Array(n).fill(-1));
// for 3 x 5 array
new Array(3).fill(new Array(5).fill(0))