Min value on main diagonal of the 2D Array - javascript

I managed to create a 2d array and populate it automatically with my code. I'd like to find the min value on the main diagonal, but I'm stuck and have no idea how to approach that idea from my code. Can anyone explain me how can I manage to achieve this pretty please? Everything that I've tried or come up with gave no results whatsoever..
var matrix = Array.from(Array(10), () => new Array(10));
for(i=0; i<10; i++){
for(j=0; j<10; j++)
matrix[i][j] = Math.floor(Math.random() * 100);
}
console.log(matrix);

Construct a 1-d array of the diagonal. Use Math.min with .apply to find the min value in that array.
var matrix = Array.from(Array(10), () => new Array(10));
for(i=0; i<10; i++){
for(j=0; j<10; j++)
matrix[i][j] = Math.floor(Math.random() * 100);
}
const diag = matrix.map((m, i) => m[i]);
const min = Math.min.apply(null, diag);
console.log(diag, "min = " + min);

The main diagonal of 2D Square Array (Matrix) is always at col_index == row_index, so you can iterate through the array to find the minimum value through it.
I made the array to 3x3 in my snippet to show the simpler case, but you may get it to 10x10 to try as well.
function getMinimumOfDiag(arr) {
var min = Infinity;
for (var i = 0; i < arr.length; i++)
if(arr[i].length > i)
if(arr[i][i] < min)
min = arr[i][i]
return min;
};
var matrix = Array.from(Array(3), () => new Array(3));
for(i=0; i<3; i++){
for(j=0; j<3; j++)
matrix[i][j] = Math.floor(Math.random() * 100);
}
console.log(matrix);
console.log(getMinimumOfDiag(matrix));

Assuming the matrix has rows and columns of same length, This should work,
var matrix = Array.from(Array(10), () => new Array(10));
const matrixLength = 10;
for(let i=0; i<matrixLength; i++){
for(j=0; j<matrixLength; j++)
matrix[i][j] = Math.floor(Math.random() * 100);
}
let minValueInDiagonal = Number.MAX_SAFE_INTEGER;
for(let i = 0; i < matrixLength; i++) {
minValueInDiagonal = Math.min(matrix[i][i], minValueInDiagonal);
}
console.log("Matrix is", matrix);
console.log("Min value in diagonal is: ", minValueInDiagonal);

Related

Adding numbers in a matrix

I have a two-dimensional array, and I want to sum all the values in that array, where the value is not -1.
Suppose I have a matrix that has the following values:
0,1 = 1.68
1,2 = 1.74
2,0 = 1.61
3,4 = -1
...
I want to add the all the numbers that are not -1
What I did try, and which obviously doesn't work for me, is:
for(i=0; i<data.length; ++i) {
for(j=0; j<data.length; ++j) {
if(data[i][j] != -1) {
sum += data[i][j]+data[j][i]
}
}
}
In my case, if an index (n, m) = k then it is also true that index (m, n) = k.
So for example, if (n, m) = 1.74, then (m, n) = 1.74. That is why I need to do data[i][j]+data[j][i] in the code above
What I REALLY want as result, is this: sum = (0,1 + 1,0) + (1,2 + 2,0) + (2,0 + 0,2) => sum = 2*(1,68) + 2*(1,74) + 2*(1,68)
What I get as result from my code above, is undefined.
I tried an alternative solution using .map (...), which according to the document, takes a function to map. But for now it is just a bit too complicated for me with the double array (I'm not experienced programmer yet)
data.map((a,i) => a.map((n,j) => n+data[i][j]));
I got an error here saying a not a function
You can use nested reduce
const data = [];
var dt = [1,2,3]
data[0] = dt;
data[1] = dt;
data[2] = dt;
var total = data.reduce((n,arr)=> n+arr.reduce((n,val)=>n+val), 0);
console.log(total);
I suppose that you want to sum all the values in a square matrix. So even though (m,n) = (n,m) in your matrix, one simple way to sum the values is :
let sum = 0;
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data.length; j++) {
if (data[i][j] !== -1) sum += data[i][j];
}
}
console.log(sum);
But if you want to do some calculation that take into account the fact that (m,n) = (n,m) in your matrix, you can try this:
let sum = 0;
for (let i = 0; i < data.length; i++) {
for (let j = 0; j < data.length; j++) {
if (data[i][j] !== -1) {
if (i === j) sum += data[i][j];
if (j < i) sum += 2*data[i][j];
}
}
}
console.log(sum);

javascript canvas: draw moving average line with curves

So basically, I want to draw a curved average line over a certain amount of points of a time-series line chart. Like this:
I want it to span the entire length of the chart but I can't figure out how to calculate the start and end points because the average would (I think) be a point in the middle of each section. Looking at a stock chart with moving average you can see what I want to acheive:
I calculate the averages first by splitting the data array up into chunks based on a period of time. So if I start with:
[
{ time: 1, value: 2 },
{ time: 2, value: 4 },
{ time: 3, value: 5 },
{ time: 4, value: 7 },
]
I get to:
var averages = [
{
x: 1.5,
y: 3,
},
{
x: 3.5 (the average time)
y: 6 (the average value)
},
]
This is what I've tried where I end up with an incomplete line, one that doesnt start at the beginning of the chart and doesnt stop at the end, but stars and ends inside the chart at the first average time:
ctx.moveTo((averages[0].x), averages[0].y);
for(var i = 0; i < averages.length-1; i ++)
{
var x_mid = (averages[i].x + averages[i+1].x) / 2;
var y_mid = (averages[i].y + averages[i+1].y) / 2;
var cp_x1 = (x_mid + averages[i].x) / 2;
var cp_x2 = (x_mid + averages[i+1].x) / 2;
ctx.quadraticCurveTo(cp_x1, averages[i].y ,x_mid, y_mid);
ctx.quadraticCurveTo(cp_x2, averages[i+1].y ,averages[i+1].x, averages[i+1].y);
}
ctx.stroke();
How would you do this?
To get a moving mean you need to just get the mean of n points either side of the current sample.
For example
// array of data points
const movingMean = []; // the resulting means
const data = [12,345,123,53,134,...,219]; // data with index representing x axis
const sampleSize = 5;
for(var i = sampleSize; i < data.length - sampleSize; i++){
var total = 0;
for(var j = i- sampleSize; j < i + sampleSize; j++){
total += data[j];
}
movingMean[i] = total / (sampleSize * 2);
}
This method does not pull the mean forward giving the most accurate mean for each data point.
The problem with this method is that you do not get a mean for the first n and last n samples, where n is the number of samples either side of the mean.
You can do an alternative that will pull the mean forward a little but by applying a weighted mean you can reduce the bias a little
for(var i = sampleSize; i < data.length + Math.floor(sampleSize / 4); i++){
var total = 0;
var count = 0;
for(var j = sampleSize; j > 0; j --){
var index = i - (sampleSize - j);
if(index < data.length){
total += data[index] * j; // linear weighting
count += j;
}
}
movingMean[i-Math.floor(sampleSize / 4)] = total / count;
}
This method keeps that mean closer to the current sample end.
The example show a random data set and the two types of means plotted over it. Click to get a new plot. The red line is the moving mean and the blue is the weighted mean. Note how the blue line tends to follow the data a little slow.
The green line is a weighted mean that has a sample range 4 times greater than the other two.
// helper functions
const doFor = (count, callback) => {var i = 0; while (i < count) { callback(i ++) } };
const setOf = (count, callback) => {var a = [],i = 0; while (i < count) { a.push(callback(i ++)) } return a };
const rand = (min, max = min + (min = 0)) => Math.random() * (max - min) + min;
const randG = (dis, min, max) => {var r = 0; doFor(dis,()=>r+=rand(min,max)); return r / dis};
function getMinMax(data){
var min = data[0];
var max = data[0];
doFor(data.length - 1, i => {
min = Math.min(min,data[i+1]);
max = Math.max(max,data[i+1]);
});
var range = max-min;
return {min,max,range};
}
function plotData(data,minMax){
ctx.beginPath();
for(var i = 0; i < data.length; i++){
if(data[i] !== undefined){
var y = (data[i] - minMax.min) / minMax.range;
y = y *(ctx.canvas.height - 2) + 1;
ctx.lineTo(i/2,y);
}
}
ctx.stroke();
}
function getMovingMean(data,sampleSize){
const movingMean = []; // the resulting means
for(var i = sampleSize; i < data.length - sampleSize; i++){
var total = 0;
for(var j = i- sampleSize; j < i + sampleSize; j++){
total += data[j];
}
movingMean[i] = total / (sampleSize * 2);
}
return movingMean[i];
}
function getMovingMean(data,sampleSize){
const movingMean = []; // the resulting means
for(var i = sampleSize; i < data.length - sampleSize; i++){
var total = 0;
for(var j = i- sampleSize; j < i + sampleSize; j++){
total += data[j];
}
movingMean[i] = total / (sampleSize * 2);
}
return movingMean;
}
function getWeightedMean(data,sampleSize){
const weightedMean = [];
for(var i = sampleSize; i < data.length+Math.floor(sampleSize/4); i++){
var total = 0;
var count = 0;
for(var j = sampleSize; j > 0; j --){
var index = i - (sampleSize - j);
if(index < data.length){
total += data[index] * j; // linear weighting
count += j;
}
}
weightedMean[i-Math.floor(sampleSize/4)] = total / count;
}
return weightedMean;
}
const dataSize = 1000;
const sampleSize = 50;
canvas.width = dataSize/2;
canvas.height = 200;
const ctx = canvas.getContext("2d");
function displayData(){
ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height);
var dataPoint = 100;
var distribution = Math.floor(rand(1,8));
var movement = rand(2,20);
const data = setOf(dataSize,i => dataPoint += randG(distribution, -movement, movement));
const movingMean = getMovingMean(data, sampleSize);
const weightedMean = getWeightedMean(data, sampleSize*2);
const weightedMean1 = getWeightedMean(data, sampleSize*8);
var minMax = getMinMax(data);
ctx.strokeStyle = "#ccc";
plotData(data,minMax);
ctx.strokeStyle = "#F50";
plotData(movingMean,minMax);
ctx.strokeStyle = "#08F";
plotData(weightedMean,minMax);
ctx.strokeStyle = "#4C0";
plotData(weightedMean1,minMax);
}
displayData();
document.onclick = displayData;
body { font-family : arial; }
.red { color : #F50; }
.blue { color : #0AF; }
.green { color : #4C0; }
canvas { position : absolute; top : 0px; left :130px; }
<canvas id="canvas"></canvas>
<div class="red">Moving mean</div>
<div class="blue">Weighted mean</div>
<div class="green">Wide weighted mean</div>
<div>Click for another sample</div>

Strange performance quirk in javascript

I experience a strange differences in performance of simple task depending of array I am working with. The task is to calculate sum of those elements in array which are greater than 5. Task is performed on arrays with equal lenghts.
I try the very same approach on three different array objects:
1) var hugeArray1 - array with all elemenets randomly picked from 0:10 range
2) var hugeArray2 - copy of hugeArray1 sorted with Array.prototype.sort()
3) var hugeArray3 - handcrafted but sorted array with values from 0:10 range, spread to equaly cover this interval.
I try to calculate sum of elements greater than 5 many times for each Array and then average them. What is strange, time needed varies a lot for those three arrays.
1) hugeArray1: 5.805ms
2) hugeArray2: 15.738ms
3) hugeArray3: 3.753ms
Result for array sorted with sort() is extreamly poor. Why is that? it looks like sort() returns some kind of wraper/proxy instead of 'native' Array, which affects performance. I tried it on 2 computers. Also i tried to change order of testing.
I include code below, please tell me what is happening here.
// random array with elements 0-10 of size n
function randomArray(n) {
var arr = [];
for (var i = 0; i < n; ++i) {
arr.push(Math.random() * 10);
}
return arr;
};
// measures time of execution
function measureTime(f) {
var start = new Date().getTime();
f();
var stop = new Date().getTime();
return stop - start;
};
// enumerate ofer array and calculate sum of elementsgreater than 5
function sumGreaterThan5(arr) {
var sum = 0;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] > 5.0)
sum += arr[i];
}
return sum;
}
// generate array os size 'size' with elements with constant step to fill interval 0:10
function generateSortedArr(size) {
var arr = [];
for (var i = 0; i < size; ++i) {
arr.push(i * 10 / size);
}
return arr;
}
var huge = 1000000;
var hugeArray1 = randomArray(huge);
var hugeArray2 = hugeArray1.slice(0).sort();
var hugeArray3 = generateSortedArr(huge);
var hugeArrays = [hugeArray1, hugeArray2, hugeArray3];
hugeArrays.forEach(x=> {
var res = [];
for (var i = 0; i < 1000; ++i) {
res.push(measureTime(function () {
sumGreaterThan5(x);
}));
}
console.log(res.reduce((prev, curr)=> prev + curr) / res.length);
});
// random array with elements 0-10 of size n
function randomArray(n) {
var arr = [];
for (var i = 0; i < n; ++i) {
arr.push(Math.random() * 10);
}
return arr;
};
// measures time of execution
function measureTime(f) {
var start = new Date().getTime();
f();
var stop = new Date().getTime();
return stop - start;
};
// enumerate ofer array and calculate sum of elementsgreater than 5
function sumGreaterThan5(arr) {
var sum = 0;
for (var i = 0; i < arr.length; ++i) {
if (arr[i] > 5.0)
sum += arr[i];
}
return sum;
}
// generate array os size 'size' with elements with constant step to fill interval 0:10
function generateSortedArr(size) {
var arr = [];
for (var i = 0; i < size; ++i) {
arr.push(i * 10 / size);
}
return arr;
}
var huge = 1000000;
var hugeArray1 = randomArray(huge);
var hugeArray2 = hugeArray1.slice(0).sort();
var hugeArray3 = generateSortedArr(huge);
var hugeArrays = [hugeArray1, hugeArray2, hugeArray3];
hugeArrays.forEach(function(x){
var res = [];
for (var i = 0; i < 1000; ++i) {
res.push(measureTime(function () {
sumGreaterThan5(x);
}));
}
console.log(res.reduce(function(prev, curr){return prev + curr},0) / res.length);
});

Speeding up simple math operations on numeric 2D array (matrix) in JavaScript

I have a numeric 2D array (an array of arrays, or a matrix) and I need to do simple matrix operations like adding a value to each row, or multiplying every value by a single number. I have little experience with math operations in JavaScript, so this may be a bone-headed code snippet. It is also very slow, and I need to use it when the number of columns is 10,000 - 30,000. By very slow I mean roughly 500 ms to process a row of 2,000 values. Bummer.
var ran2Darray = function(row, col){
var res = [];
for (var i = 0 ; i < row; i++) {
res[i] = [];
for (var j = 0; j < col; j++) {
res[i][j] = Math.random();
}
}
return res;
}
var myArray = ran2Darray(5, 100);
var offset = 2;
for (i = 0; i < myArray.length; i++) {
aRow = myArray[i];
st = Date.now();
aRow.map(function addNumber(offset) {myArray[i] + offset*i; })
end = Date.now();
document.write(end - st);
document.write("</br>");
myArray[i] = aRow;
}
I want to avoid any added libraries or frameworks, unless of course, that is my only option. Can this code be made faster, or is there another direction I can go, like passing the calculation to another language? I'm just not familiar with how people deal with this sort of problem. forEach performs roughly the same, by the way.
You don't have to rewrite array items several times. .map() returns a new array, so just assign it to the current index:
var myArray = ran2Darray(5, 100000);
var offset = 2;
var performOperation = function(value, idx) {
return value += offset * idx;
}
for (i = 0; i < myArray.length; i++) {
console.time(i);
myArray[i] = myArray[i].map(performOperation)
console.timeEnd(i);
}
It takes like ~20ms to process.
Fiddle demo (open console)
Ok, Just a little modification and a bug fix in what you have presented here.
function addNumber(offset) {myArray[i] + offset*i; }) is not good.
myArray[i] is the first dimention of a 2D array why to add something to it?
function ran2Darray (row, col) {
var res = [];
for (var i = 0 ; i < row; i++) {
res[i] = [];
for (var j = 0; j < col; j++) {
res[i][j] = Math.random();
}
}
return res;
}
var oneMillion = 1000000;
var myArray = ran2Darray(10, oneMillion);
var offset = 2;
var startTime, endTime;
for (i = 0; i < myArray.length; i++) {
startTime = Date.now();
myArray[i] = myArray[i].map(function (offset) {
return (offset + i) * offset;
});
endTime = Date.now();
document.write(endTime - startTime);
document.write("</br>");
}
try it. It's really fast
https://jsfiddle.net/itaymer/8ttvzyx7/

getting different random numbers in a loop not random

I am filling an array with random numbers with a loop, but the random number is exactly the same for each item in the array, I think this is because of the seed value that Math.rand() uses. How can i get a different number each time?
for(var i = 0; i < 10; i++){
number[i] = getRandom(0, 100);
}
function getRandom(a, b){
var num = Math.floor((Math.random()*b)+a);
return num;
}
Works fine for me:
http://jsfiddle.net/kzUUt/
You need to declare number though...
var number = new Array(10);
for(var i = 0; i < 10; i++)
{
number[i] = getRandom(0, 100);
console.log(number[i]);
}
function getRandom(a, b)
{
var num = Math.floor((Math.random()*b)+a);
return num;
}
Here is working demo.
var number = new Array();
for (var i = 0; i < 10; i++) {
number[i] = getRandom(0, 100);
}
function getRandom(a, b) {
return Math.floor((Math.random() * b) + a);
}
for (var j = 0; j < 10; j++) {
alert(number[j]);
}

Categories