I want to setup a grid containing m * n objects. This grid got a width of m rows and n columns.
I tried this code first
let map = [][]; // Create an array that takes a x and y index
function createMap() {
for (let x = 0; x < columnCount; x++) {
for (let y = 0; y < rowCount; y++) {
addCell(x, y);
}
}
}
function addCell(x, y) {
map[x][y] = cell(); // create a new object on x and y
}
Obviously this is a wrong syntax. The initialization of map is wrong. How can I create the array that I can access a object by passing in the x and y coordinate to the array?
Let's say I want to access the object on (3|7) I want to go for map[3][7].
Is that possible?
You cant initialize a 2d array, as there are no real 2d arrays in js. However you could setup a regular array, and add arrays to it:
function createMap(columnCount, rowCount) {
const map = [];
for (let x = 0; x < columnCount; x++) {
map[x] = []; // set up inner array
for (let y = 0; y < rowCount; y++) {
addCell(map, x, y);
}
}
return map;
}
function addCell(map, x, y) {
map[x][y] = cell(); // create a new object on x and y
}
const map = createMap(10, 10);
You aren't actually that far off with your solution. You're right, though, you cannot initialize a two-dimensional array like let a = [][]. If you add just one line to your for-loops, your solution also produces a map-like structure:
In your createMap() function, you just need to initialize every field of the the array with an array, after that you can fill the fields of this array:
function createMap() {
for (let x = 0; x < 10; x++) {
map[x] = []; // initialize map[x] as an array
for (let y = 0; y < 10; y++) {
addCell(x, y);
}
}
}
And initialize map as a simple array.
Here is a working example:
let map = [];
createMap();
console.log(map);
function createMap() {
for (let x = 0; x < 5; x++) {
map[x] = [];
for (let y = 0; y < 5; y++) {
addCell(x, y);
}
}
}
function addCell(x, y) {
map[x][y] = cell(x,y); // create a new object on x and y
}
function cell(x,y) {
return (x+1)+":"+(y+1);
}
You need a single array as value and a check if one row does not exist.
function createMap(rowCount, columnCount) {
for (let x = 0; x < rowCount; x++) {
for (let y = 0; y < columnCount; y++) {
addCell(x, y);
}
}
}
function addCell(x, y) {
map[x] = map[x] || [];
map[x][y] = x + '|' + y;
}
var map = [];
createMap(4, 8);
console.log(map[3][7]);
console.log(map);
An approach by using Array.from.
function createMap(rowCount, columnCount) {
map = Array.from(
{ length: rowCount }, // take rowCount as length
(_, i) => Array.from( // fill with new array
{ length: columnCount }, // take columnCount for every row
(_, j) => [i, j].join('|') // initialize cell with some value
)
);
}
var map;
createMap(4, 8);
console.log(map[3][7]);
console.log(map);
Not sure if you are having trouble creating the grid or displaying it.
Here is yet another way to create it:
const grid = Array.from(new Array(5),(_,x)=>Array.from(new Array(5),(_,y)=>addCell(x,y)));
Here are 2 ways to show the grid:
const grid = Array.from(new Array(5),()=>Array.from(new Array(5),()=>"-"));
const rotate = grid =>
grid[0].map(
(_,y)=>grid.map(
(_,x)=>[y,x]
)
).map(
row=>row.map(([x,y])=>grid[y][x])
);
const format = grid => grid.map(x=>x.join(" ")).join("\n");
//set some values of grid
[[0,2],[1,2],[2,2],[3,2],[4,2]].forEach(
([x,y])=>grid[x][y]="X"
);
//you can map the grid to columns first, it'll look like it's rotated
// unless you generate the columns in div float lefts
console.log("map grid columns first:")
console.log(format(grid));
//you can rotate the grid to build each row and then each column like html table
console.log("map grid rows first:")
console.log(format(rotate(grid)));
var grid=[];
var grid_length=10; //mathematical length
var grid_width=10; //mathematical width
function pos(x,y){
return (y*grid_length)-grid_length-1+x-2;
}
function replaceItem(x,y,item){
grid[pos(x,y)]=item;
}
var itemsRequested=[];
function iRequest(x,y){ // get Item on grid.
itemsRequested.push(grid[pos(x,y)]); // this both adds the Object to a list and returns it
return grid[pos(x,y)];
}
This method only makes a mathematical grid, with which you can reference with the pos() function.
Then to answer your question to get the object on 3,7 you would simply say
var a=iRequest(3,7);
//currently would return undefined because there are no objects in the array.
When using this method, 1,1 is the top left corner, and pos(1,1) would return 0.
Here's a functional method that doesn't rely on any reassignment or mutation:
const lengthX = 5;
const lengthY = 2;
const map = Array.from({ length: lengthX }, (_, colIndex) => (
Array.from({ length: lengthY }, (_, rowIndex) => (
// some element to put in each, for example
{ foo: 'bar'}
))
));
console.log(map);
The colIndex and rowIndex are optional, they're not used in this snippet, but if you need to create elements based on their location in the grid, they're the variables to use.
try this:
var x = new Array(10);
for (var i = 0; i < 10; i++) {
x[i] = new Array(20);
}
x[5][12] = 3.0;
Related
I am trying to make a Tetris game. I am trying to work on a function that rotates a 2D variable array 90 degrees (or -90).
For example, given an array like:
"-T-",
"TTT"
It would output:
"T-",
"TT",
"T-"
I have tried this function:
function rotateN90(a){
var temp = [];
for(var x = 0; x<a[0].length; x++){
temp.push("");
for(var y = 0; y<a.length; y++){
temp[x] += a[y][x];
}
}
return temp;
}
But it does not give the desired result. While it does rotate the first T-Block example given -90 degrees once, afterwards it reverts to it's original state.
Please help!
(PS: I am using KA's processing environment, so I can't use libraries or ES6)
The following code is to rotate a mxn size array to -90 degree.
function rotateN90(a){
var temp = new Array(a[0].length); // number of columns
var i=0;
for (i = 0; i < temp.length; i++) {
temp[i] = [];
}
for(i=0;i<a.length;i++){
for(let j = 0; j<a[0].length;j++){
temp[j][i]= a[i][a[i].length-1-j];
}
}
return temp;
}
If your array is :
[[1, 2,3],[4, 5, 6]]
It will rotate -90 degree and returned array will be
[[3, 6],[2, 5],[1, 4]]
class Array2D extends Array {
constructor(width, height, array) {
super();
this.width = width;
this.height = height;
for(let i = 0; i < width*height; i++) {
this[i] = array ? array[i]:0;
}
}
set(x, y, value) {
this[x+y*this.width] = value;
}
get(x, y) {
return this[x+y*this.width];
}
static swap(array2d) {
const result = new Array2D(array2d.height, array2d.width);
for(let x = 0; x < array2d.width; x++) {
for(let y = 0; y < array2d.height; y++) {
result.set(y, x, array2d.get(x, y));
}
}
return result;
}
static flip(array2d) {
const result = new Array2D(array2d.width, array2d.height);
for(let x = 0; x < array2d.width; x++) {
for(let y = 0; y < array2d.height; y++) {
result.set(x, array2d.height-1-y, array2d.get(x, y));
}
}
return result;
}
static spin(array2d) {
const swapped = Array2D.swap(array2d);
return Array2D.flip(swapped);
}
}
const a2d = new Array2D(2, 2, [1, 1, 1, 0]);
console.log(Array2D.spin(Array2D.spin(a2d)));
This should do the job, changed format though a little.
Because class notation isn't allowed in khan academy here is a modified solution
//technically this one is a little unnessecary, but I like the organization
function create2D(width, height, array) {
var arr = [];
arr.width = width;
arr.height = height;
for(var i = 0; i < width*height; i++) {
arr[i] = array ? array[i]:0;
}
return arr;
}
function set(array, x, y, value) {
array[x+y*array.width] = value;
}
function get(array, x, y) {
return array[x+y*array.width];
}
function swap(array2d) {
var result = create2D(array2d.height, array2d.width);
for(var x = 0; x < array2d.width; x++) {
for(var y = 0; y < array2d.height; y++) {
set(result, y, x, get(array2d, x, y));
}
}
return result;
}
function flip(array2d) {
var result = create2D(array2d.width, array2d.height);
for(var x = 0; x < array2d.width; x++) {
for(var y = 0; y < array2d.height; y++) {
set(result, x, array2d.height-1-y, get(array2d, x, y));
}
}
return result;
}
function spin(array2d) {
return flip(swap(array2d));
}
var a1 = create2D(2, 2, [1, 1, 1, 0]);
var a2 = spin(spin(a1));
console.log(a2);
This answer would work for flipping 90 AND flipping -90
a truthy value in the left parameter would flip it -90
a falsey value in the left parameter would flip it +90
//1 to rotate left, 0 to rotate right
function rotate(arr,left){
var newArr=[]
arr.forEach(function(a){newArr.push(a.toString())})
arr=newArr //we gonna do some wild stuff so this is to not mess with the original array given to function
arr=arr.map(function(a){return a.split``})
var newArr=new Array(arr[0].length)
for(var i=0;i<newArr.length;i++){newArr[i]=[]}
arr.forEach(function(a,i){
a.forEach(function(b,j){
newArr[j][i]=b
})
})
if(left){
newArr=newArr.map(function(a){return a.join``})
return(newArr)
}
//else(right)
newArr.map(function(a){a.reverse()})
newArr=newArr.map(function(a){a.join``})
return(newArr)
}
//example 1 (-90 degrees)
console.log("example 1(-90 degrees)",rotate(["-T-","TTT"],1))
//same example but you can use truthy or falsy values not JUST 1 or 0
console.log("example 1(-90 degrees) with another truthy value",rotate(["-T-","TTT"],{a:true}))
//example 2(+90 degrees)
console.log("example 2(+90 degrees)",rotate(["-T-","TTT"],0))
Can you please write a js code that fills empty matrix randomly with 0 or 1? I need to use Random() function.
I wrote this code and I got an error Random() is not defined
var matrix = [];
for(var y = 0; y<5; y++){
for(var x = 0; x<5; x++){
let arr = [0,1]
matrix[y][x]= random(arr)
matrix.push(matrix[y][x])
}
}
You should Math.random() and then use Math.round() to get 0 or 1.
Secondly you should set matrix[y] to an empty array otherwise code will throw error.
var matrix = [];
for(var y = 0; y<5; y++){
matrix[y] = [];
for(var x = 0; x<5; x++){
matrix[y][x]= Math.round(Math.random())
matrix.push(matrix[y][x])
}
}
console.log(matrix)
An easier to create a matrix of any length you can use map(). Create an array of given length and map it to a another array with same length have random values from 0 or 1
const getMatrix = len => [...Array(len)].map(x => [...Array(len)].map(b => Math.round(Math.random())));
let res = getMatrix(5);
console.log(res)
For different length and width use two parameters.
const getMatrix = (l,w) => [...Array(l)].map(x => [...Array(w)].map(b => Math.round(Math.random())));
let res = getMatrix(2,3);
console.log(res)
You should use Math.round(Math.random()).
An easy way to do it using ES6:
const arr = new Array(5).fill().map(() => new Array(5).fill().map(() => Math.round(Math.random())));
console.log(arr);
You have to use the fill() method before map(), otherwise you will get undefined values.
The "classical" way to do it using your snippet of code will be similar to what you tried, with the addition of the standard built-in object Math which has the random() method and also round() to get integer values. If you want a matrix (2D array) then you will need to push an array into each row, otherwise you will get a simple array.
var matrix = [];
for(var y = 0; y < 5; y++) {
const row = [];
for(var x = 0; x < 5; x++) {
row.push(Math.round(Math.random()));
}
matrix.push(row);
}
console.log(matrix);
I want to group together adjacent (vertically and horizontally) characters in an array, in this case all the adjacent "*" belong to one group, see below. And then I want to be able to count how many groups of "*" there are, in this case the answer is 3.
var x = ["...***....",
"..*****...",
"...***....",
"........*.",
".......***",
"..*.....*.",
".***......"];
The code:
function compareRows(){
var totalGroups = 0;
for (i = 0; i < x.length; i++) {
var array = x[i];
for (j = 0; j < array.length; j++) {
var row = array[j];
for (k = 0; k < row.length; k++) {
var char1 = row[k];
var nextRow = j+1;
var char2 = row[nextRow];
if(char1== "*"){
if(char1 != char2) {
totalGroups+=1;
}
} else {
//console.log("Keep searching..");
}
}
}
} console.log(totalGroups);
}
compareRows();
So basically for each row I'm searching for the character "*" and when it's found, if the character at the same index on the row below isn't a "*", then one group is found. However, at the moment totalGroups is 20, the total amout of "*" found in the whole array. I feel a bit stuck and don't know how to proceed.
I believe you'll need to walk the grid at any point you find an asterisk and keep track of cells you have already visited. You can do so with a visited array to avoid walking the same cell twice and a recursive walk function. Here's what I was able to come up with:
const grid = [
"...***....",
"..*****...",
"...***....",
"........*.",
".......***",
"..*.....*.",
".***......"
];
function getGroups(grid) {
// split the grid into a 2d array of objects (cells)
const cellGrid = grid.map((s, y) => s.split('').map((value, x) => ({value, x, y})));
const height = cellGrid.length;
const width = cellGrid[0].length;
const visited = []; // keep track of visited cells
const groups = [];
let currentGroup = [];
// walk each cell left-to-right top-to-bottom
for(let y = 0; y < height; y++) {
for(let x = 0; x < width; x++) {
walkFromCell(x, y, true);
}
}
return groups;
function walkFromCell(x, y, groupStart) {
const cell = getCell(x, y);
// ignore visited and non-group cells
if(!cell || cell.value !== '*' || visited.includes(cell)) return;
currentGroup.push(cell);
visited.push(cell);
walkFromCell(x + 1, y, false);
walkFromCell(x - 1, y, false);
walkFromCell(x, y + 1, false);
// groupStart is only true for the first cell in a group
if(groupStart) {
groups.push(currentGroup);
currentGroup = [];
}
}
function getCell(x, y) {
return cellGrid[y] ? cellGrid[y][x] : null;
}
}
const groups = getGroups(grid);
const groupCount = groups.length;
console.log(`Count = ${groupCount}`);
console.log('Groups =', groups);
My goal is to make a randomly generated 2D Array in Javascript, that has an X amount of the same one character value while the rest of the values are equal to another character.
In this example, there are 10 rows and 10 columns for the 2D Array. 20 out of the possible 100 values of the Array should be equal to 'Y' (for yes) and the 80 others should be 'N' (for no). I want the 'Y's to be randomly placed all over the Array, and I absolute need exactly 20 of them to be 'Y's and the rest 'N's.
I had a less efficient way before, and I thought to try this approach, where after I define the Array, I make the first X amount of values a 'Y' and then the rest all 'N's. Then I shuffle the array, (using the shuffle from the underscore library) so that the 'Y's are all spread out randomly everywhere.
Is this an efficient way of getting what I need done? Are there any better solutions? I tried making a JSFiddle with my example, but the site appears to be down at the moment.
(I was unable to test my code yet to see if the shuffle worked correctly on my 2D array)
var rows = 10;
var cols = 10;
var elements = 20;
//Define Empty Array
var test = new Array(rows);
for (var k = 0; k < rows; k++)
{
test[k] = Array(cols);
}
var i = 1;
for (var x = 0; x < rows; x++)
{
for (var y = 0; y < cols; y++)
{
if (i <= elements)
{
test[x][y] = "Y";
}
else
{
test[x][y] = "N";
}
}
}
//Shuffle all those values so they're no longer in order
var shuffledTest = _.shuffle(test);
//Print in rows
for (var x = 0; x < rows; x++)
{
console.log(shuffledTest[x]);
}
A very simple solution is to first create an array, fill it with a number of "N"s, insert the "Y"s at random indexes, and then finally splitting it into the 2-dimensional array that you want:
var tmpArr = [], // Temporary 1-dimensional array to hold all values
arr = [], // The final 2-dimensional array
rows = 10,
cols = 10,
elements = 20; // Number of "Y"s
// 1. Fill temporary array with "N"s
for (var i = 0; i < rows * cols - elements; i += 1) {
tmpArr.push("N");
}
// 2. Insert "Y"s at random indexes in the temporary array
for (var i = 0; i < elements; i += 1) {
var index = Math.round(Math.random() * (tmpArr.length + 1));
tmpArr.splice(index, 0, "Y");
}
// 3. Split temporary array into 10 seperate arrays
// and insert them into the final array
for (var i = 0; i < rows; i += 1) {
var row = tmpArr.slice(i * cols, (i + 1) * cols);
arr.push(row);
}
JSBin to illustrate: http://jsbin.com/luyacora/1/edit
You can try this solution, it uses underscores range to create a pair of arrays to use as iterators, though their values don't matter.
Play around with the randomizer function to get an even distribution of 'y's
JSBIN: http://jsbin.com/yaletape/1/
var rows = _.range(0, 10, 0);
var columns = _.range(0, 10, 0);
function randomizer(mult){
return Math.floor((Math.random()*mult)+1);
}
var y_count = 0;
var matrix = _.map(rows, function(){
return _.map(columns, function(v, i){
var value;
var y_allowed = randomizer(3);
var current_y_count = 0;
if(y_count < 20 && current_y_count < y_allowed){
var rand = randomizer(5);
if(rand > 4){
value = 'y';
current_y_count++;
y_count++;
}
}
if(!value){
value = 'n';
}
return value;
});
});
//The above could be simplified to
var matrix = _.range(0,10,0).map(function(){
return _.range(0,10,0).map(function(){
//put the logic code from above here
});
});
Maybe shuflle a 2D array is not the best way. As #Zeb mentioned, here is some code that fill random positions with the 'Y' value. After that, the other positions are filled with 'N'.
http://plnkr.co/edit/avyKfgsgOSdAkRa1WOsk
var arr = [];
var cols = 10;
var rows = 10;
var positions = rows*cols; // 100
var YQty = 10; // only 10 'Y' are needed
// 'Y' values.
for(i = 0; i < YQty; i++)
{
do
{
x = parseInt(Math.random() * cols);
y = parseInt(Math.random() * rows);
filled = false;
if (typeof(arr[x]) == "undefined")
{
arr[x] = [];
}
if (typeof(arr[x][y]) == "undefined")
{
arr[x][y] = 'Y';
filled = true;
}
}
while (!filled);
}
// 'N' values.
for (x = 0; x < cols; x++)
{
if (typeof(arr[x]) == "undefined")
{
arr[x] = [];
}
for (y = 0; y < rows; y++)
{
if (arr[x][y] != 'Y')
{
arr[x][y] = 'N';
}
}
}
Shuffling the multidimensional array is not the best approach. Seeing as any sort is worse than linear time complexity. The easiest solution would be to create your multidimensional array and then set each index value to the char you want the 'rest' of the values to be. Then for 1 -> the number of other char value choose a random index and set that to the char.
Note: If the randomly picked spot has already been changed you need to choose a new one to make sure you have the right amount at the end.
I have a javascript object -
cell{xPos, yPos};
I would like to create a 2d array of this object.
cellPrototype = function(x, y) {
this.xPos = x;
this.yPos = y;
}
var cell = new Array();
for(var i=0;i<10;i++)
{
cell[i] = new Array();
for(var j=0;j<10;j++)
{
cell[i][j] = new cellPrototype(i,j);
}
}
This code doesn't work.
Neither does -
var cellPrototype = function(x, y) {
return {
xPos : x;
yPos : y;
}
var cell = new Array();
for(var i=0;i<10;i++)
{
cell[i] = new Array();
for(var j=0;j<10;j++)
{
cell[i][j] = new cellPrototype(i,j);
}
}
So how do I create a 2d array of an object in javascript?
This works fine for me, I'm not sure if that's exactly the output you're looking for, where
Array[x][y] will reference an object with points at x, y.
var Coords = function(x, y) {
return {
"x" : x,
"y" : y
};
};
var Main = [];
for (var i = 0, l = 10; i < l; i++) {
Main[i] = [];
for (var j = 0, l2 = 10; j < l2; j++) {
Main[i][j] = Coords(i, j);
}
}
http://jsfiddle.net/robert/d9Tgb/
You can make a 2d array like so:
var new_array = [];
var arr_length = 10;
for(var i = 0; i < arr_length; ++i){
new_array[i] = [];
}
This post is a bit old, but here is another way to create a 2D array
var arr1=[];
var x=['a','b','c','d'];
var y=[1,2,3,4];
for( var i in x){
arr1.push([x[i],y[i]]); //For x and y of the same length
}
In JavaScript x and y can be objects arrays
jsFiddle It :)
make an empty array and push the child arrays onto it
var array = [];
array.push([1,2,3,4]);
//array[0][0] == 1
or all in one shot
var array = [[1,2,3,4], [1,2,3,4], [1,2,3,4]];