Flatten array to 1 line - javascript

Hey I need some help here in javascript
[ [ 0, 0, 0, -8.5, 28, 8.5 ],
[ 1, 1, -3, 0, 3, 12 ],
[ 2, 2, -0.5, 0, 0.5, 5.333333333333333 ] ]
I want that array above to be in the form of this
0 0 0 -8.5 28 8.5, 1 1 -3 0 3 12, 2 2 -0.5 0 0.5 5.333333333333333
concat and reduce is placing a comma after each value

You can do it simply using Array.prototype.map() & Array.prototype.join()
Example:
var myArr = [ [ 0, 0, 0, -8.5, 28, 8.5 ],
[ 1, 1, -3, 0, 3, 12 ],
[ 2, 2, -0.5, 0, 0.5, 5.333333333333333 ] ];
var str = myArr.map(insideArr => insideArr.join(" ")).join();
console.log(str);

arr.map(item => item.join(' ')).join(',');

This question can be answered in 2 steps. First, flatten out the array using the Array.prototype.reduce() higher order function with the spread operator (...). Then, use the Array.prototype.join() method to convert the flattened array into a list of numbers.
const arr = [ [ 0, 0, 0, -8.5, 28, 8.5 ],
[ 1, 1, -3, 0, 3, 12 ],
[ 2, 2, -0.5, 0, 0.5, 5.333333333333333 ] ];
const flatten = arr.reduce((combine, item) => [...combine, ...item], [])
.join(' ');

Related

snowflake UDTF update array at specific index

i'm very new to JS especially in snowflake and i am trying to achieve a very simple thing - i would like to update an array according to an index for each row.
this is my code:
CREATE TABLE T1(C1 INT); -- test table
INSERT INTO T1(C1) VALUES (1),(2),(3),(4),(5),(6),(7);
-- MY UDTF:
CREATE OR REPLACE FUNCTION "SUMMER"(INF FLOAT)
RETURNS TABLE (NUM float, NUM2 array)
LANGUAGE JAVASCRIPT
AS '{
processRow: function (row, rowWriter, context) {
this.ar[this.index]=-1;
rowWriter.writeRow( {NUM: this.index, NUM2: this.ar} );
this.index=(this.index+1)%3;
},
finalize: function (rowWriter, context) {
rowWriter.writeRow({NUM: 0,NUM2: [0,0,0,0]});
},
initialize: function(argumentInfo, context) {
this.ar=[0,0,0,0]; --array i want to update at specific index
this.index = 0; --index changing every row
}}';
SELECT * FROM T1,TABLE(SUMMER(C1::FLOAT));
Result I receive is:
1 0 [ -1, -1, -1, 0 ]
2 1 [ -1, -1, -1, 0 ]
3 2 [ -1, -1, -1, 0 ]
4 0 [ -1, -1, -1, 0 ]
5 1 [ -1, -1, -1, 0 ]
6 2 [ -1, -1, -1, 0 ]
7 0 [ -1, -1, -1, 0 ]
0 [ 0, 0, 0, 0 ]
Whereas i was hoping to be able to update the array according to an index, hence receive following arrays:
[0,0,0,0]
[-1,0,0,0]
[-1,-1,0,0]
[-1,-1,-1,0]
[-1,-1,-1,-1]
[-1,-1,-1,-1]
[-1,-1,-1,-1]
there are 3 problems, you are outputing N + 1 rows of output, but you say you want N (7) for the seven lines. Which implies you should drop the finalizer, as it's giving you the extra row. OR you do want the n+1 so you can have all the before and the final after, where as you code code is writing after, and a fake before (but afterwards). If you want the before, write the before in the initializer.
second problem, your array is 4 wide, and you want all four values changed, but you are modulating by 3. That needs to go to 4 it would seem.
And lastly, all your output values appear to be the make value, because you are assigning the "reference" to the array as the result. So you need to clone the array to make clean new data. This question implies slice is a good way to go thus:
so sticking with the N+1 way I would use:
I have made a tiny change to your set to -1 to sub 1, so we can see the wrap-round is working:
CREATE OR REPLACE FUNCTION "SUMMER"(INF FLOAT)
RETURNS TABLE (NUM float, NUM2 array)
LANGUAGE JAVASCRIPT
AS '{
processRow: function (row, rowWriter, context) {
//this.ar[this.index]=-1; -- tweaked to show it working
this.ar[this.index] -=1;
rowWriter.writeRow( {NUM: this.index, NUM2: this.ar.slice(0)});
this.index=(this.index+1)%4;
},
finalize: function (rowWriter, context) {
rowWriter.writeRow({NUM: 0, NUM2: [0,0,0,0]});
},
initialize: function(argumentInfo, context) {
this.ar=[0,0,0,0];
this.index = 0;
}}';
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7) ) as v(c1),
TABLE(SUMMER(v.c1::FLOAT))
ORDER BY 1;
gives:
C1
NUM
NUM2
1
0
[ -1, 0, 0, 0 ]
2
1
[ -1, -1, 0, 0 ]
3
2
[ -1, -1, -1, 0 ]
4
3
[ -1, -1, -1, -1 ]
5
0
[ -2, -1, -1, -1 ]
6
1
[ -2, -2, -1, -1 ]
7
2
[ -2, -2, -2, -1 ]
null
0
[ 0, 0, 0, 0 ]
so if you want to have the last row first, push the NULLS FIRST
SELECT *
FROM (VALUES (1),(2),(3),(4),(5),(6),(7) ) as v(c1),
TABLE(SUMMER(v.c1::FLOAT))
ORDER BY 1 NULLS FIRST;
gives:
C1
NUM
NUM2
null
0
[ 0, 0, 0, 0 ]
1
0
[ -1, 0, 0, 0 ]
2
1
[ -1, -1, 0, 0 ]
3
2
[ -1, -1, -1, 0 ]
4
3
[ -1, -1, -1, -1 ]
5
0
[ -2, -1, -1, -1 ]
6
1
[ -2, -2, -1, -1 ]
7
2
[ -2, -2, -2, -1 ]
Another option:
So if you really are trying to build an array of zeros and negative ones, you can just do it in SQL:
SELECT c1
,ARRAY_CONSTRUCT(0,0,0,0) as zeros
,ARRAY_CONSTRUCT(-1,-1,-1,-1) as negs
,LEAST(c1-1, 4) as nf
,ARRAY_SLICE(negs, 0, nf) as np
,ARRAY_SLICE(zeros, nf, 4) as zp
,ARRAY_CAT(np, zp) as answer
FROM VALUES (1),(2),(3),(4),(5),(6),(7) as v(c1)
ORDER BY 1;
gives:
C1
ZEROS
NEGS
NF
NP
ZP
ANSWER
1
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
0
[]
[ 0, 0, 0, 0 ]
[ 0, 0, 0, 0 ]
2
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
1
[ -1 ]
[ 0, 0, 0 ]
[ -1, 0, 0, 0 ]
3
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
2
[ -1, -1 ]
[ 0, 0 ]
[ -1, -1, 0, 0 ]
4
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
3
[ -1, -1, -1 ]
[ 0 ]
[ -1, -1, -1, 0 ]
5
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
4
[ -1, -1, -1, -1 ]
[]
[ -1, -1, -1, -1 ]
6
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
4
[ -1, -1, -1, -1 ]
[]
[ -1, -1, -1, -1 ]
7
[ 0, 0, 0, 0 ]
[ -1, -1, -1, -1 ]
4
[ -1, -1, -1, -1 ]
[]
[ -1, -1, -1, -1 ]
and that can be done in a one line wonder:
SELECT c1
,ARRAY_CAT(
ARRAY_SLICE(ARRAY_CONSTRUCT(-1,-1,-1,-1), 0, LEAST(c1-1, 4)),
ARRAY_SLICE(ARRAY_CONSTRUCT(0,0,0,0), LEAST(c1-1, 4), 4)
) as answer
FROM VALUES (1),(2),(3),(4),(5),(6),(7) as v(c1)
ORDER BY 1;
gives:
C1
ANSWER
1
[ 0, 0, 0, 0 ]
2
[ -1, 0, 0, 0 ]
3
[ -1, -1, 0, 0 ]
4
[ -1, -1, -1, 0 ]
5
[ -1, -1, -1, -1 ]
6
[ -1, -1, -1, -1 ]
7
[ -1, -1, -1, -1 ]

Javascript - Optimal way to get maximum sum of arrays in an array

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.

Weird Behaviour when nesting 2D arrays in a 3D array

Currently I'm working on a Minimax algorithm for four-in-a-row in javascript. I have decided to store possible moves in a array, continuing to nest arrays within arrays for every branch.
However, when I attempt to edit a certain value in an array, it edits all other values within the same column.
Code:
var BOARD = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
];
// Put 3 x 2D Arrays into one 3D Array
var NODE_TREE = [BOARD, BOARD, BOARD];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);
Chrome V8 interpreter output:
[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ] ]
What should happen but dosen't:
[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]
Javascript seems to ignore the First dimension index number. This issue only happens when I use an existing array nested within an array. If I were to make a 3D array from scratch, this bug does not happen.
For a lazy initalization, you could use a parsed JSON string.
This generates an independent object without references to the original object.
var BOARD = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
],
JSON_BOARD = JSON.stringify(BOARD),
NODE_TREE = [JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD), JSON.parse(JSON_BOARD)];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);
.as-console-wrapper { max-height: 100% !important; top: 0; }
When you put BOARD 3 times in to the array, you are not "copying" the items in to the new array, you are actually just creating 3 references to the original BOARD array.
Therefore any change made to any one of those references will be reflected in all instances of BOARD.
If you want to create 3 distinct arrays in your 3d array you will need to clone or copy the arrays. You can do this by mapping on the outer array and copy the contents with Array.prototype.slice();
var BOARD = [
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
];
// function to map and copy arrays with .slice()
function sliceArrays (outerArray){
return outerArray.map((arr)=>{
return arr.slice()
});
}
var NODE_TREE = [sliceArrays(BOARD), sliceArrays(BOARD), sliceArrays(BOARD)];
NODE_TREE[1][2][0] = 2;
console.log(NODE_TREE);
//[ [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ],
// [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 2, 0, 0 ] ],
// [ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ] ]

Regex to match unquoted strings but not numbers in CSV

Trying to write a regex for my text editor (BBEdit) to encode strings that are not already quoted within an almost correctly syntaxed JSON style object so that I can use within a JavaScript context that would otherwise see these text strings as undefined variables.
Thus :
[ 0, 0, Header, 1, 17, 480 ],
[ 1, 0, Start_track ],
[ 1, 0, Title_t, "Dance of the knights (Romeo & Juliet)" ],
[ 1, 0, Tempo, 600000 ],
[ 1, 0, Time_signature, 4, 2, 24, 8 ],
[ 1, 0, Key_signature, 1, "major" ]
would become:
[ 0, 0, "Header", 1, 17, 480 ],
[ 1, 0, "Start_track" ],
[ 1, 0, "Title_t", "Dance of the knights (Romeo & Juliet)" ],
[ 1, 0, "Tempo", 600000 ],
[ 1, 0, "Time_signature", 4, 2, 24, 8 ],
[ 1, 0, "Key_signature", 1, "major" ]
You could use the below regex.
([\[,]\s*)([A-Za-z_]\S*)(?=,|\s*\])
And then replace the match with $1"$2"
DEMO
Example:
> var s = '[ 1, 0, Title_t, "Dance of the knights (Romeo & Juliet)" ],';
> s.replace(/([\[,]\s*)([A-Za-z_]\S*)(?=,|\s*\])/g, '$1"$2"')
'[ 1, 0, "Title_t", "Dance of the knights (Romeo & Juliet)" ],'

Understanding the geometry of a truncated Icosahedron, for rendering

I'm trying to render a truncated icosahedron like above with clickable zones using Three.js.
I found the code for a regular icosahedron
var t = ( 1 + Math.sqrt( 5 ) ) / 2;
var vertices = [
[ -1, t, 0 ], [ 1, t, 0 ], [ -1, -t, 0 ], [ 1, -t, 0 ],
[ 0, -1, t ], [ 0, 1, t ], [ 0, -1, -t ], [ 0, 1, -t ],
[ t, 0, -1 ], [ t, 0, 1 ], [ -t, 0, -1 ], [ -t, 0, 1 ]
];
var faces = [
[ 0, 11, 5 ], [ 0, 5, 1 ], [ 0, 1, 7 ], [ 0, 7, 10 ], [ 0, 10, 11 ],
[ 1, 5, 9 ], [ 5, 11, 4 ], [ 11, 10, 2 ], [ 10, 7, 6 ], [ 7, 1, 8 ],
[ 3, 9, 4 ], [ 3, 4, 2 ], [ 3, 2, 6 ], [ 3, 6, 8 ], [ 3, 8, 9 ],
[ 4, 9, 5 ], [ 2, 4, 11 ], [ 6, 2, 10 ], [ 8, 6, 7 ], [ 9, 8, 1 ]
];
THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
And drew the conclusion that t is φ & vertices consists of all the permutations of:
(0, ±1, ±φ) (±1, ±φ, 0) (±φ, 0, ±1) - From Here
So I modified my vertices as per:
(0, ±1, ±3φ) (±2, ±(1+2φ), ±φ) (±1, ±(2+φ), ±2φ) - From Here
Resulting in:
var vertices = [
[-2, (1+2*t,t], [2,(1+2*t), t ], [-2,-(1+2*t),-t], [2,-(1+2*t),-t ],
[0,-1,3*t], [0,1,3*t], [0,-1,-3*t], [0,1,-3*t],
[1,-(2+t),-2*t ],[1,(2+t),2*t],[-1,-(2+t),-2*t],[-1,(2+t),2*t]
];
Now I understand I have to modify the faces as well. Icosahedron seems to have 20 triangular faces & I can construct any polygon in Three.js with triangles, only.
Does it then follow, that I need the coordinates for 5 pentagons & 12 hexagons in the form of:
5 * 12 + 6 * 20 = 180 triangles
If so, how should I proceed in generating those coordinates? Or even if I am wrong regarding the whole thing.
The JSModeler framework can generate a lot of solids, including truncated icosahedron, so maybe the source can help you.
You can find the code here if you find for GenerateTruncatedIcosahedron:
https://github.com/kovacsv/JSModeler/blob/master/src/extras/solidgenerator.js
The code creates polygons with five and six vertices, but it is easy to replace them with triangles.

Categories

Resources