Unable to update matrix created with Javascript Array constructor [duplicate] - javascript

This question already has answers here:
Unexpected behavior using Array Map on an Array Initialized with Array Fill [duplicate]
(1 answer)
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 9 months ago.
I am doing some Javascript Matrix exercises and came across the problem of my Matrix not updating as expected when it's created using the Javascript Array constructor.
I created a matrix called theatre:
const theatre = new Array(5).fill(new Array(10).fill(0));
which prints as expected:
console.log(theatre)
[ [ 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 ] ]
however, when I attempt to change the values of each element in the first two rows to 1, every value in the matrix is changed.
for(let i = 0; i < 2; i++){
for(let j = 0; j < 10; j++){
theatre[i][j] = 1;
}
}
console.log(theatre)
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ] ]
To test further, I updated theatre to be equal to a matrix instead of using the array constructor and ran the for loop again which returned the expected output.
const theatre = [ [ 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 ] ]
for(let i = 0; i < 2; i++){
for(let j = 0; j < 10; j++){
theatre[i][j] = 1;
}
}
console.log(theatre)
[ [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ],
[ 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 ] ]
Why doesn't this logic work as expected on the matrix created with the Array constructor? Am I misunderstanding how the array constructor works with fill?

Related

Making a chessboard with two queens on it [duplicate]

This question already has answers here:
Unexpected value change in 2D array in JavaScript
(1 answer)
How can I create a two dimensional array in JavaScript?
(56 answers)
Closed 3 years ago.
Im looking to make an 8 x 8 chessboard in my terminal. I've made the proper 8 x 8 grid but can't add the two queens now as 1's
I keep trying as you can see in the code arrayz[0][1] = 1. I'm wondering if the problem is with my looping or there's an easy way to insert two ones into the problem.
const generateBoard= function(){
let arrayz = []
let set= []
let newArray = []
for (i = 0; i < 8; i++){
newArray.push(0)
}
for (y = 0; y < 8; y++){
//newArray[0][1] = 1
arrayz.push(newArray)
arrayz[0][1] = 1 //my failed code that im trying to use to input a single one
}
return arrayz
}
console.log(generateBoard(whiteQueen, blackQueen))
[ [ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0, 0, 0, 0 ] ] //what i keep getting
[ [ 0, 1, 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, 1 ] ]//what i want
This code creates only one board row array, newArray, rather than the desired 8. All 8 entries in the array arrayz are just references to newArray. Modifying any one of them will modify all 8, which is obviously not the intent.
In fact, printing the output here on Stack Overflow shows:
[
[
/**id:2**/
0,
1,
0,
0,
0,
0,
0,
0
],
/**ref:2**/,
/**ref:2**/,
/**ref:2**/,
/**ref:2**/,
/**ref:2**/,
/**ref:2**/,
/**ref:2**/
]
Which labels each reference array as a pointer to the first element which has the id 2. Here's the runnable example:
const generateBoard= function(){
let arrayz = []
let set= []
let newArray = []
for (i = 0; i < 8; i++){
newArray.push(0)
}
for (y = 0; y < 8; y++){
//newArray[0][1] = 1
arrayz.push(newArray)
arrayz[0][1] = 1 //my failed code that im trying to use to input a single one
}
return arrayz
}
console.log(generateBoard())
The reference problem can be addressed in a variety of ways. For example, changing
arrayz.push(newArray)
to
arrayz.push(newArray.slice());
makes a true copy of newArray using Array#slice, eliminating the unwanted aliasing.
Another way to make a 2d grid of zeroes is using the Array constructor, Array#fill and Array#map:
const board = Array(8).fill().map(() => Array(8).fill(0));
board[0][1] = 1;
console.log(board);

How to write out n*n Matrix values in JavaScript?

I'm new to JavaScript, so I decided to try to make a simple n*n Array. When I'm trying to write it out, I get, something starnge back.
var map = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 3, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 3, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
];
function GoTh() {
for (var i = 0; i < map.length; i++) {
for (var j = 0; j < map[i].length; j++) {
console.log(map[i][j]);
}
}
}
GoTh();
I expected it to write all 100 values, but it gives back this:
1 2 3 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 3 1
That's because same-value console.logs are grouped together in browsers' consoles.
This can usually be disabled, i.e. in Chrome & Opera:
In Firefox it's in console's settings (press F1 while using console)
Another option is to write more data along with the value, eg.:
console.log(i, j, map[i][j]);
The problem is the ouput in the console itself. If there are multiple similar entries - like the first 10 elements of value 1 in the first row plus the 1 in the second row, it will be grouped as a single entry of 11. You can see that there are multiple if you look to the right of a particular entry.

How to determine if chunks of a value could fit into an array

Given an input array of 1s and 0s of arbitrary length, such as:
[0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0]
How can I (most efficiently) calculate a new array detailing if chunks of size n 0s which can fit into the input?
Examples
Where output now means
1 == 'Yes a zero chunk that size could go here'
0 == 'Couldn't fit a chunk that size there'
Chunk size = 1 ([0]): [1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1]
Chunk size = 2 ([0,0]): [0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1]
Chunk size = 3 ([0,0,0]): [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
Chunk size = 4 ([0,0,0,0]): [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
I'm using ES6, so any language features are fine.
EDIT:
The output shouldn't just be a 'yes'/'no' a chunk of size 'n' can fit in this array. More specifically, it needs to be an array of the same length, where a '1' / 'true' array value represents either:
Yes, a chunk of size 'n' could start and fit here, or
Yes, this slot could contain a chunk of size 'n' that started before it
On that second point, this would mean for chunk size 3:
input = [1, 0, 0, 0, 0, 1];
output = [0, 1, 1, 1, 1, 0];
Edit 2:
This is the function I came up with but it seems very inefficient:
const calculateOutput = (input, chunkSize) => {
const output = input.map((value, index) => {
let chunkFitsHere = false;
const start = (index - (chunkSize) >= 0) ? index - (chunkSize) : 0;
const possibleValues = input.slice(start, index + chunkSize);
possibleValues.forEach((pValue, pIndex) => {
let consecutives = 0;
for (let i = 0; i < possibleValues.length - 1; i += 1) {
if (consecutives === chunkSize) {
break;
}
if (possibleValues[i+1] === 0) {
consecutives += 1;
} else {
consecutives = 0;
}
}
if (consecutives === chunkSize) {
chunkFitsHere = true;
}
});
return chunkFitsHere ? 1 : 0;
});
return output;
};
You could count the connected free places by reversing the array and take an flag for the last return value for mapping.
Array before final mapping and after, depending on n
1 0 4 3 2 1 0 0 2 1 0 0 0 3 2 1 0 2 1 array with counter
1 0 4 4 4 4 0 0 2 2 0 0 0 3 3 3 0 2 2 array same counter
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ------------------
1 0 1 1 1 1 0 0 1 1 0 0 0 1 1 1 0 1 1 n = 1
0 0 1 1 1 1 0 0 1 1 0 0 0 1 1 1 0 1 1 n = 2
0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 1 0 0 0 n = 3
0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 n = 4
function chunk(array, n) {
return array
.slice()
.reverse()
.map((c => v => v ? c = 0 : ++c)(0))
.reverse()
.map((l => v => l = v && (l || v))(0))
.map(v => +(v >= n));
}
var array = [0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0];
console.log(chunk(array, 1).join(' '));
console.log(chunk(array, 2).join(' '));
console.log(chunk(array, 3).join(' '));
console.log(chunk(array, 4).join(' '));
If you like only one mapping at the end, remove the last two map and use
.map((l => v => l = +(v && (v >= n || l)))(0));
for final mapping.
You can traverse array once, calculating length of the series of zeros. If it is long enough, fill output with series of 1 of the same length.
Note that you can fill output for different chunk lengths simultaneously (filling chunks in rows of 2d array with row index not exceeding zerolen)
Python code:
def zerochunks(a, n):
l = len(a)
result = [0] * l #list of l zeros
zerolen = 0
for i in range(l + 1):
### Short circuit evaluation to shorten code
if (i==l) or (a[i] != 0):
if (zerolen >= n): #series of zeros is finished here
for j in range(i - zerolen, i):
result[j] = 1
zerolen = 0
else:
zerolen += 1
return result
print(zerochunks([0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0], 1))
print(zerochunks([0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0], 2))
print(zerochunks([0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0], 3))
print(zerochunks([0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0], 4))
print(zerochunks([0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0], 5))
>>>
[1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1]
[0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1]
[0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0]
[0, 0, 1, 1, 1, 1, 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]
And function for getting all arrays with chunks in maxn range:
def zerochunksall(a, maxn):
l = len(a)
result = [[0] * l for i in range(maxn)]
zerolen = 0
for i in range(l + 1):
if (i==l) or (a[i] != 0):
for k in range(0, zerolen):
for j in range(i - zerolen, i):
result[k][j] = 1
zerolen = 0
else:
zerolen += 1
return result
print(zerochunksall([0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0], 5))
>>
[[1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],
[0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1],
[0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 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]]
function fit(input, n) {
var output = [];
for(var i = 0; i < input.length; i++) {
var fit = true;
for(var j = i; j < i + n; j++) {
if(j >= input.length || input[j]) { // either over the array size or occupied
fit = false;
break;
}
}
output.push(fit);
}
return output;
}
var input = [0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0];
console.log(fit(input, 1).map(v => +v));
console.log(fit(input, 2).map(v => +v));
console.log(fit(input, 3).map(v => +v));
console.log(fit(input, 4).map(v => +v));
outputs
[ 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1 ]
[ 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 ]
[ 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]
[ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
These don't seem to exactly match your expected output though, but that may be because I'm assuming the flags in the array should mark the start of the chunk (i.e. can you fit N truthy values in the array starting from this position).
(See below, where e = your expected result, n = the output of my algorithm.)
input = [ 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0 ]
e = 2 = [ 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1 ]
n = 2 = [ 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 ]
==== ==== ==== ====
You can use array.prototype.some to check if the chunk can fit starting to some index of the input array. To check if the chunk with it's actual length can fit, you can use array.prototype.every:
var input = [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0];
var chunk = [0,0,0];
var res = input.some((e, i) => chunk.every((c, j) => input[i + j] === c));
console.log(res);
var input = [0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0];
var chunk = [0, 0, 0, 0, 0, 0, 0, 0];
var res = input.some((e, i) => chunk.every((c, j) => input[i + j] === c));
console.log(res);
You could use some method and then if the current element is 0 you can slice part of the array from current index and check if its all zeros.
const data = [0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0]
function check(arr, n) {
let chunk = Array(n).fill(0).join('');
return arr.some((e, i) => e === 0 && arr.slice(i, i + n).join('') == chunk)
}
console.log(check(data, 3))
console.log(check(data, 4))
console.log(check(data, 5))

Calculating anti-aliasing on a grid of points

I'm representing an image by a list of integers representing the intensity of each pixel in an image. Each point is either 0 or 1. Given this data, how can I calculate the antialiased values so the final result is smooth?
Example data:
// What I have
const aliased = [
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 1, 0,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
];
// What I want to calculate
const smoothed = [
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
0, 0, 1, 0, 0.5, // <- point with intensity of 50%
0, 0, 0, 1, 0,
0, 1, 0, 1, 0,
0, 0, 1, 0, 0,
0, 0, 0, 0, 0,
];
Current input
Desired output

How can I cumulate _.zip, _.map _.reduce operations?

Given a JSON as this one :
var data = {
"entries": [
{
"fund": 1,
"values": [
{ "name": "alm1", "splits": [ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]},
{ "name": "alm2", "splits": [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
]
},
{
"fund": 2,
"values": [
{ "name": "alm1", "splits": [ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ "name": "alm2", "splits": [ 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ "name": "alm3", "splits": [ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] }
]
}
]
};
I would be able to set "sums" property as it with lodash/underscore :
var expected = {
"entries": [
{
"fund": 1,
"values": [
{ "name": "alm1", "splits": [ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]},
{ "name": "alm2", "splits": [ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
],
"sums": [ 0.5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
},
{
"fund": 2,
"values": [
{ "name": "alm1", "splits": [ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ "name": "alm2", "splits": [ 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] },
{ "name": "alm3", "splits": [ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0] }
],
"sums": [ 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
}
],
"sums": [ 4.5, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0]
};
I've tried different methods with lodash, without success.
_.map(), _.reduce() or _.zip()
Is it possible to cumulate/chain call to obtain the expected result?
Thanks a lot for your help.
I think unzip() is better suited for what you're doing:
var a1 = [ 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
a2 = [ 1.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
a3 = [ 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
_([a1, a2, a3])
.unzip()
.map(_.sum)
.value()
// → [4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Categories

Resources