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;
}
Related
How do i multiply every number in the array from position tabProsent[I] to the left? It is not working for me to write tabProsent[i].reduceRight(getSum).
function getSum(total, num) {
return total * num;
}
// Update the current slider year (each time you drag the slider handle)
slider.oninput = function() {
output.innerHTML = this.value;
var i;
for (i = 0; i < tabAar.length; i++) {
if (slider.value == tabAar[i]) {
output2.innerHTML=Math.round(startVerdi * tabProsent[i].reduceRight(getSum));
}
}
}
This is a possible solution.
Note: I don't know what the result should be if the index is negative, actually then you get an result of 1. If index is greater then array-length the I reduce pos to the array-length.
function getMult(arr, pos) {
if (pos>=arr.length)
pos = arr.length-1;
let res =1;
for (let i=0; i<= pos; i++) {
res *= arr[i];
}
return res;
}
console.log(getMult([1,2,3,4,5], 3));
A functional approach could look like this:
let multToLeft = (arr, num, m) => {
if (num < 0 || num > arr.length) throw new Error(`Invalid num ${num}`);
return [ ...arr.slice(0, num).map(v => v * m), ...arr.slice(num) ];
};
let examples = [
[ [ 1, 2, 3, 4, 5 ], 2, 10 ],
[ [ 1, 2, 3, 4, 5 ], 3, 20 ],
[ [ 1, 2, 3, 4, 5 ], 5, 11 ]
];
for (let [ arr, num, m ] of examples) {
console.log(`multToLeft(${JSON.stringify(arr)}, ${num}, ${m}) -> ${JSON.stringify(multToLeft(arr, num, m))}`);
}
Note that I am working with num instead of index. I've chosen num to indicate the actual number of elements to the left of the array that get multiplied. This makes more sense than working with index, as it becomes messy to apply the multiplication to zero elements in the array (since supplying 0 would still mean to apply the multiplication to the first array item).
Why the following array doesn't push correctly in the loop to r?
If I change to if((pivot + originArr[c]) <= 5) instead of if((pivot + originArr[c]) <= 3)
My result is wrong:
[ [ 0, 1, 2, 3, 4 ],
[ 0, 1, 2, 3, 4 ],
[ 0, 1, 2, 3, 4 ],
[ 0, 2, 3 ],
[ 1, 2, 3 ] ]
Expected result should be[ [ 0, 1, 2], [ 0, 1, 3], [ 0, 1, 4], [ 0, 2, 3 ] ]
If r is not empty, it will recursive and send the first iteration result to the function to do computation until the "r" is empty. It doesn't push individual group of array to "r" for every c loop.
var data = [0, 1, 2, 3, 4, 5];
function compute(originArr, filterArr) {
var r = [];
var arr;
let firstLoop = false;
if (filterArr.length == 0) {
firstLoop = true;
arr = originArr;
} else {
arr = filterArr;
}
arr.forEach(function(i, index) {
var pivot;
if (firstLoop) {
pivot = index;
} else {
pivot = parseInt(i.slice(-1));
}
var nextIndex = pivot + 1;
console.log(pivot, nextIndex);
for (var c = nextIndex; c < originArr.length; c++) {
let tempResult = [];
console.log(c);
if (pivot + originArr[c] <= 3) {
if (firstLoop) {
tempResult.push(index);
} else {
tempResult = i;
}
tempResult.push(c);
console.log(tempResult);
r.push(tempResult); // suppose to push [0,1], [0,2], [0,3], [1,2] for the first iteration
}
}
});
if (r.length > 0) {
return compute(originArr, r);
} else {
return arr;
}
}
console.log(compute(data, []));
//Final result should be [[0,1,2]]
I think I found out the problem.
We can't clone the array like this
tempResult = i;
it will affect the reference 'i' after I have pushed the new number into the temResult.
So my solution is to change the cloning way to:
tempResult = [...i];
That cloning will not affects the reference.
There is an outer array containing many other arrays. I generate the inner arrays an push them to the outer one.
for (i = 0; i < 12; i++) {
if (i == 0) {
var p = [];
for (n = 0; n < 4; n++) {
p.push(n);
}
} else {
s = i % (3);
var b = p[s+1];
p[s+1] = p[s];
p[s] = b;
}
console.log(p);
}
/*OUTPUT:
Array(4) [ 0, 1, 2, 3 ]
tsp.js:45:17
Array(4) [ 0, 2, 1, 3 ]
tsp.js:45:17
Array(4) [ 0, 2, 3, 1 ]
tsp.js:45:17
Array(4) [ 2, 0, 3, 1 ]
tsp.js:45:17
Array(4) [ 2, 3, 0, 1 ]
tsp.js:45:17
Array(4) [ 2, 3, 1, 0 ]
tsp.js:45:17
Array(4) [ 3, 2, 1, 0 ]
tsp.js:45:17
Array(4) [ 3, 1, 2, 0 ]
tsp.js:45:17
Array(4) [ 3, 1, 0, 2 ]
tsp.js:45:17
Array(4) [ 1, 3, 0, 2 ]
tsp.js:45:17
Array(4) [ 1, 0, 3, 2 ]
tsp.js:45:17
Array(4) [ 1, 0, 2, 3 ]
*/
This code outputs as expected a lot of different arrays. But this one outputs one array containing the same array over and over again:
o = [];
for (i = 0; i < 12; i++) {
if (i == 0) {
var p = [];
for (n = 0; n < 4; n++) {
p.push(n);
}
} else {
s = i % (3);
var b = p[s+1];
p[s+1] = p[s];
p[s] = b;
}
o.push(p);
}
console.log(o);
/*
OUTPUT:
(12) […]
0: Array(4) [ 1, 0, 2, … ]
1: Array(4) [ 1, 0, 2, … ]
2: Array(4) [ 1, 0, 2, … ]
3: Array(4) [ 1, 0, 2, … ]
4: Array(4) [ 1, 0, 2, … ]
5: Array(4) [ 1, 0, 2, … ]
6: Array(4) [ 1, 0, 2, … ]
7: Array(4) [ 1, 0, 2, … ]
8: Array(4) [ 1, 0, 2, … ]
9: Array(4) [ 1, 0, 2, … ]
10: Array(4) [ 1, 0, 2, … ]
11: Array(4) [ 1, 0, 2, … ]
length: 12
<prototype>: Array []
tsp.js:47:13
*/
I expected that the second code outputs all the different arrays from the for loop packed in one array, but it doesn't.
When you do o.push(p); you're pushing a reference of p into your array. This means at each iteration of your loop when you modify the elements in p, the elements at your reference change, thus changing the array within your o array.
Thus, you need to make unique references to your p arrays before pushing them into your o array. One way to do this is using .slice() to make a copy of your array like so:
var o = [];
for (var i = 0; i < 12; i++) {
if (i == 0) {
var p = [];
for (var n = 0; n < 4; n++) {
p.push(n);
}
} else {
var s = i % (3);
var b = p[s + 1];
p[s + 1] = p[s];
p[s] = b;
}
o.push(p.slice()); // copy the elements in p to a new array, such that the array is now it's own unique reference in memory
}
console.log(o);
One problem with both examples, is that you declare p in the if branch, but reference it in the else branch and in the enclosing scope.
Try moving it to the start of the function:
for (i = 0; i < 12; i++) {
var p = [];
if (i == 0) {
or
var p = [];
for (i = 0; i < 12; i++) {
if (i == 0) {
Depending on which meets your requirements
You're declaring var p = []; inside the loop which seems to be working because it is a javascript, but very confusing. Move it to the upper lever near the o = [];
the problem you're facing is because you're pushing the reference to an array and not just values. You need to copy values to a new array before doing a o.push();
var o = [];
var p = [];
for (i = 0; i < 12; i++) {
if (i == 0) {
for (n = 0; n < 4; n++) {
p.push(n);
}
} else {
s = i % (3);
var b = p[s + 1];
p[s + 1] = p[s];
p[s] = b;
}
var copy = [];
for (j = 0; j < p.length; j++) {
copy.push(p[j]);
}
o.push(copy);
}
console.log(o);
I have a problem with grouping an array of numeric value:
I have values in an array like this
var numb = [5,10,11,6,7,18,1,8,2,1,15,12,4,5,3,4,6,7,15,20];
that are then sorted into ascending numerical order
var sortedNumb = [1,1,2,3,4,4,5,5,6,6,7,7,8,10,11,12,15,15,18,20];
Now I want to create a group of numbers like
1-4 , 5-8 , 9-12 , 13-16 , 17-20
Is it possible to create groups dynamically, like that?
// important code
var numberToGroupOn = 4;
var numb = [5,10,11,6,7,18,1,8,2,1,15,12,4,5,3,4,6,7,15,20];
var srt = numb.slice(0).sort(function(a, b) { return a - b; });
var groupCount = Math.ceil(srt[srt.length-1] / numberToGroupOn);
var grps = {};
for(var i = 1; i <= groupCount; i++)
{
grps[((i*numberToGroupOn)-(numberToGroupOn-1)).toString() + '-' + (i*numberToGroupOn).toString()] =
srt.filter(function(a) {return (a <= i*numberToGroupOn) && (a >= (i*numberToGroupOn)-(numberToGroupOn-1))});
}
// unimportant code to see output in SO snippet
var output = '';
for(var key in grps)
{
output += key + ': ' + grps[key]+'<br>';
}
document.write(output);
This figures out the number of groups and then builds a dictionary of the groups using Array.prototype.filter.
It only works with positive numbers.
Assuming that 1-4, 5-8, 9-12, 13-16, 17-20 grouping means that you want 5 groups, the first one (1-4) containing all the numbers within the [1, 4] interval; the second one (5-8) containing all the numbers within the [5, 8] interval, and so on.
// numbers and intervals must be in ascending order
var numb = [5,10,11,6,7,18,1,8,2,1,15,12,4,5,3,4,6,7,15,20];
// 1-4 , 5-8 , 9-12 , 13-16 , 17-20
var intervals = [4, 8, 12, 16, 20];
numb.sort(function (a, b) {
return a - b;
});
var groups = [];
var j = 0;
for (var i = 0; i < intervals.length; i++) {
var group = [];
while (numb[j] <= intervals[i]) {
group.push(numb[j]);
j++;
}
groups.push(group);
}
console.log(groups);
The output:
[ [ 1, 1, 2, 3, 4, 4 ],
[ 5, 5, 6, 6, 7, 7, 8 ],
[ 10, 11, 12 ],
[ 15, 15 ],
[ 18, 20 ] ]
EDIT: After reading the comment about calculating the intervals based on the max number in the array.
var numb = [5,10,11,6,7,18,1,8,2,1,15,12,4,5,3,4,6,7,15,20];
numb.sort(function (a, b) {
return a - b;
});
var max = numb[numb.length - 1];
// Five groups based on the max value of the array
var increment = max / 5;
var groups = [];
var j = 0;
for (var i = increment; i <= max; i += increment) {
var group = [];
while (numb[j] <= i) {
group.push(numb[j]);
j++;
}
groups.push(group);
}
console.log(groups);
Output:
[ [ 1, 1, 2, 3, 4, 4 ],
[ 5, 5, 6, 6, 7, 7, 8 ],
[ 10, 11, 12 ],
[ 15, 15 ],
[ 18, 20 ] ]
Code : Assuming sortedNumb is not empty :)
var sortedNumb = [1,1,2,3,4,4,5,5,6,6,7,7,8,10,11,12,15,15,18,20];
var groups = [[sortedNumb[0]]];
var lastfirstValueInArray = sortedNumb[0];
var i = 1;
var j = 0;
while (i < sortedNumb.length)
{
if (sortedNumb[i] >= lastfirstValueInArray+4 || (sortedNumb[i]%4 == 1 && sortedNumb[i] != lastfirstValueInArray))
{
j++;
lastfirstValueInArray = 1+j*4;
groups[j] = [];
}
groups[j][groups[j].length] = sortedNumb[i];
i++;
}
console.log(groups);
Output :
[Array[6], Array[7], Array[3], Array[2], Array[2]]
Edit :
You seemed to want a range of group of 4, if you want N, just create a function taking it as parameter, and replace all 4 by N in code =)
Lets say that I am to remove the oldest element of an array, because I wanted to replace it with a new value. (first-in-first-out).
For example, I have this array of values
var arr = [1,2,3,4,5,6,7]
And I wanted to only get the first three, values, and then on the 4th, replace the element who came first
[1,2,3], [4,2,3], [4,5,3] and so on..
I came up with a solution
var arr = [1,1,2,3,4,5,6,7];
var newArr = [];
for(i=0; i<arr.length; i++){
if(newArr.length == 3 && newArr.indexOf(arr[i]) < 0) {
newArr[i%3] = arr[i];
} else if(newArr.indexOf(arr[i]) < 0) {
newArr.push(arr[i])
}
console.log(newArr)
}
Which will render:
1
1
1,2
1,2,3
1,4,3
1,4,5
6,4,5
6,7,5
Instead of
1
1,2
1,2,3
4,2,3
4,5,3
4,5,6
7,5,6
What am I missing out.
var arr = [1, 1, 2, 3, 4, 5, 6, 7];
var newArr = [], currentIndex = 0;
for (i = 0; i < arr.length; i++) {
if (newArr.length === 3 && newArr.indexOf(arr[i]) < 0) {
newArr[currentIndex % 3] = arr[i];
currentIndex += 1;
} else if (newArr.indexOf(arr[i]) < 0) {
newArr.push(arr[i]);
}
console.log(newArr)
}
Output
[ 1 ]
[ 1 ]
[ 1, 2 ]
[ 1, 2, 3 ]
[ 4, 2, 3 ]
[ 4, 5, 3 ]
[ 4, 5, 6 ]
[ 7, 5, 6 ]
You just need to track the current index where you need to place the number using a separate variable.