NaN out of matrix multiplication? - javascript

I have the code below for matrix formation out of an array and its multiplication.
But when I try to multiply two matrices like mtp(matrix(2,2,[1,2,3,4]),matrix(2,2,[1,0,0,1])) it returns NaN in all places.
Please help me out
function matrix(m, n, arr) {
var result = {};
for (t = 1; t <= m; t++) {
result[t] = {};
};
for (i = 1; i <= m; i++)
for (j = 1; j <= n; j++) result[i][j] = arr[m * (i - 1) + j - 1];
return {
"result": result,
"m": m,
"n": n
};
}
function mtp(a, b) {
if (parseInt(a.n) != parseInt(b.m)) {
return;
} else {
var result = [];
var m = parseInt(a.m);
var n = parseInt(b.n);
var k = parseInt(a.n);
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
for (p = 1; p <= k; p++) {
result[m * (i - 1) + j - 1] += (parseInt(a.result[i][p]) * parseInt(b.result[p][j]));
console.log(parseInt(a.result[i][p]) * parseInt(b.result[p][j]))
}
}
}
}
console.log(result, matrix(m, n, result).result);
}
mtp(matrix(2,2,[1,2,3,4]),matrix(2,2,[1,0,0,1]));

When you define result it is an array of zero elements
var result = [];
When you try to add a number to an element of the array, that element is not defined, Adding any number to undefined gives you NaN. There are 2 ways to solve this, either initialize your array with the right length of zeros, or default it to zero during the sum. I've chosen the latter below,
result[m * (i - 1) + j - 1] = (result[m * (i - 1) + j - 1]||0) + (a.result[i][p] * b.result[p][j]);
// Note here ---------------------------------------------^
I've got rid of all the unnecessary parseInt calls.
function matrix(m, n, arr) {
var result = {};
for (t = 1; t <= m; t++) {
result[t] = {};
};
for (i = 1; i <= m; i++)
for (j = 1; j <= n; j++) result[i][j] = arr[m * (i - 1) + j - 1];
return {
"result": result,
"m": m,
"n": n
};
}
function mtp(a, b) {
if (a.n != b.m) {
return;
} else {
var result = [];
var m = a.m;
var n = b.n;
var k = a.n;
for (i = 1; i <= m; i++) {
for (j = 1; j <= n; j++) {
for (p = 1; p <= k; p++) {
result[m * (i - 1) + j - 1] = (result[m * (i - 1) + j - 1]||0) + (a.result[i][p] * b.result[p][j]);
console.log(a.result[i][p] * b.result[p][j])
}
}
}
}
console.log(result, matrix(m, n, result).result);
}
mtp(matrix(2,2,[1,2,3,4]),matrix(2,2,[1,0,0,1]));

In your mtp() function the values of the elements inside your result array are uninitialized (that is, you've defined an array, but that array has no actual values or even a determined length), so in your inner loop when you +=, you're referencing a newly created array element which has no default value (and therefore is undefined), and adding some number to that undefined value.
An undefined value plus a number is not a number (NaN). Try preinitializing your result array.

Related

output not displaying inside the array

const pyramidOfAsterisks = function(val) {
var arr=[];
for (let m = 1; m <= val; m++) {
if (m === 7)
break;
for (let s = 1; s <= val - m; s++) {
document.write(" &nbsp");
}
for (let n = 1; n <= m; n++) {
document.write("* ");
}
for (let p = 2; p <= m; p++) {
document.write("* ");
}
document.write("<br />");
arr.push()
}
}
var pyramid = pyramidOfAsterisks(12);
document.write(pyramid);
I have tried to display the output inside the given empty array., so i pushed the function into the array , but not displaying inside the array.
You never push anything to the array arr
You never return anything in pyramidOfAsterisks which is why it prints undefined
Replace document.write with arr.push and return arr before the end of pyramidOfAsterisks.
const pyramidOfAsterisks = function(val) {
var arr=[];
for (let m = 1; m <= val; m++) {
if (m === 7)
break;
for (let s = 1; s <= val - m; s++) {
arr.push(" &nbsp");
}
for (let n = 1; n <= m; n++) {
arr.push("* ");
}
for (let p = 2; p <= m; p++) {
arr.push("* ");
}
arr.push("<br />");
//arr.push()
};
return arr
}
//REM: Be aware of array.join
var pyramid = pyramidOfAsterisks(12);
document.write(pyramid.join(''));
In the arr.push() function input the value you want to add to the array.
For example
arr.push("one")
arr.push("two")
// It will return ["one","two"]
const pyramidOfAsterisks = function(val) {
// var arr=[];
for (let m = 1; m <= val; m++) {
if (m === 7)
break;
for (let s = 1; s <= val - m; s++) {
document.write(" &nbsp");
}
for (let n = 1; n <= m; n++) {
document.write("* ");
}
for (let p = 2; p <= m; p++) {
document.write("* ");
}
document.write("<br />");
// arr.push()
}
}
var pyramid = pyramidOfAsterisks(12);
// document.write(pyramid);
This code works fine. It outputs undefined because of the document.write in the end. pyramidOfAsterisks does not return any value yet you assign the value it returns to a variable named pyramid, this is why pyramid is equal to undefined

Find largest d in array such that a + b + c = d

Task
You are given a sorted integer array arr. It contains several unique integers(negative, positive, or zero).
Your task is to find the largest d such that a + b + c = d, where a, b, c, and d are distinct elements of arr. If no such an element d found, return null.
Example:
For arr = [2,3,5,7,12], the output should be 12 (this array passes my function correctly)
For arr = [-100,-1,0,7,101], the output should be 0 (this one does not pass)
I could manage the positive numbers check but my function miserably fails with negatives
function findD(arr) {
myArr = arr.sort((a, b) => b - a);
for (var i = 0; i < myArr.length; i++) {
for (var k = i + 1; k < myArr.length - 2; k++) {
var j = k + 1,
d = myArr.length - 1;
while (j < d) {
let sum = myArr[k] + myArr[j] + myArr[d];
if (sum == myArr[i]) {
return myArr[i];
} else if (sum < myArr[i]) {
d--;
} else if (sum > myArr[i]) {
j++;
}
}
}
}
return null
}
how to handle negative values in the array?
Let's imagine there's an array like [-2, -1, 0, 3].
Then, after sorting it in the descending order as per your algorithm it will be [3, 0, -1, -2]. Obviously, your algorithm will pick only 3 as you assume d must be larger than numbers at the remaining 3 positions. That's wrong, of course. You shouldn't assume that a, b and c are necessarily less than d. That's why you must check other cases when d occupies all possible positions in relation to a,b,c. So, first consider a brute force approach that will have O(n^4) time and O(1) space complexity:
...
for (var i = myArr.length; i >= 0 ; i--) {
for (var k = 0; k < myArr.length; k++) {
if (k == i) {
continue
}
for (var j = k + 1; j < myArr.length; j++) {
if (j == i) {
continue
}
for (var d = j + 1; d < myArr.length; d++) {
if (d == i) {
continue
}
if (myArr[i] == myArr[k] + myArr[j] + myArr[d]) {
return myArr[i]
}
}
}
}
}
return null
...
But this problem can be solved in O(n^2) time and O(n^2) space.
First we should realise that a + b = d - c.
So, for the given array arr and every pair of indices i,j: i<j we store arr[i] + arr[j] (a + b) as a key and pair i,j as an item of a value (the value is a list of pairs of indices) in sumsMap. The value must be a list because there can be several pairs of indices corresponding to the same sum a + b.
Then, go through each pair of indices again k,l and check if a key arr[l] - arr[k] (d - c) or arr[k] - arr[l] (c - d) exists in sumsMap. If it does and indices l,k are different from the ones in sumsMap[s] then update the maximum element if it's lower than arr[l].
function solve(arr) {
var sumsMap = {}
for (var i = 0; i < arr.length; i++) {
for (var j = i + 1; j < arr.length; j++) {
var sum = arr[i] + arr[j]
// several pairs of indices can correspond to the same summ so keep all of them
var mappedIndices = sumsMap[sum]
if (typeof mappedIndices == "undefined") {
mappedIndices = []
}
let pair = {}
pair.first = i
pair.second = j
mappedIndices.push(pair)
sumsMap[sum] = mappedIndices
}
}
var maxD = Number.MIN_SAFE_INTEGER
for (var k = 0; k < arr.length; k++) {
for (var l = 0; l < arr.length; l++) {
mappedIndices = sumsMap[arr[l] - arr[k]]
if (mappedIndices != undefined) {
// in the worst case, 4 pairs of indices may contain k or l but the fifth one won't as numbers in the array are unique and hence the same index can occur only twice
var steps = Math.min(5, mappedIndices.length)
for (var s = 0; s < steps; s++) {
var pair = mappedIndices[s]
if (pair.first != k && pair.first != l && pair.second != k && pair.second != l) {
maxD = Math.max(maxD, arr[l])
}
}
}
}
}
if (maxD == Number.MIN_VALUE) {
return -1
} else {
return maxD
}
}
document.write(solve([-100,-1,0,7,101] ))
document.write("<br>")
document.write(solve([-93,-30,-31,-32] ))
I translated the function Renaldo suggested from https://www.geeksforgeeks.org/find-largest-d-in-array-such-that-a-b-c-d/ to JavaScript for you.
function findLargestd(S, n){
var found = false;
// sort the array in
// ascending order
S.sort((a, b) => a - b);
// iterating from backwards to
// find the required largest d
for(var i = n - 1; i >= 0; i--){
for(var j = 0; j < n; j++){
// since all four a, b, c,
// d should be distinct
if(i == j){
continue;
}
for(var k = j + 1; k < n; k++){
if(i == k){
continue;
}
for(var l = k + 1; l < n; l++){
if(i == l){
continue;
}
// if the current combination
// of j, k, l in the set is
// equal to S[i] return this
// value as this would be the
// largest d since we are
// iterating in descending order
if(S[i] == S[j] + S[k] + S[l]){
found = true;
return S[i];
}
}
}
}
}
//if not found, return 0
if(found === false){
return 0;
}
}

loop three digit numbers where product == sum

So I have this task where I have to nest three loops together then find out all the three digit numbers where product == sum.
For example:
123
1*2*3 = 6
1+2+3 = 6
This is what I have tried so far:
var summen = a + b + c;
var produktet = a * b * c;
for (var i = 100; i <= 100; i++) {
for (var j = 100; j <= 101; j++) {
for (var e = 100; e < 1000; e++) {
if (summen == produktet) {
pOutput.innerHTML += e + " ";
}
}
}
Thank you in advance and any help is really appreciated!
(i thought that i need to use if and else but i'm basically stuck to be honest)
If you want to do it with three loops, use three that start at 0 and end at 9, and then add and multiply in the inner loop:
let output = [];
for (let a = 0; a < 10; a++) {
for (let b = 0; b < 10; b++) {
for (let c = 0; c < 10; c++) {
if (a * b * c === a + b + c) output.push("" + a + b + c)
}
}
}
console.log(output)
You could iterate from zero to 999 and take the stringed value as array. Then check the sum against the product and store the value if equal.
const
sum = array => array.reduce((a, b) => a + b),
product = array => array.reduce((a, b) => a * b);
var i,
temp,
values = [];
for (i = 0; i < 1000; i++) {
temp = Array.from(i.toString().padStart(3, '0'), Number);
if (sum(temp) === product(temp)) {
values.push(temp.join(''));
}
}
console.log(values);

least common multiple: What is wrong with my code?

function lcm(arr) {
arr = arr.sort(function(a, b) {
return a - b;
});
var j = 1;
var num = arr[0];
for (i = 1; i < arr.length; i++) {
while (num % arr[i] !== 0) {
j = j + 1;
num = j * arr[0];
}
arr[0] = num;
}
return num;
}
console.log(lcm([3, 5, 6, 10]));
I am trying to find the least common multiple for a range of numbers in an array. The code works fine for array with two items, however the output for arrays with more than two items seems to exceed the value expected.
Can anyone help me find the bug in my code ?
Thank you
Set j back to 1 each time through the loop through the array elements. Otherwise, when you process the next number, you start with a high multiplier.
// function that find the least common multiple
function lcm(arr) {
arr = arr.sort(function(a, b) {
return a - b;
});
var num = arr[0];
for (i = 1; i < arr.length; i++) {
var j = 1;
while (num % arr[i] !== 0) {
j = j + 1;
num = j * arr[0];
}
arr[0] = num;
}
return num;
}
console.log(lcm([3, 5, 6, 10]));

Universal function for getting all unique pairs, trebles etc from an array in javascript

I am looking to create a function in javascript, which would allow me to pass a long array, together with one argument.
what I'm looking for is something like this:
var ar = [1,2,3,4];
var pairs = superAwesomeFunction(ar,2) //=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]];
var trebles = superAwesomeFunction(ar,3) //=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]
ideally, the function would have no limit on the folding argument.
I wrote a piece of code that looks like this, which is working fine, but it's not really useful as it isn't universal, and I would need a lot of such functions, which seems silly.
getAll2Folds: function (ar) {
var combinations = [],
numOdds = ar.length;
for (var i = 0; i < numOdds; i++) {
for (var j = i + 1; j < numOdds; j++) {
combinations.push([ar[i], ar[j]]);
}
}
return combinations;
},
getAll3Folds: function (ar) {
var combinations = [],
numOdds = ar.length;
for (var i = 0; i < numOdds; i++) {
for (var j = i + 1; j < numOdds; j++) {
for (var k = j + 1; k < numOdds; k++) {
combinations.push([ar[i], ar[j], ar[k]]);
}
}
}
return combinations;
};
},
... (not so great :|)
getAll8Folds: function (ar) {
var combinations = [],
numOdds = ar.length;
for (var i = 0; i < numOdds; i++) {
for (var j = i + 1; j < numOdds; j++) {
for (var k = j + 1; k < numOdds; k++) {
for (var l = k + 1; l < numOdds; l++) {
for (var m = l + 1; m < numOdds; m++) {
for (var n = m + 1; n < numOdds; n++) {
for (var o = n + 1; o < numOdds; o++) {
for (var p = o + 1; p < numOdds; p++) {
combinations.push([ar[i], ar[j], ar[k], ar[l], ar[m], ar[n], ar[o], ar[p]]);
}
}
}
}
}
}
}
}
return combinations;
}
I'm free to use underscore, jquery or whatever tool i want, but can't find an elegant solution, which would also be performant. ideas?
Thanks
Basically combine() takes an array with the values to combine and a size of the wanted combination results sets.
The inner function c() takes an array of previously made combinations and a start value as index of the original array for combination. The return is an array with all made combinations.
The first call is allways c([], 0), because of an empty result array and a start index of 0.
var arr = [1, 2, 3, 4, 5, 6, 7];
function combine(a, size) {
function c(part, start) {
var result = [], i, l, p;
for (i = start, l = arr.length; i < l; i++) {
// get a copy of part
p = part.slice(0);
// add the iterated element to p
p.push(a[i]);
// test if recursion can go on
if (p.length < size) {
// true: call c again and concat it to the result
result = result.concat(c(p, i + 1));
} else {
// false: push p to the result, stop recursion
result.push(p);
}
}
return result;
}
return c([], 0);
}
out(JSON.stringify(combine(arr, 2), null, 4), true);
out(JSON.stringify(combine(arr, 3), null, 4), true);
out(JSON.stringify(combine(arr, 4), null, 4), true);
out(JSON.stringify(combine(arr, 5), null, 4), true);
out(JSON.stringify(combine(arr, 6), null, 4), true);
// just for displaying the result
function out(s, pre) {
var descriptionNode = document.createElement('div');
descriptionNode.className = 'description';
if (pre) {
var preNode = document.createElement('pre');
preNode.innerHTML = s + '<br>';
descriptionNode.appendChild(preNode);
} else {
descriptionNode.innerHTML = s + '<br>';
}
document.getElementById('out').appendChild(descriptionNode);
}
<div id="out"></div>

Categories

Resources