I'm having trouble with matrix multiplication code in JavaScript. If I run the function below with the following two matrices:
var m1 = [ [ 1, 0, 0 ],
[ 0, 1, 0 ],
[ 1, 1, 0 ],
[ 0, 0, 1 ],
[ 1, 0, 1 ],
[ 0, 1, 1 ],
[ 1, 1, 1 ] ];
var m2 = [ [ '0', '1', '1', '0', '0', '1', '1' ] ];
var matrixMult = function (m1, m2) {
console.log(m1);
console.log(m2);
console.log("m1 length: %d, m2[0].length: %d", m1.length, m2[0].length);
if (m1.length != m2[0].length) {
console.error("Incompatible matrix dimensions for multiplication.");
return false;
}
var result = [];
for (var i = 0; i < m1[0].length; i++) {
result[i] = [];
for (var j = 0; j < m2.length; j++) {
var sum = 0;
for (var k = 0; k < m1.length; k++) {
sum += m1[i][k] * m2[k][j];
}
result[i][j] = sum;
}
}
return result;
}
I get this error:
/path/to/file.js:58
sum += m1[i][k] * m2[k][j];
^
TypeError: Cannot read property '0' of undefined
at matrixMult (...)
What's going wrong? Could the issue be that m2.length is only 1?
There is only a m2[0], but your inner for loop runs from 0 to m1.length, which is bigger than 0. So when it tries accessing m2[1] it throws the error.
Also by following definition of matrix multiplication
Multiplication of two matrices is defined only if the number of columns of the left matrix is the same as the number of rows of the right matrix.
(Source: Wikipedia)
you cannot multiply your sample matrixes, because m1 has 3 columns, but m2 has only one row.
EDIT
Now that I understood your question correctly, I wrote a little function that might help you out:
function multiplyMatrix(m1, m2) {
var result = [];
for(var j = 0; j < m2.length; j++) {
result[j] = [];
for(var k = 0; k < m1[0].length; k++) {
var sum = 0;
for(var i = 0; i < m1.length; i++) {
sum += m1[i][k] * m2[j][i];
}
result[j].push(sum);
}
}
return result;
}
multiplyMatrix(m1, m2);
// => [ [2, 4, 2] ]
Related
I need to write a program that creates a 2d array in variable "numbers" in rows (5) and columns (4). The elements of the array have to be consecutive integers starting at 1 and end at 20. I have to use "for" loop.
[ 1, 2, 3, 4 ],
[ 5, 6, 7, 8 ],
[ 9, 10, 11, 12 ],
[ 13, 14, 15, 16 ],
[ 17, 18, 19, 20 ],
So I came up with that:
const numbers = [];
const columns = 4;
const rows = 5;
for (let i = 0; i < rows; i++) {
numbers [i] = [];
for (let j = 0; j < columns; j++){
numbers [i][j] = j + 1;
}
}
console.log(numbers);
But the result of this is five identical rows, like this:
[ 1, 2, 3, 4 ],
[ 1, 2, 3, 4 ],
[ 1, 2, 3, 4 ],
[ 1, 2, 3, 4 ],
[ 1, 2, 3, 4 ]
Do you have any idea how to fix it? How to make second row starting from 5?
Here is some updated code. You need to add i*columns to every value
const numbers = [];
const columns = 4;
const rows = 5;
for (let i = 0; i < rows; i++) {
numbers[i] = [];
for (let j = 0; j < columns; j++){
numbers[i][j] = j + 1 + (i*columns);
}
}
console.log(numbers);
Looks like in the second loop, you should do numbers [i][j] = j * i; instead
Every time the outer for loop starts a new iteration, j is reset back to 0, which is why you keep getting rows starting with 1.
To fix this, you could declare a variable outside of the for loops that tracks the current number, and use that instead of j like so:
const numbers = [];
const columns = 4;
const rows = 5;
let currNum = 0;
for (let i = 0; i < rows; i++) {
numbers [i] = [];
for (let j = 0; j < columns; j++){
currNum++;
numbers [i][j] = currNum;
}
}
console.log(numbers);
I have a task where I need to swap the index values within an array.
This is the code that I have written. I am kinda new to js, so it may be a bit off.
function swap(arr){
for(let i = 0; i = arr.length; i++){
if (arr[i] == 0){
return arr[i] + 1
}
if (arr[i]== 1){
return arr[i] - 1
}
}else{
return "only accepts 0 and 1"
}
}
console.log(swap[[1,0,0],[0,1,0],[1,1,0]])
the console.log should return [[0,1,1],[1,0,1],[0,0,1]]
Usin array.map() you can solve this problem.
This can be the possible solution:
const x = [[1,0,0],[0,1,0],[1,1,0]];
const result = x.map(el => el.map(item => item === 1 ? 0: 1))
console.log(result);
Using ES6 you could make something like this:
const swapArray = [0,1,1].map(index => !index);
Result: swapArray = [true, false, false]
This is brute force, you could do it probably with a map.
function swap(arr){
let returnArr = []
for(let i = 0; i < arr.length; i++){
let returnArr1 = []
for (let j = 0; j < arr.length; j++){
console.log(arr[i][j])
if(arr[i][j] === 0) returnArr1.push(1)
else if(arr[i][j] === 1) returnArr1.push(0)
}
returnArr.push(returnArr1)
}
return returnArr
}
swap([[1,0,0],[0,1,0],[1,1,0]])
[ [ 0, 1, 1 ], [ 1, 0, 1 ], [ 0, 0, 1 ] ]
You are probably wanting to do something like this -
function swap(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr[i].length; j++) {
// Here we are just comparing arr[i][j]
// - if it is 1, make it 0
// - if it is 0, make it 1
arr[i][j] = (arr[i][j] ? 0 : 1);
}
}
// return the modified array
return arr;
}
let arr = [
[1, 0, 0],
[0, 1, 0],
[1, 1, 0]
]
console.log(swap(arr))
You could also use a short-hand syntax as follows -
let arr = [
[1, 0, 0],
[0, 1, 0],
[1, 1, 0]
];
// swapping 0s to 1 and 1s to 0
// The map will take each inner array and each element of that array and modify according to given condition
const swapped_arr = arr.map(inner_array => inner_array.map(el => el ? 0 : 1));
console.log(swapped_arr);
I have added comments at places to make you understand.
Hope this helps !
I have tested this code below, it works.
function swap(arr){
arr.forEach((item,index)=>{arr[index]=+!item});
return arr;
}
console.log(swap([1,0,0]));
console.log(swap([1,1,1]));
console.log(swap([1,0,1]));
Try this:
function swap(arr){
return arr.map(x => x.map(j => Number(!j)));
}
console.log(swap([[1,0,0],[0,1,0],[1,1,0]]));
i'm just beginning to learn javascript and this is my first question on stackoverflow, so feel free to criticize me if i'm approaching this the wrong way.
var divisibleByThreePairSum = function(array) {
var pairs = [];
for (var i = 0; i < array.length; i++) {
for (var j = i++; j < array.length; j++) {
var sum = array[i] + array[j];
if (sum % 3 === 0) {
pairs.push([i, j]);
}
}
}
return pairs;
}
console.log(divisibleByThreePairSum([3,1,0,2,1,3,2,0]));
This gives me the answer;
[ [ 1, 3 ], [ 1, 6 ], [ 3, 4 ], [ 5, 5 ], [ 5, 7 ], [ 7, 7 ] ]
[Finished in 0.2s]
For the second "for" loop, I formatted it like so, (j = i++) as to avoid repeats like [1, 3], [3, 1], but I can't seem to get rid of getting pairs like [5, 5], and [7, 7]. Is there any possible ways to format the code differently so that this doesn't happen? Again, I apologize if this was asked improperly; i'll definitely be using this site more often so please let me know if i'm doing anything wrong "question format" wise, Thanks!
Issue is j = i++. This will assign value of i to j and then increment value of i. This will also result in skipping of alternate values of i as it is incremented twice.
for(var i = 0; i< 5; i++){
for(var j = i++; j< 5; j++){
console.log(i,j)
}
}
You should rather use j=i+1. This will sent next value and will not increment value of i
var divisibleByThreePairSum = function(array) {
var pairs = [];
for (var i = 0; i < array.length; i++) {
for (var j = i+1; j < array.length; j++) {
var sum = array[i] + array[j];
if (sum % 3 === 0) {
pairs.push([i, j]);
}
}
}
return pairs;
}
console.log(divisibleByThreePairSum([3, 1, 0, 2, 1, 3, 2, 0]));
var combinations = function(numArr, choose, callback) {
var n = numArr.length;
var c = [];
var inner = function(start, choose_) {
if (choose_ == 0) {
callback(c);
} else {
for (var i = start; i <= n - choose_; ++i) {
c.push(numArr[i]);
inner(i + 1, choose_ - 1);
c.pop();
}
}
}
inner(0, choose);
}
I'm not entirely sure how I would append all the items inside an array after it's done creating all the combinations.
I attempted some modifications to the code though I ultimately ended up messed it up.
Example :
So, are you trying to do something like this: http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/
I found a double-loop implementation accomplishes the task pretty well:
function findCombinations(nums, cb) {
var allCombinations = [];
var maxIndex = nums.length - 1;
var i = 0, j = 0;
for (i; i <= maxIndex; i += 1) {
for (j = i; j <= maxIndex; j += 1) {
if (i !== j) {
allCombinations.push([ nums[i], nums[j] ]);
}
}
}
cb(allCombinations);
}
findCombinations([1, 2, 3, 4], function (combinations) {
console.log(combinations);
});
Prints the output:
[ [ 1, 2 ], [ 1, 3 ], [ 1, 4 ], [ 2, 3 ], [ 2, 4 ], [ 3, 4 ] ]
Were you specifically trying to implement a recursion tree?
If this is the right output, I got it to work with a minor fix to your solution.
Your approach is totally correct. You just need to think about when you're beginning/ending
a combination. When a combination ends you need to push the current combination to an external array.
Your base case signifies when a combination is complete, at this point you need to push a COPY of the current combination.
> combinations([0,1,2,3],2)
[ [ 0, 1 ],
[ 0, 2 ],
[ 0, 3 ],
[ 1, 2 ],
[ 1, 3 ],
[ 2, 3 ] ]
> combinations([0,1,2,3],3)
[ [ 0, 1, 2 ],
[ 0, 1, 3 ],
[ 0, 2, 3 ],
[ 1, 2, 3 ] ]
Here is the tweaked solution. You could use the callback on c if you'd like.
function combinations(numArr, choose, callback) {
var n = numArr.length;
var c = [];
var temp = [];
var inner = function(start, choose_) {
if (choose_ === 0) {
c.push(temp.slice());
} else {
for (var i = start; i <= n - choose_; i++) {
temp.push(numArr[i]);
inner(i + 1, choose_ - 1);
temp.pop();
}
}
}
inner(0, choose);
return c;
}
I am creating a game and I need to generate some game pieces. Each piece is an array consisting of 4 numbers(each represents a property of the piece) ranging from 0-2. I need to generate all combinations to get all the game pieces.
So I would need [1, 0, 2, 0], [2, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 0] etc..
There should be 81 total combinations of [a, b, c, d] where each variable is a number 0-2.
I am using javascript but any psudocode would be helpful.
Any help is appreciated. Thanks!
Mine
var arr=[];
for (var str,i=0;i<81;i++) {
str = i.toString(3);
arr.push(("000"+str).slice(-4)); // Hmm, I thought slice returned an array.
}
Here is an update taking into account the comments from #katspaugh and #herby
var arr=[];
for (var str,i=81;i<162;i++) {
str = i.toString(3);
arr.push((str).slice(-4).split('').map(Number));
}
If it is a homework, tag it as such.
var BASE = 3, LEN = 4, LIMIT = Math.round(Math.pow(BASE, LEN));
var c = [];
for (var i = 0; i < LIMIT; ++i) {
var item = [];
for (var j = 0, k = i; j < LEN; ++j, k = Math.floor(k/BASE)) {
item.push(k % BASE);
}
c.push(item);
}
Here is a more tricky solution but showing the math behind it better, hopefully:
var BASE = 3, LEN = 4;
var powers = [];
for (var i = 0, LIMIT = 1; i < LEN; ++i, LIMIT *= BASE) {
powers.push(LIMIT);
}
var c = [];
for (i = 0; i < LIMIT; ++i) {
c.push(powers.map(function(basePower) {
return Math.floor(i/basePower) % BASE;
}));
}
var BASE = 3, COMB_LEN = 4
var max = parseInt(new Array(COMB_LEN + 1).join(BASE - 1), BASE),
comb = new Array(COMB_LEN + 1).join(0).split('').map(Number)
var combinations = [], i, n
for (i = 0; i <= max; i++) {
n = i.toString(BASE).split('').map(Number)
combinations.push(
comb.slice(0, COMB_LEN - n.length).concat(n)
)
}