Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
Let's imagine I have to arrays:
const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const array2 = [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];
array2.map((elem, index) => {
// Looking here to return the value from array1 by index
});
From array2 I am looking to return values from array1, by the index position, but just in the range 1 -10. The idea is that it should go in a kind of circle where the start value is 1 and end value is 10.
The expected output for the above example is:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5]
More examples of how it should work:
Index 1 from array2 -> return 1 from array1
Index 10 from array2 -> return 10 from array1
Index 12 from array2 -> return 2 from array1
Index 20 from array2 -> return 10 from array1
Index 999 from array2 -> return 9 from array1
Index 1225 from array2 -> return 5 from array1
You can use the remainder operator (%):
const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const array2 = [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];
const result = array2.map((elem, index) => array1[index % array1.length]);
console.log(result);
You really don't need to have array2, which provides no information other than its length -- the zeroes are not relevant. So given just the length, it could be as follows:
const array1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const length = 15;
const result = Array.from({length}, (elem, index) => array1[index % array1.length]);
console.log(result);
You probably don't need two arrays to achieve this. You could use the modulo operator to perform 'wrap around' like lookups.
For example:
array1[index % (array1.length)]
if you absolutely need the info in a second array, something like this would achieve the desired result:
array2.forEach((_, index) => array2[index] = array1[index % (array1.length)]);
I have a game, (published BTW its here at https://juniorcpc.itch.io/dungeon-game and the download file for the code is there too), and it uses arrays to create tile maps. (0-4 numbers represent different tiles) The problem is i can only create maps and publish those, and i want to know how to have the code create those array maps for me. I cannot use other tutorials, as they only show how to with tile maps, or mazes, or something else, but mine uses arrays not other systems. If there is a way to make a procedural map with arrays that would be awesome, thanks!
BTW the arrays are 10x10 grids, 1 = wall, 0 = empty space, 3 = exit.
Example of array:
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 0, 0, 2, 4, 1,
1, 2, 2, 0, 0, 2, 2, 2, 2, 1,
1, 1, 1, 2, 0, 2, 2, 2, 2, 1,
1, 2, 2, 0, 0, 2, 2, 2, 4, 1,
1, 0, 0, 0, 2, 2, 2, 3, 2, 1,
1, 0, 2, 2, 2, 2, 2, 2, 2, 1,
1, 0, 2, 1, 1, 2, 0, 0, 0, 1,
1, 0, 2, 2, 2, 2, 0, 0, 0, 1,
1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
],
Here is how it draws them: ( i have a canvas in my HTML with a width of 300px and a height of 300px)
function mapM() {
var ctx = document.getElementById("canv").getContext('2d');
ctx.fillStyle = "red";
var mapOnX = -1;
var mapOnY = 0;
var l = map[0].length + 1;
for (i = 0; i < l; i++) {
if (i % 10 == 0) {
var mapOnX = 0;
mapOnY++;
} else {
mapOnX++;
}
if (map[level][i] == 1) {
ctx.fillStyle = "red";
} else {
if (map[level][i] == 0) {
ctx.fillStyle = 'blue';
} else {
if (map[level][i] == 3) {
ctx.fillStyle = 'gold';
} else {
if (map[level][i] == 2) {
ctx.fillStyle = 'black';
} else {
ctx.fillStyle = 'lightBlue';
}
}
}
}
ctx.fillRect(mapOnX * 25, mapOnY * 25, 25, 25);
ctx.fillStyle = 'purple';
ctx.fillRect(mapX * 25, mapY * 25, 25, 25);
}
}
Dont worry about other numbers i can do that. Thanks!
:) I'm creating a maze using JS and P5, with a two dimensional array filled with numbers 0-8. 0 are empty spots, 1 are walls, 2 is the character you walk with, 3 is the exit and 4-8 are items that randomly spawn. In order to exit the maze (through 3, which is set on a fixed spot), all items need to be collected (if you walk over an item, the value of this spot changes back to 0), so every value in the array should be below 4 in order to exit. Now I need a way to check if this is the case.
I tried it with every() but I guess this only works for regular arrays. I suppose I need a for loop but I don't know this should look. So that's where I need help!
My maze consists of 18 rows and columns, like so (but then 15 more rows)
let maze = [
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
[1,2,0,0,0,0,1,0,1,0,0,0,0,1,0,0,1,0,1,0,0,0,3],
[1,1,1,1,1,0,1,0,0,0,1,1,0,0,0,0,1,0,1,0,1,0,1]
]
The items spawn randomly, this already works. Now I tried checking if every value is <= 3, with the every, like so
function checkBoard(mazenumbers){
return mazenumbers <= 3;
}
function alertMazenumbers() {
alert(maze.every(checkBoard));
}
And want this to display through an alert, once you walk into the exit location, like this
else if(direction === 'right') {
if(maze[playerPos.y][playerPos.x + 1] == 3) {
alertMazenumbers();
}
I want to get an alert with true if every value is <= 3, and false if not.
Currently, with this every(), I do get the alert but it only returns false, even when all items are cleared and it should return true.
You are on the right track using every!
The maze is an array of arrays (as Denys mentioned in his comment), so you have to use every twice, like so:
function canExitMaze(maze) {
return maze.every(row => row.every(cell => cell <= 3))
}
If you don't recognize the arrow function syntax (=>) this article explains it.
Hope this helps!
You can check if every point in the maze is <=3 by doing this
const isTrue = num => num <= 3; // is a single cell true
const isRowTrue = row => row.every(isTrue); // are all cells in a row true
const isMazeTrue = rows => rows.every(isTrue); // are all cells in all rows true
const maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]
];
console.log(isMazeTrue(maze));
Method 1: Check if every array only contains numbers that are <= 3
let maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]
];
function testMaze(maze) {
return maze.every(row => row.every(itemIsValid));
}
function itemIsValid(item) {
return item <= 3;
}
console.log(testMaze(maze));
maze[2][4] = 4;
console.log(testMaze(maze));
Method 2: Merge the arrays and search the numbers
var maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]
];
function testMaze(maze) {
return [].concat(...maze).every(itemIsValid);
}
function itemIsValid(item) {
return item <= 3;
}
console.log(testMaze(maze));
maze[2][4] = 4;
console.log(testMaze(maze));
Method 3: Convert the maze to a string and use regex
var maze = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 3],
[1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]
];
function testMaze(maze) {
//or maze.toString().match(/\d+/g).every(x => itemIsValid(+x));
return !/[4-8]/g.test(`${maze}`);
}
function itemIsValid(item) {
return item <= 3;
}
console.log(testMaze(maze));
maze[2][4] = 4;
console.log(testMaze(maze));
I have the following array:
arr = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 1, 0, 0, 2 ],
[ 1, 0, 0, 1, 0, 2, 4 ],
[ 0, 0, 0, 0, 2, 4, 4 ],
[ 0, 0, 0, 0, 4, 4, 0 ],
[ 1, 1, 1, 0, 0, 0, 0 ],
[ 1, 1, 0, 2, 0, 0, 2 ],
[ 1, 0, 0, 4, 0, 2, 0 ],
[ 0, 0, 0, 4, 2, 0, 0 ],
[ 0, 0, 2, 0, 0, 0, 1 ],
[ 0, 2, 4, 0, 0, 1, 2 ],
[ 2, 4, 4, 2, 1, 2, 4 ],
[ 4, 4, 0, 0, 2, 4, 0 ]
]
Currently, I'm getting the max array sum in arr i.e 19 like this
function getMaxSum(arr) {
return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[arr.length - 1];
}
I need to know is there any better way to achieve this?
I'm using array length of the original array to get the last element of resulting array because in this case, length of original array and resulting array is same. If the scenario is different then how can I use the length of the resulting array here:
return arr.map(e => e.reduce((a, b) => a + b, 0)).sort((a,b) => a - b)[HERE - 1];
Not a huge improvement, but it seems a little more literal to spread the values into Math.max
const data = [
[ 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 0, 0, 1, 1, 0 ],
[ 1, 0, 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 1, 0, 0, 2 ],
[ 1, 0, 0, 1, 0, 2, 4 ],
[ 0, 0, 0, 0, 2, 4, 4 ],
[ 0, 0, 0, 0, 4, 4, 0 ],
[ 1, 1, 1, 0, 0, 0, 0 ],
[ 1, 1, 0, 2, 0, 0, 2 ],
[ 1, 0, 0, 4, 0, 2, 0 ],
[ 0, 0, 0, 4, 2, 0, 0 ],
[ 0, 0, 2, 0, 0, 0, 1 ],
[ 0, 2, 4, 0, 0, 1, 2 ],
[ 2, 4, 4, 2, 1, 2, 4 ],
[ 4, 4, 0, 0, 2, 4, 0 ]
]
function getMaxSum(arr) {
return Math.max(...arr.map(e => e.reduce((a, b) => a + b, 0)))
}
console.log(getMaxSum(data))
As #Rajesh points out, Math.max is faster that a sort:
const numbers = Array(10000).fill().map((x,i)=>i);
const max = numbersIn => Math.max(...numbersIn);
const getMaxViaSort = numbersIn => numbersIn
.sort((a, b) => a > b ? -1 : 1)[0]
console.time('max');
max(numbers);
console.timeEnd('max');
console.time('max via sort');
getMaxViaSort(numbers);
console.timeEnd('max via sort');
The optimal strategy should be one where we need the least interaction with the arrays.
In my method i test the array products individually and compare that with a variable inside my loop. In this way i don't need to run a new implied loop to have Math.max check all my entries again, netting a speed boost.
This also saves on memory management as i don't need to map and return a new array of results for Math.max.
At the end of the loop i simply return the variable.
var data = [
[1, 1, 1, 1, 1, 1, 1],
[1, 1, 0, 0, 1, 1, 0],
[1, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 2],
[1, 0, 0, 1, 0, 2, 4],
[0, 0, 0, 0, 2, 4, 4],
[0, 0, 0, 0, 4, 4, 0],
[1, 1, 1, 0, 0, 0, 0],
[1, 1, 0, 2, 0, 0, 2],
[1, 0, 0, 4, 0, 2, 0],
[0, 0, 0, 4, 2, 0, 0],
[0, 0, 2, 0, 0, 0, 1],
[0, 2, 4, 0, 0, 1, 2],
[2, 4, 4, 2, 1, 2, 4],
[4, 4, 0, 0, 2, 4, 0]
];
function getMaxSum1(arr) {
//The original method
return arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }).sort(function (a, b) { return a - b; })[arr.length - 1];
}
function getMaxSum2(arr) {
//From https://stackoverflow.com/a/51704254/5242739
return Math.max.apply(Math, arr.map(function (e) { return e.reduce(function (a, b) { return a + b; }, 0); }));
}
function sumArray(arr) {
var val = 0;
for (var index = 0; index < arr.length; index++) {
val += val;
}
return val;
}
function getMaxSum3(arr) {
//My method
var max;
for (var i = 0; i < arr.length; i++) {
var val = sumArray(arr[i]);
if (max === void 0 || val > max) {
max = val;
}
}
return max;
}
//TEST
//parameters
var runs = 10;
var tests = 100000;
//output area
var out = document.body.appendChild(document.createElement("pre"));
//test functions
function simulate1() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum1(data);
}
out.textContent += 'getMaxSum1 took: ' + (Date.now() - dt) + "ms\n";
requestAnimationFrame(simulate2);
}
function simulate2() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum2(data);
}
out.textContent += 'getMaxSum2 took: ' + (Date.now() - dt) + "ms\n";
requestAnimationFrame(simulate3);
}
function simulate3() {
var t = tests;
var dt = Date.now();
while (t--) {
getMaxSum3(data);
}
out.textContent += 'getMaxSum3 took: ' + (Date.now() - dt) + "ms\n\n";
if (runs--) {
requestAnimationFrame(simulate1);
}
}
//start
simulate1();
pre {
max-height: 200px;
overflow-y: scroll;
background-color: #eee;
}
I included OliverRadini's answer to compare the relative speed boosts.
i'm making a HTML5 game and i'm using a matriz to store the map. But now i'm using $getJson to read that values through a json file and it works, but the problem is when a change the value of my matrix through the web inspector the map changes but when i call that function directly on code i get an error:
game.js:51TypeError: 'undefined' is not an object (evaluating 'levels.Level1')
line 51: mapa.loadMap(levels.Level1.board);
Why this only works when a call the function "mapa.loadMap(levels.Level1.board)" on web inspector?
function map(){
this.loadMap = function (l){
var j= 0;
for (var i = 0; i < l.length; i++) {
var object = l[i];
for (property in object) {
var value = object[property];
this.board[j][property] = value;
}
j++;
}
}
this.width = 10;
this.height = 8;
this.image = new Image();
this.image.src = "images/level1/tiles.png";
this.board = [ [1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 2],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[8, 0, 0, 0, 33, 1, 1, 1, 1, 1],
[8, 0, 0, 0, 0, 0, 0, 37, 0, 0],
[25, 26, 0, 0, 0, 0, 0, 38, 0, 0],
[27, 28, 5, 5, 6, 7, 0, 38, 0, 0],
[1, 1, 1, 1, 1, 9, 5, 39, 5, 5],
];
(...)
Forget that XD
My code is a mess because it's a sketch but i solved with:
$(document).ready(function(){
init();
});
$(window).load(function () {
console.log(levels.Level1.board);
mapa = new map();
render();
});
Thanks for helping :)
And sorry for my english XD
$(document).ready(function(){
init();
});
$(window).load(function () {
console.log(levels.Level1.board);
mapa = new map();
render();
});