Trying to count possible combinations to get a targetTotal. Using powerSet returns the sum without adding itself. E.g [1,2,3,5] returns [3+1] for a targetSum of 4, whereas I expect to get [1+1+1+1], [2+2], [3+1].
Do you have any ideas how I could make it count itself first as a case?
function powerset(arr) {
var ps = [[]];
for (var i=0; i < arr.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(arr[i]));
}
}
return ps;
}
function sum(arr) {
var total = 0;
for (var i = 0; i < arr.length; i++)
total += arr[i];
return total
}
function findSums(numbers, targetSum) {
var sumSets = [];
var numberSets = powerset(numbers);
for (var i=0; i < numberSets.length; i++) {
var numberSet = numberSets[i];
if (sum(numberSet) == targetSum)
sumSets.push(numberSet);
}
return sumSets;
}
Example invocation:
findSums([1,2,3,4,5],6); [[2,3], [1,4], [5], [1,1,1,1,1,1], [2,2,2], [3,3]]
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;
}
I am doing freecodecamp's Bonfire:Chunky Monkey. I almost have the solution, but I can't figure it out why it isn't working. So my question is: "Why does this return [['a', 'b']], instead of [['a','b'],['c','d']]?
function chunk(arr, size) {
var array = [];
var tmp = [];
for(var i = 0; i < Math.floor(arr.length/size); i++)
{
for(var j = 0; j < size; j++)
{
tmp.push(arr[j]);
}
array.push(tmp);
tmp = [];
arr.splice(0,size);
}
return array;
}
chunk(['a', 'b', 'c', 'd'], 2);
Because you are altering the length of arr within the loop. As a result, the outer loop only runs once. You need to cache this before you alter it:
function chunk(arr, size) {
var array = [];
var tmp = [];
// save this, otherwise the 2nd iteration will not run at all
// because the new array length will be 2, making half of that 1
var iter = Math.floor(arr.length / size);
for (var i = 0; i < iter; i++) {
for (var j = 0; j < size; j++) {
tmp.push(arr[j]);
}
array.push(tmp);
tmp = [];
arr.splice(0, size);
}
return array;
}
You are modifying the length of arr on each iteration preventing it from executing the second time.
Besides, one loop is enough.
function chunk(arr, size) {
var array = [];
for(var i = 0; i < arr.length; i += size) {
array.push(arr.slice(i, i + size));
}
return array;
}
chunk(['a', 'b', 'c', 'd'], 2);
Another approach:
function chunk(arr, size) {
var array = [];
var tmp = [];
var aux = 0;
for(var i = 0; i < Math.ceil(arr.length/size); i++)
{
for(var j = aux; j < aux + size; j++)
{
arr[j] != undefined?tmp.push(arr[j]):false;
}
aux = aux + size;
array.push(tmp);
tmp = [];
}
return array;
}
console.log(chunk(['a', 'b', 'c', 'd', 'e', 'f'], 2));
PS: It works with even and odd number of elements in the array.
Plenty of answers with working codes, so I just answer the why.
You thought the outer loop iterates twice, because Math.floor(arr.length/size) is 2 at the beginning:
for(var i = 0; i < Math.floor(arr.length/size); i++) {
// ....
}
However, arr is chunked in the first iteration:
arr.splice(0,size); // arr is ['c', 'd'] after this step
For the second iteration, i becomes 1 and Math.floor(arr.length/size) is actually Math.floor(['c', 'd']/2), the check fails and the loop exits. So there isn't a second iteration.
Configurable chunk size example with a loop.
function chunk(arr, chunkSize) {
var array = [];
for (var index = 0, arrLen; index < chunkSize; index++) {
arrLen = arr.length;
if (arrLen >= chunkSize) {
array[index] = arr.splice(0, chunkSize === 1 ? arrLen : chunkSize);
} else if (arrLen > 0) {
array[index] = arr.splice(0, arrLen);
}
}
return array;
}
var result = chunk(['a', 'b', 'c', 'd'], 1);
console.log(result);
Is there anyway to merge arrays in javascript by ordering by index/position. I'm try to accomplish this and haven't been able to find any examples of this.
var array1 = [1,2,3,4]
var array2 = [a,b,c,d]
var array3 = [!,#,#,$]
var merged array = [1,a,!,2,b,#,3,c,#,4,d,$]
I know you can use concat() to put one after the other.
As long as the arrays are all the same length you could just do:
var mergedArray = [];
for (var i = 0, il = array1.length; i < il; i++) {
mergedArray.push(array1[i]);
mergedArray.push(array2[i]);
mergedArray.push(array3[i]);
}
EDIT:
For arrays of varying lengths you could do:
var mergedArray = [];
for (var i = 0, il = Math.max(array1.length, array2.length, array3.length);
i < il; i++) {
if (array1[i]) { mergedArray.push(array1[i]); }
if (array2[i]) { mergedArray.push(array2[i]); }
if (array3[i]) { mergedArray.push(array3[i]); }
}
This should work for arrays of ANY length:
var mergeArrays = function () {
var arr = [],
args = arr.slice.call(arguments),
length = 0;
for (var i = 0, len = args.length; i < len; i++) {
length = args[i].length > length ? args[i].length : length;
}
for (i = 0; i < length; i++) {
for (var j = 0; j < len; j++) {
var value = args[j][i];
if (value) {
arr.push(value);
}
}
}
return arr;
};
Example:
var array1 = [1,2,3,4];
var array2 = ['a','b','c','d','e','f','g','h','i','j','k','l'];
var array3 = ['!','#','#','$','%','^','&','*','('];
mergeArrays(array1, array2, array3);
// outputs: [1, "a", "!", 2, "b", "#", 3, "c", "#", 4, "d", "$", "e", "%", "f", "^", "g", "&", "h", "*", "i", "(", "j", "k", "l"]
This would work also (a little more terse syntax):
var mergeArrays = function () {
var arr = [],
args = arr.slice.call(arguments),
length = Math.max.apply(null, args.map(function (a) { return a.length; }));
for (i = 0; i < length; i++) {
for (var j = 0, len = args.length; j < len; j++) {
var value = args[j][i];
if (value) {
arr.push(value);
}
}
}
return arr;
};
For arrays that are all the same size, where you pass one or more arrays as parameters to merge:
function merge()
{
var result = [];
for (var i=0; i<arguments[0].length; i++)
{
for (var j=0; j<arguments.length; j++)
{
result.push(arguments[j][i]);
}
}
return result;
}
var array1 = ['1','2','3','4'];
var array2 = ['a','b','c','d'];
var array3 = ['!','#','#','$'];
var merged = merge(array1, array2, array3);
Nothing built in, but it wouldn't be hard to manage:
var maxLength = Math.max(array1.length, array2.length, array3.length),
output = [];
for (var i = 0; i < maxLength; i++) {
if (array1[i] != undefined) output.push(array1[i]);
if (array2[i] != undefined) output.push(array2[i]);
if (array3[i] != undefined) output.push(array3[i]);
}
try this...
var masterList = new Array();
var array1 = [1,2,3,4];
var array2 = [a,b,c,d];
var array3 = [!,#,#,$];
for(i = 0; i < array1.length; i++) {
masterList.push(array1[i]);
masterList.push(array2[i]);
masterList.push(array3[i]);
}
It looks like you want to "zip" some number of same-length arrays into a single array:
var zip = function() {
var numArrays=arguments.length
, len=arguments[0].length
, arr=[], i, j;
for (i=0; i<len; i++) {
for (j=0; j<numArrays; j++) {
arr.push(arguments[j][i]);
}
}
return arr;
};
zip([1,2], ['a', 'b']); // => [1, 'a', 2, 'b']
zip([1,2,3], ['a','b','c'], ['!','#','#']); // => [1,'a','#',...,3,'c','#']
If the input arrays could be of different length then you've got to figure out how to deal with that case...
Yes, there is some way to do that. Just:
loop through the larger array,
until at the currently processed position both arrays have elements, assign them one-by-one to the new array,
after the shorter array ends, assign only elements from the longer array,
The resulting array will have the elements ordered by the index from the original arrays. From your decision depends, position in which one of these arrays will have higher priority.
This works for any number of array and with arrays of any length.
function myMerge() {
var result = [],
maxLength = 0;
for (var i = 0; i < arguments.length; i++) {
if (arguments[i].length > maxLength) { maxLength = arguments[i].length; }
}
for (var i = 0; i < maxLength; i++) {
for (var j = 0; j < arguments.length; j++) {
if (arguments[j].length > i) {
result.push(arguments[j][i]);
}
}
}
return result;
}
Eli beat me to the punch up there.
var posConcat = function() {
var arrays = Array.prototype.slice.call(arguments, 0),
newArray = [];
while(arrays.some(notEmpty)) {
for(var i = 0; i < arrays.length; i++) {
if(arguments[i].length > 0)
newArray.push(arguments[i].shift());
}
}
return newArray;
},
notEmpty = function() { return arguments[0].length > 0; };
Usage:
var orderedArray = posConcat(array1,array2,array3);
Sample: http://jsfiddle.net/HH9SR/
Consider this:
[ ["a", "b"], ["c", "d"], ["e"] ]
How can this be tranformed to:
[ "a c e", "a d e", "b c e", "b d e" ]
// edit: tested and works
function product(set) {
if(set.length < 2)
return set[0];
var head = set.shift(), p = product(set), r = [];
for(var j = 0; j < head.length; j++)
for(var i = 0; i < p.length; i++)
r.push([head[j]].concat(p[i]));
return r;
}
var set = [
[ "a", "b", "c"],
[ "D", "E" ],
[ "x" ]
];
var p = product(set);
for(var i = 0; i < p.length; i++)
document.write(p[i] + "<br>");
This works:
<html><body><script>
var to_join = [ ["a", "b"], ["c", "d"], ["e"] ];
var joined = to_join[0];
for (var i = 1; i < to_join.length; i++) {
var next = new Array ();
var ends = to_join[i];
for (var j = 0; j < ends.length; j++) {
for (var k = 0; k < joined.length; k++) {
next.push (joined[k]+ " " + (ends[j]));
}
}
joined = next;
}
alert (joined);
</script></body></html>
Try concat method:
var newArr=[];
for(var i=0; i< arr.length; i++)
{
newArr = newArr.concat(arr[i]);
}