Combinations of n words from array of m words - Javascript - javascript

Given arr = ['mat','cat','fat']
A function getComb(arr, n = 2) where n is the number of words each combination must have.
Expected results:
mat cat
mat fat
cat fat
I could not modify the code below any further to get the desired results. Any idea? thx
Thanks to Knskan3:
'getCombinations': (arr, n) => {
let i, j, k, elem, l = arr.length, childperm, ret = [];
if (n === 1) {
for (let i = 0; i < arr.length; i++) {
ret.push([arr[i]]);
}
return ret;
}
else {
for (i = 0; i < l; i++) {
elem = arr.shift();
for (j = 0; j < elem.length; j++) {
childperm = lib.getCombinations(arr.slice(), n - 1);
for (k = 0; k < childperm.length; k++) {
ret.push([elem[j]].concat(childperm[k]));
}
}
}
return ret;
}
},

I suggest a space-efficient generator function:
// Generate all k-combinations of first n array elements:
function* combinations(array, k, n = array.length) {
if (k < 1) {
yield [];
} else {
for (let i = --k; i < n; i++) {
for (let combination of combinations(array, k, i)) {
combination.push(array[i]);
yield combination;
}
}
}
}
// Example:
console.log(...combinations(['mat', 'cat', 'fat'], 2));

Related

Is there a way to extend JavaScript call stack size?

I have tried setting Error.stackTraceLimit = Infinity in chrome and firefox, but no effect.
I'm just trying to multiply two matrixes in a recursive way.
it breakes at the point of a [32][32] matrix.
Here is the code that i run, a simple devide and conquer matrix multiplication
first i generate 2 random matrices and then multiply them
function divideConquer(a, b) {
var i = 0,
j = 0,
k = 0;
var c = [];
let row = [];
// creating the output
for (let l = 0; l < a.length; l++) {
row = [];
for (let m = 0; m < b[0].length; m++) {
row.push(parseInt(0));
}
c.push(row);
}
multiplyRecursion(a, b);
return c;
function multiplyRecursion(a, b) {
// If all rows traversed
if (i >= a.length)
return;
// If i < row1
if (j < b[0].length) {
if (k < a[0].length) {
c[i][j] += a[i][k] * b[k][j];
k++;
multiplyRecursion(a, b);
}
k = 0;
j++;
multiplyRecursion(a, b);
}
j = 0;
i++;
multiplyRecursion(a, b);
}
}
function generateRandomMatrix(n) {
let row = [],
matrix = [];
for (let i = 0; i < n; i++) {
row = [];
for (let j = 0; j < n; j++) {
row.push(Math.floor(Math.random() * 10));
}
matrix.push(row);
}
return matrix;
}
let a = generateRandomMatrix(32);
let b = generateRandomMatrix(32);
console.log(divideConquer(a, b));

What realization is faster and why

I wrote a function that calculate this value/formula:
and I have 2 realizations, and I don't understand, why realization with 3 loops is working faster than realization with if's?
Please, explain to me why is that?
If's realization:
function res(p, square) {
let res = 0
let i = 1;
let j = 1;
let k = 1;
label: for (;;) {
res += (i ** 3 * j ** 2 * k)
if (k < p) {
k++
continue label
}
if (j < p) {
k = 1
j++
continue label
}
if (i < p) {
k = 1
j = 1;
i++
continue label
}
if (k == p && j == p && i == p) {
return res
}
}
}
Loop realization:
function res1(p) {
let res = 0
for (let i = 0; i <= p; i++) {
for (let j = 0; j <= p; j++) {
for (let k = 0; k <= p; k++) {
res += (i ** 3 * j ** 2 * k)
}
}
}
return res
}

How can I refactor a lot of similar nested loops in my Matrix class?

How can I properly refactor my Matrix class where nearly all the methods I use in this class have double nested loops which all look almost exactly the same?
Here are two of many methods that I wish to include in this class. It's going to be unnecessarily long if I don't find a better way to deal with this.
randomize() {
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.matrix[i][j] = Math.random();
}
}
}
add(n) {
if (n instanceof Matrix) {
for (let i = 0; i < this.matrix.length; i++) {
for (let j = 0; j < this.matrix[i].length; j++) {
this.matrix[i][j] += n.matrix[i][j];
}
}
} else {
for (let i = 0; i < this.matrix.length; i++) {
for (let j = 0; j < this.matrix[i].length; j++) {
this.matrix[i][j] += n;
}
}
}
}
Similar to Barmar's answer just with a different flavor:
// Specify the limits for i, j, and then pass in a function
// which takes the index parameters.
function loop(iMax, jMax, fn) {
for (let i = 0; i < iMax; i++) {
for (let j = 0; j < jMax; j++) {
fn(i, j);
}
}
}
function randomize() {
loop(this.rows, this.columns, (i, j) => {
this.matrix[i][j] = Math.random();
});
}
function add(n) {
if (n instanceof Matrix) {
loop(this.matrix.length, this.matrix[0].length, (i, j) => {
this.matrix[i][j] += n[i][j];
});
}
}
This more generic approach allows you to do whatever you want with the loop indices. You could do reassignment, or you could log out the matrix values, or assign them to a new matrix.
loop(this.rows, this.cols, (i, j) => {
console.log(this.matrix[i][j]);
});
loop(this.rows, this.cols, (i, j) => {
that.matrix = this.matrix[i][j];
});
You can use a function.
class Matrix {
constructor(arr) {
this.matrix = arr;
this.rows = arr.length;
this.cols = arr[0].length;
}
loop(func, arr2, arr2Recurse) {
this.matrix = this.matrix.map((row, i) =>
row.map((col, j) => func(col, arr2Recurse ? arr2.matrix[i][j] : arr2))
);
}
randomize() {
this.loop(() => Math.random());
}
add(n) {
this.loop((el, nEl) => (el += nEl), n, n instanceof Matrix);
}
}
var a = new Matrix([[1, 2], [3, 4]]);
var b = new Matrix([[5, 6], [7, 8]]);
a.add(b);
console.log(a);
a.add(1);
console.log(a);
a.randomize();
console.log(a);
Use a higher-order function, which receives a function to be called on each element and returns the new value to replace it.
In my example below, the callback function also receives the indexes, so it can use them to reference another matrix, which is needed in the add method.
updateEach(callback) {
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.matrix[i][j] = callback(this.matrix[i][j], i, j);
}
}
}
randomize() {
this.updateEach(() => Math.random());
}
add(n) {
if (n instanceof Matrix) {
this.updateEach((oldval, i, j) => oldval + n.matrix[i][j]);
} else {
this.updateEach((oldval) => oldval + n)
}
}

Arrays with elements less or equal to the elements in given array

What is the most JS-style way to solve the following problem?
Given an array A, find all arrays B, such that for i <= A.length: B[i] <= A[i]. Example of what I expect:
#Input
A = [1,2,0]
#Output
B = [[0,0,0],
[1,0,0],
[1,1,0],
[1,2,0],
[0,1,0],
[0,2,0]]
In Python I used:
B = [[]];
for t in [range(e+1) for e in A]:
B = [x+[y] for x in B for y in t]
Thanks in advance!
Use the following code (any loop for one item of the array a):
var a = [1, 2, 0], b = [];
for (var i = 0; i < a[0]; i++) {
for (var j = 0; j < a[1]; j++) {
for (var k = 0; k <= a[2]; k++) {
b.push([i, j, k]);
}
}
}
If you know the numebr of items in the array a only on runtime, use the following recursive function:
function fillArray(source, dest, recursionLevel, tempArr) {
if (recursionLevel >= source.length) {
dest.push(tempArr);
return;
}
for (var i = 0; i <= source[recursionLevel]; i++) {
var tempArr2 = tempArr.slice(); // Copy tempArr
tempArr2.push(i);
fillArray(source, dest, recursionLevel + 1, tempArr2);
}
}
fillArray(a, b, 0, []);
I found this solution. I'm sure it can be coded in a much nicer way. However, it works and I hope you find it useful
all_combinations(A){
var B = [];
for (var i = 0; i < A[0] + 1; i++) {
B.push([i]);
}
for (var i = 1; i < A.length; i++) {
var _tmp_array = [];
for (var j = 0; j < A[i] + 1; j++) {
for (var k = 0; k < B.length; k++) {
var _new_element = B[k].concat([j]);
_tmp_array.push(_new_element);
}
}
B = _tmp_array;
}
return B;
}

JavaScript arrays - Finding the number of combinations of 2 elements

I come from a Ruby background, which features an enumerable class. In Ruby, I can easily find combinations of array elements.
array.combination(2).count
I know that JavaScript doesn't feature such built in functions, so I was wondering how I could implement this in JS. I was thinking something like
I have an array as follows
var numbers = [9,7,12]
var combos = []
for (var i = 0; i < numbers.length; i++) {
combos.push([numbers[i], numbers[i+1])
}
By the way, the possible combos are
[9,7], [9,12] and [7,12]
so by calling the length function on this array, 3 would be returned.
Any ideas?
How about:
for (var i = 0; i < numbers.length; i++)
for (var j = i + 1; j < numbers.length; j++)
combos.push([numbers[i], numbers[j]]);
Are you strictly talking about 2-combinations of the array or are you interested in a k-combinations solution?
Found this in this gist
function k_combinations(set, k) {
var i, j, combs, head, tailcombs;
if (k > set.length || k <= 0) {
return [];
}
if (k == set.length) {
return [set];
}
if (k == 1) {
combs = [];
for (i = 0; i < set.length; i++) {
combs.push([set[i]]);
}
return combs;
}
// Assert {1 < k < set.length}
combs = [];
for (i = 0; i < set.length - k + 1; i++) {
head = set.slice(i, i+1);
tailcombs = k_combinations(set.slice(i + 1), k - 1);
for (j = 0; j < tailcombs.length; j++) {
combs.push(head.concat(tailcombs[j]));
}
}
return combs;
}
Here's a recursive function, which should work for any number:
function combination(arr, num) {
var r= [];
for(var i = 0 ; i < arr.length ; i++) {
if(num===1) r.push([arr[i]]);
else {
combination(arr.slice(i+1), num-1).forEach(function(val) {
r.push([].concat(arr[i], val));
});
}
}
return r;
} //combination
Working Fiddle

Categories