unable to create an automatic filling array without writing it manually - javascript

I'd like to create an coordinates array so that I don't have to manually write 100 pairs of x and y values. I was thinking of using for loop inside another for loop, but I couldn't achieve it.
I'd like to make an empty array, named CoordsArray, and making use of the push method within the most inner for, create an mixed array as follows:
var coordsArray = [
{x:0,y:0},{x:0,y:20},{x:0,y:40},{x:20,y:0},{x:20,y:20},{x:20,y:40},{x:40,y:0},{x:40,y:20},{x:40,y:40}
]
The usage of the above code is for creating three rows of three circles (using D3js) without creating the array manually, because later I'll have to create a 10 rows of ten circles and creating the x and the y position of each one will be very cumbersome. What's the best approach to achieve it? Thanks.

The pattern I see is this:
the x-value is the (array index / # of cols) rounded down to the
nearest integer
the y-value is the modulo of the (array index / # of
cols)
So you can start with an empty array of length (rows * cols), fill each entry with the circle size, and then map each element to an object created by multiplying the array value by those x and y calculations...
let rows = 3,
cols = 5,
size = 20;
let data = new Array(rows*cols)
.fill(size)
.map((d, i) => ({
x: d * Math.floor(i/cols),
y: d * (i%cols)
}));
console.log(data);
Granted, it may not be as human-readable as nested loops, but I like it...

You should always post the code you've tried.
Here's one way:
var coordsArray = [];
const rows = 10,
cols = 10,
size = 20;
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
coordsArray[row * cols + col] = [row * size, col * size];
}
}

Related

From an array of objects, I want to pick a random object from the array and set one of that object's variables

I have an array named grid. Stored in that array is an object, cell. I want to set one of cell's variables(isBomb) to true.
I know that this isn't quite how to do it, but here is my(nonfunctioning implementation).
When I try to run it, I get this error message: Main, line 32:Cannot set property '288' of undefined I assume that's because I formatted it wrong. Could anyone help?
for(var i in grid){
for(var j=0; j<bombAmount; j++){
this.isBomb[floor(random(grid.length))]=true;
}
This is in javascript, with the p5.js library.
Openprocessing link
You can use Math.random() to achieve this. For example:
const grid = [{
cellId: 1
}, {
cellId: 2
}, {
cellId: 3
}, {
cellId: 4
}, {
cellId: 5
}, {
cellId: 6
}, {
cellId: 7
}, {
cellId: 8
}, {
cellId: 9
}, {
cellId: 10
}];
function pickRandomCell() {
return grid[Math.floor(Math.random() * grid.length)];
}
for (let i = 0; i < 50; i++) {
console.dir(pickRandomCell());
}
As the answer above, do Math.random() and update the cell like this:
// Do a loop to apply each bomb to a cell
for (let i = 0; i < bombAmount; i++) {
const randomPosition = Math.round(Math.random() * (grid.length -1));
// Select random cell from grid, and update the "isBomb" to true
grid[randomPosition].isBomb = true;
}
There are quite a few issues with the code that this question doesn't address.
I will start with the simplest question from the title: picking a random object from the an array. The existings answers already address this. I wanted to point out that random() in p5 can also take an array as an argument and returns a random item from that array, as you can see in the reference example:
function setup(){
let words = ['apple', 'bear', 'cat', 'dog'];
let word = random(words); // select random word
console.log(word);
createCanvas(100, 100);
text(word, 10, 50);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
Back to the snippet you posted:
for(var i in grid){
for(var j=0; j<bombAmount; j++){
this.isBomb[floor(random(grid.length))]=true;
}
}
In the context above this will not point to an individual cell.
You might be looking at something like grid[i].isBomb = true instead.
isBomb is a boolean property of Cell hence the errors when trying to access it via array access notation.
The connection between bombAmount and isBomb is unclear.
Perhaps you meant to use something like the bombsFound array returned by checkArea() somehow ?
If you want to pick a random cell to have a bomb or not you could something like:
for(let i = 0; i < grid.length; i++){
grid[i].isBomb = random(0.0, 1.0) > 0.5;
}
the example above sets a psuedo random chance of 50/50 that a cell will be a bomb or not.
The Cell constructor actually accepts isBomb as it's last argument:
function Cell(x, y, bombNum, clicked, isBomb)
Therefore you could skip the loop completely and simply randomly assign isBomb when populating grid:
for (var y = 0; y < rows; y++) {
for (var x = 0; x < cols; x++) {
var cell = new Cell(x, y, index(x, y), false, random(0.0, 1.0) > 0.5);
grid.push(cell);
}
}
Currently it looks like you're not passing the expected arguments to the Cell constructor:
var cell = new Cell(x, y, false);
These are just a few of the issues and points out that you may not fully understand the code you're trying to modify. I recommend slowing down, stepping back for a second and with pen an paper figure out what you're trying to achieve. With the clear goals, break them down into very simple individual steps, solve one step at a time, then start integrating the tested individual steps into the larger program.
Update based on the clarification in the comment bellow you could easily do something like:
for(let i = 0; i < bombAmount; i++){
grid[i].isBomb = random(0.0, 1.0) > 0.5;
}
However this won't guarantee 20 bombs, but a 50-50 chance that the 1st 20 cells might have bombs.
If you want to guarantee 20 bombs at random locations you could use a temporary array to pick a random from, but remove that randomly selected item so it won't be selected on the next iteration.
Here's a snippet to illustrate the idea:
// make a new array that will hold references to the original cells
let selection = grid.map(cell => cell);
// for the bomb amount...
for(let i = 0 ; i < bombAmount; i++){
// pick a random index
let randomIndex = floor(random(selection.length));
// retrieve the cell at that index and remove it from the selection list
let cell = selection.splice(randomIndex, 1);
// set that cell as a bomb
cell.isBomb = true
}

How can I form matrix lines programmaticaly based on an element list?

I'm practicing some programming logic with a challenge that a friend shared with me. Here's the problem:
Write a script that takes an integer n as the numbers of rows and columns of a matrix and take the element list of the matrix.
Example: n=3
matrix = [[11 2 4],
[4 5 6],
[10 8 -12] ]
And print the determinant of the matrix to -100 <= m[i][j] <= 100
My solution, code, problem, question so far:
SOLUTION
Create an array with n empty positions, in the future those positions will store other arrays, they will be each line of the matrix.
Loop through each empty position to fill with a new matrixLine
Create a variable inside the loop that will be a matrix line with elements
Loop the element list to get the necessary elements of a line
Put the matrix line with elements on the final matrix
CODE
function createMatrix(rowsAndColumns, elementsList) {
const finalMatrix = Array(rowsAndColumns)
for(let i = 0; i < finalMatrix.length; i++) {
let matrixLineWithElements = []
for(let k = 0; k < rowsAndColumns; k++) {
matrixLineWithElements[k] = elementsList[k]
}
finalMatrix[i] = matrixLineWithElements
}
}
PROBLEM
As you have probably noticed on the code, I'm taking the same elements from the list to form a line. The final matrix is formed successfully, but I can't figure out how to cout different values per line, here's an image of my terminal:
QUESTIONS
I stopped trying to figure out while code and took the following notes -
If I have a list of four elements:
[10. 90, 100, 25]
I will form a matrix 2X2, so I need to count the elements of the list.
0(zero) and 2 are the start point of the counting, with a counting salt of 2 (same value of n variable).
There's some kind of pattern here, look, if I got a 9 element list, such as
[10, 90, 100, 25, 36, 48, 2, 5, 6]
I will form a matrix 3X3, so I need to count the elements of the list.
0(zero), 3 and 6 are the starting point of counting, with a counting salt of 3 (same value of n variable).
How can I do this counting programmatically?
Do my approach and thinking on the problem make some sense or there are better ways of doing it?
Let's go by examples
Col 0
Col 1
Row 0
0
1
Row 1
2
3
Col 0
Col 1
Col 2
Row 0
0
1
2
Row 1
3
4
5
Row 2
6
7
8
These are 2 "matrices" with cells that I filled with indexes of elementsList elements that are to be placed in them.
You can see that for the "0th" row the column number is the index, but for the 1st row it's the column index increased by the number of elements in the first row.
In the 2nd row it's the column index increased by 2 times the length of row (or by the number of elements already placed if we go with the second version of code - with counter).
We can deduce that nth row indexes start at n*(length of row) and increase by one just as the column indexes hence the formula for the elementsList index in the matrix cell: (row number) * (length of row) + columnn index
function createMatrix(rowsAndColumns, elementsList) {
const finalMatrix = Array(rowsAndColumns)
for(let i = 0; i < finalMatrix.length; i++) {
let matrixLineWithElements = []
for(let k = 0; k < rowsAndColumns; k++) {
matrixLineWithElements[k] = elementsList[k+i*finalMatrix.length] // here you just needed to add i times (max i)
}
finalMatrix[i] = matrixLineWithElements
}
return finalMatrix // I added this only so that it can be printed
}
console.log(createMatrix(2,[1,2,3,4]))
Other option:
function createMatrix(rowsAndColumns, elementsList) {
const finalMatrix = Array(rowsAndColumns)
let counter = 0 // Added counter
for(let i = 0; i < finalMatrix.length; i++) {
let matrixLineWithElements = []
for(let k = 0; k < rowsAndColumns; k++) {
matrixLineWithElements[k] = elementsList[counter]
counter+=1 // Increment counter
}
finalMatrix[i] = matrixLineWithElements
}
return finalMatrix // I added this only so that it can be printed
}
console.log(createMatrix(2,[1,2,3,4]))
However, I dislike mutating the variables
function createMatrix(n, elementsList) {
const range = (length) => [...Array(length).keys()]
const finalMatrix = range(n).map((i) =>
range(n).map((j) =>
elementsList[i * n + j]
))
return finalMatrix // I added this only so that it can be printed
}
console.log(createMatrix(2,[1,2,3,4]))

How to efficiently feed the output of a GPU JS function back into it?

I am attempting to use GPU JS to accelerate the performance of a dynamic programming algorithm.
Here is my current code:
let pixels = new Uint32Array(5 * 5);
for (let i = 0; i < pixels.length; i++) {
pixels[i] = i;
}
function kFunction() {
let width = this.output.x;
let row = this.constants.row;
let col = this.thread.x;
let prevRow = (row - 1) * width;
let base = (row * width) + col;
let prevBase = (prevRow * width) + col;
let nw = this.constants.pixels[prevBase - 1];
let n = this.constants.pixels[prevBase];
let ne = this.constants.pixels[prevBase + 1];
return this.constants.pixels[base] + Math.min(Math.min(nw, n), ne);
}
var gpuKernel = gpu.createKernel(kFunction)
.setConstants({ pixels: pixels, row: 1 })
.setOutput([5, 5]);
console.log(gpuKernel());
This works, except I would like to have it run on each row, instead of just row 1.
The issue is that in order to run on the next row, the previous row has to be computed first (for rows n > 1 the nw, n, and ne values should be computed based on the previous row's value instead of pixels)
I could easily fix this by putting createKernel in a loop and running it on every row, but I believe that constantly returning the value from the GPU and sending it back is slow. I heard that Textures might be able to solve this, to maintain some sort of state, but I cannot find any relevant information on them.
Is what I'm asking to do possible? To have a single GPU function call to compute the entire cumulative sum table without passing data back and forth for each row computed?

Constructing a random array of given size from all elements of another array, with the condition of upper and lower bounds for their occurance

I have defined an array called box as follows:
var box = [a,b,c,d,e,f,g,h,i,j];
I am generating random number between 0 to the length of the array. In this case the length of the array is 10:
var random_number = Math.floor(Math.random() * box.length);
I retrieve values from the box array by passing the random number as an array index:
var random_element = box[random_number];
I need to create a new array called room using the elements from box, so that:
the size of room is 40,
every element from box is present in room,
each element from box must occur in 'room` at least 3 times,
each element from box must occur in 'room` at most 5 times.
Idea
The possible approach is to fill array first by the minimum amount of each element, then randomly add elements until the array is filled up. Of course we should take care about maximum bound too.
Code
MINIMUM_AMOUNT = 3
MAXIMUM_AMOUNT = 5
// We also need to track how much of each element we have
// Fill minimum amount of each element
for (i = 0; i < box.length; i++) {
for (j = 0; j < MINIMUM_AMOUNT; j++) {
room.push(box[i])
}
// At first the are only 3 elements
count[i] = MINIMUM_AMOUNT
}
// Fill the rest of the array
while (room.length != 40) {
random_index = Math.trunc(10 * Math.random())
random_elem = box[random_index]
// If this element did not yet reach its limit
if (count[random_index] < MAXIMUM_AMOUNT) {
room.push(random_elem)
count[random_index]++
}
}
Shuffling
For now your array will look like [a, a, a, b, b, b, ..., j, j, j, a, e, b, ...]. If you need items to be more randomly placed, consider using a shuffling algorithm.
I think #Destiners idea is perfect for this job. I just would like to share my implementation of that idea. I use the room array both to hold the characters and also for the lookup table. So for instance room.a will give the count of "a" characters in the room array. Then applied a generic proper shuffling.
Array.prototype.shuffle = function(){
var i = this.length,
j;
while (i > 1) {
j = ~~(Math.random()*i--);
[this[i],this[j]] = [this[j],this[i]];
}
return this;
};
var box = ["a","b","c","d","e","f","g","h","i","j"];
room = box.reduce((p,c) => (p[c] = 3, p.push(...c.repeat(3).split("")),p),[]);
while (room.length < 40) {
var c = box[~~(Math.random()*box.length)];
room[c] < 5 && (room.push(c), room[c]++);
}
room.shuffle();
console.log(room);
console.log(room.a);

Algorithm to remove extreme outliers in array

I've got an array which I use for the x-axis in a D3 graph, and it blows up because the chart size is too small for the size of the array. I had a look at data and there are extreme outliers in the data. See chart below.
The data around 0 (its not totally zero, its 0.00972 etc).
The data starts getting interesting around 70, then massive spikes about 100. the data then continues and then the same sort of thing on the other side about 200.
Can anyone help me with some algo that removes the extreme outliers? e.g. give me 95% or 90% percentiles and remove the contiguous elements (e.g. not just one element from the middle but x number of elements from the start of the array and the end of the array, where x depends on working out where best to do it based on the data? In Javascript as well please!
thanks!
ps you'll need to save the image to view it properly
Assuming the data is like
var data[] = {0.00972, 70, 70, ...};
first sort
data.sort(function(a,b){return a-b});
then take off the bottom 2.5% and top 2.5%
var l = data.length;
var low = Math.round(l * 0.025);
var high = l - low;
var data2 = data.slice(low,high);
An alternative would be to only show data within 3 standard deviations of the mean. If you data is normally distributed 99.7% will fall in this range.
var sum=0; // stores sum of elements
var sumsq = 0; // stores sum of squares
for(var i=0;i<data.length;++i) {
sum+=data[i];
sumsq+=data[i]*data[i];
}
var mean = sum/l;
var varience = sumsq / l - mean*mean;
var sd = Math.sqrt(varience);
var data3 = new Array(); // uses for data which is 3 standard deviations from the mean
for(var i=0;i<data.length;++i) {
if(data[i]> mean - 3 *sd && data[i] < mean + 3 *sd)
data3.push(data[i]);
}
Or similar using some multiple of the Inter-quartile range
var median = data[Math.round(l/2)];
var LQ = data[Math.round(l/4)];
var UQ = data[Math.round(3*l/4)];
var IQR = UQ-LQ;
var data4 = new Array();
for(var i=0;i<data.length;++i) {
if(data[i]> median - 2 * IQR && data[i] < mean + 2 * IQR)
data4.push(data[i]);
}

Categories