So i scanned a bit the website and found nothing on it except for permutation but is not really that. What i'm looking for is to input an array of elements example: [2,5,10] and get the result of all possible, non duplicate sums. It there any one that can be done? Using the example, the array [7,10,15] should be resulted from such function.
Since people think this is a challenge or homework, it is not.
What i tried so far is something like this but i'm stuck:
for(var i = 0; i < multipliers.length;){
var length = multipliers.length;
var counter = 0;
while(++counter <= length){
var x = 0;
var sum = multipliers[i] + multipliers[x];
x++;
console.log(sum)
}
i++;
}
The only possible solution with a single loop, is to use to count from zero to 2 with the power of the item count minus one.
Basically it renders to this
indices comment
------- ---------
0 1 2
0 0 0
1 0 0
0 1 0
1 1 0 take this combination
0 0 1
1 0 1 take this combination
0 1 1 take this combination
1 1 1
function getCombination(array, size) {
var result = [],
temp,
i, j,
max = 1 << array.length;
for (i = 0; i < max; i++) {
temp = [];
for (j = 0; j < array.length; j++) {
if (i & 1 << j) {
temp.push(array[j]);
}
}
if (temp.length === size) {
result.push(temp.reduce(function (a, b) { return a + b; }));
}
}
return result;
}
console.log(getCombination([2, 5, 10], 2));
You could use a recursive approach while checking the wanted length and if some values are still available.
This solution works with a nested approach for any elementsand collects them in a temporary array. If the array has the wanted lenght, then the elements are added and the result pushed to the result set.
The important part is the recursive calling with the actual element and the calling without the actual element.
function getCombination(array, size) {
function getC(temp, i) {
if (temp.length === size) {
result.push(temp.reduce(function (a, b) { return a + b; }));
return;
}
if (i === array.length) {
return;
}
getC(temp.concat(array[i]), i + 1);
getC(temp, i + 1);
}
var result = [];
getC([], 0);
return result;
}
console.log(getCombination([2, 5, 10], 2));
Related
My question maybe seems like duplicated but I can't find how to do this in vanilla javascript.
(I found answer in python here.)
So basically I want to get a list of all possible combinations of number that sum up to a desired number.
For example:
function sum_to_n(n,size){}
x = sum_to_n(6,3)
// [6,0,0] [5,1,0] [4,2,0] [4,1,1] [3,3,0] [3,2,1] [2,2,2]
This is what I can do so far:
function sum_to_n(n, size, sum=[], limit) {
if (size === 1) {
sum.push(n)
return sum
}
if (!limit) {
limit = n
}
let start = Math.min(n, limit)
let stop = Math.ceil(n/size) - 1
for (let i = start; i > stop; i--) {
let tmp = [...sum];
tmp.push(i)
let combination = sum_to_n(n-i, size - 1, tmp, i)
if (combination) {
console.log(combination) // this work
}
}
}
// I don't know how to make this work
let x = sum_to_n(6, 3)
// or maybe this
for (let y in sum_to_n(6,3)) {
console.log(y)
}
This is closely related to partitions of an integer, which finds all distinct ways of breaking an integer into the sum of positive integers. For instance, the partitions of 4 are 4, 3 + 1, 2 + 2, 2 + 1 + 1, and 1 + 1 + 1 + 1. Although there is probably a more direct way of calculating your sum, it's easy to do atop a partitions function:
const partitions = (n, max = n) =>
n == 0
? [[]]
: n < 0
? []
: Array .from ({length: Math .min (n, max)}, (_, i) => i + 1) // or use a `ramge` function
.reverse()
.flatMap (x => partitions (n - x, x) .map (p => [x, ...p]))
const sumToN = (n, c) =>
partitions (n + c)
.filter (p => p .length == c)
.map (p => p .map (x => x - 1))
console .log (sumToN (6, 3))
.as-console-wrapper {max-height: 100% !important; top: 0}
(The reverse call is not strictly necessary, but the usual partition description is written in this order, as is your requested output. The Array.from (...) call would be better expressed using a range function, but is not horrible inlined like this.)
We need to do two things: we have to find only those of the correct length, and we need to allow zeros as well as the positive numbers that partition generates. We can do this by partitioning a larger number and subtracting 1 from each value in every partition, and filtering the results down to those with the proper length.
The larger number we need -- since we're going to subtract 1 for every one of our c elements in each partition -- is simply n + c.
This algorithm's performance is exponential in n. But that's necessary as there are an exponential number of such partitions, and presumably an exponential number of results for your requested output. (I don't know a proof of this, and it's possible I'm wrong. If I am, I'd love to see a sub-exponential algorithm.)
'use strict';
function _sumToN(n, size, acc = [], solutions = []) {
if (size === 0) {
const sum = acc.reduce((sum, num) => sum + num);
return sum === n ? solutions.concat([acc]) : solutions;
}
for (let i = 0; i <= n; ++i)
solutions = _sumToN(n, size - 1, acc.concat(i), solutions);
return solutions;
}
function sumToN(n, size) {
return _sumToN(n, size);
}
console.log(sumToN(6, 3));
The above uses a driver, _sumToN, which accepts an additional acc accumulator array, and a solutions array that will eventually hold all the solutions. It iterates as follows:
0 0 0
0 0 1
0 0 2
...
0 0 6
...
6 6 6
and saves off solutions when they sum to n. There are of course optimizations that can be made, but hopefully this trivial implementation helps.
let sum_to_n = (n, iteration_limit) => {
let res = [];
for (let i = 0; i < iteration_limit; i++) {
for (let j = 0; j < iteration_limit; j++) {
for (let h = 0; h < iteration_limit; h++) {
if(i+j+h == n){
res.push([i, j, h])
}
}
}
}
return res;
};
This worked for me, however it does not have a size parameter.
let getOperator = (size, arr, expect) => {
let ev = "";
for (let i = 0; i < size; i++) {
ev += `${arr[i]}+`;
}
return `${ev.slice(0, ev.length-1)} == ${expect}`;
}
let sum_to_n = (n, size, iteration_limit) => {
return new Promise(resolve => {
let identifiers = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split('');
let all_identifiers = [];
let res = [];
let ev = "";
for (let i = 0; i < size; i++) {
let r = identifiers[i];
all_identifiers.push(r);
ev += `for (let ${r} = 0; ${r} < iteration_limit; ${r}++){\n`;
}
let push_value_string = "";
for (let i = 0; i < all_identifiers.length; i++) {
push_value_string += `${all_identifiers[i]}, `;
}
ev += `\nif(${getOperator(size, all_identifiers, n)}){\nres.push([${push_value_string.slice(0, push_value_string.length-1)}]);\n}`;
for (let i = 0; i < size; i++) {
ev += "}";
}
console.log(ev);
eval(ev);
resolve(res);
});
};
sum_to_n(15, 3, 100).then(console.log);
Basically depending on the size it will make a JavaScript code in a text size times, save what word it used for the for loop and check if the addition of all is equal to n. Then evaluate it and resolve it.
Given an array of integers, what's the most efficient way to perform j operations on the array where the value of j could be => or <= array.length?
I tried something like this...
function performJ(arr, j) {
arr.sort((a, b) => b - a);
let i = 0;
while (j !== 0) {
if (i < arr.length) {
arr[i] = Math.ceil(arr[i] / 2)
} else {
// when i reaches arr.length, reset it to continue operations j
i = 0;
arr[i] = Math.ceil(arr[i] / 2)
}
// increment i, step through arr
++i;
// decrement j as we perform operations on arr
--j;
}
return arr.reduce((a, b) => a + b);
}
That works for a lot of cases, but for some reason it seems like large inputs of arr and j cause arithmetic operations in the while loop to get way off.
Thanks!
EDIT: Edited question for clarity. I previously had a solution that worked, but it took way too long. This solution's arithmetic is off, but works much faster.
Use modulo to iterate on indicies [i % arr.length] from 0 to j:
function performJ(arr, j) {
arr.someMethod(); // ?
for (let i = 0; i < j; i++) {
arr[i % arr.length] = /* operation */
}
return arr.someMethod(); // ?
}
Why not just a for loop like this?
for(let i = 0; i <= j; i++) {
const index = i % array.length;
array[index] = doSomething();
}
if array.length is 5 but j is 3 then doSomething() will only be called on the first three elements. if array.length is 3 but j is 5 then i will reach 3 and 3 % 3 === 0 so index will loop back to the beginning. That means doSomething() will be called on all three elements once and during the second run on only the first two elements.
Is this what you want?
I'm trying to solve this exercise. There is a string of numbers and among the given numbers the program finds one that is different in evenness, and returns a position of this number. The element has to be returned by its index (with the number being the actual position the number is in). If its index 0, it has to be returned as 1. I have this so far but it's not passing one test. I'm not too sure why because it feels like it should. Is anyone able to see what the error is? Any help is appreciated!
function iqTest(numbers) {
var num = numbers.split(" ");
var odd = 0;
var even = 0;
var position = 0;
for(var i = 0; i < num.length; i++) {
if(num[i]%2!==0) {
odd++;
if(odd===1) {
position = num.indexOf(num[i]) + 1;
}
}
else if(num[i]%2===0) {
even++;
if(even===1) {
position = num.indexOf(num[i]) + 1;
}
}
}
return position;
}
iqTest("2 4 7 8 10") output 3
iqTest("2 1 2 2") output 2
iqTest("1 2 2") outputs 2 when it should be 1
The simplest way is to collect all even/odd positions in subarrays and check what array has the length 1 at the end:
function iqTest(numbers) {
numbers = numbers.split(' ');
var positions = [[], []];
for (var i = 0; i < numbers.length; i++) {
positions[numbers[i] % 2].push(i + 1);
}
if(positions[0].length === 1) return positions[0][0];
if(positions[1].length === 1) return positions[1][0];
return 0;
}
console.log(iqTest("2 4 7 8 10"))
console.log(iqTest("2 1 2 2"))
console.log(iqTest("1 2 2"))
console.log(iqTest("1 3 2 2"))
Your code is overly complex.
Since the first number determines whether you're looking for an even number or an odd one, calculate it separately. Then, find the first number that doesn't match it.
function iqTest(numbers) {
numbers = numbers.split(" ");
var parity = numbers.shift() % 2;
for( var i=0; i<numbers.length; i++) {
if( numbers[i] % 2 != parity) {
return i+2; // 1-based, but we've also skipped the first
}
}
return 0; // no number broke the pattern
}
That being said, iqTest("1 2 2") should return 2 because the number in position 2 (the first 2 in the string) is indeed the first number that breaks the parity pattern (which 1 has established to be odd)
You have to define which "evenness" is the different one. Use different counters for the two cases, and return -1 if you don't have a single different one. Something like this:
function iqTest(numbers) {
var num = numbers.split(" ");
var odd = 0;
var even = 0;
var positionOdd = 0;
var positionEven = 0;
for(var i = 0; i < num.length; i++) {
if(num[i]%2!==0) {
odd++;
if(odd===1) {
positionOdd = i + 1;
}
}
else if(num[i]%2===0) {
even++;
if(even===1) {
positionEven = i + 1;
}
}
}
if (odd == 1)
return positionOdd;
else if (even == 1)
return positionEven;
else
return -1;
}
Note that, if you have exactly a single even number and a single odd one, the latter will be returned with the method of mine. Adjust the logic as your will starting from my solution.
Since the first number determines whether you're looking for an even number or an odd one, calculate it separately.
Then, find the first number that doesn't match it.
function iqTest(numbers){
// ...
const numArr = numbers.split(' ');
const checkStatus = num => (parseInt(num) % 2) ? 'odd' : 'even';
const findUniqueStatus = array => {
let numEvens = 0;
array.forEach(function(value){
if (checkStatus(value) == 'even') { numEvens++; }
});
return (numEvens === 1) ? 'even' : 'odd'
}
let statuses = numArr.map(checkStatus),
uniqueStatus = findUniqueStatus(numArr);
return statuses.indexOf(uniqueStatus) + 1;
}
}
public static int Test(string numbers)
{
var ints = numbers.Split(' ');
var data = ints.Select(int.Parse).ToList();
var unique = data.GroupBy(n => n % 2).OrderBy(c =>
c.Count()).First().First();
return data.FindIndex(c => c == unique) + 1;
}
The given function should accept any array with any number of integers.
After it should subtract each two integers from each other beside integers which the same index.
var ArrayFirst = [4, 34, 6, 1,5];
var ArraySecond = [4,34,6,1,4];
function Find(Arg) {
var ResultArray;
var SecondArray = [];
for (var i = 0; i < Arg.length; i++) {
var FirsArray;
for (var j = 0; j < Arg.length; j++) {
if (Arg.indexOf(Arg[i]) != Arg.indexOf(Arg[j])) {
console.log(Arg.indexOf(Arg[i]) + 'AND' + Arg.indexOf(Arg[j]));
FirstArray = Arg[i] - Arg[j];
console.log(FirstArray);
if (FirstArray >= 0) {
SecondArray.push(FirstArray);
}
}
}
//console.log(SecondArray);
}
ResultArray = Math.min.apply(this, SecondArray);
console.log(ResultArray);
return ResultArray;
}
So After debuging I found that function Find works with ArrayFirst but not with ArraySecond
Question : Why function is not working when Array has two integers with the same value ?
UPDATED
Sorry guys that I haven't putted more details
Task: Create a function which as result will give the sum of subtracting two integers from an array, the sum cannot be subtraction of two integers which have the same index, the sum cannot be bellow 0, the sum closest to the 0 will be the proper result.
Example: [4,6,3,56,4]
4-6,4-3...4-4, then 6-4,6-3...6-4 then etc
So result will be 0 because 4-4 sum is 0
Some Hints
Firstly i thought maybe it is something to do with operation on array but then i used apply and call on arguments
if (Array.prototype.indexOf.apply(arguments[0],[arguments[0][i]]) !== Array.prototype.indexOf.apply(arguments[0],[arguments[0][j]])) {
FirstArray = arguments[0][i] - arguments[0][j];
if (FirstArray >= 0) {
SecondArray.push(FirstArray);
}
}
}
But is still not working, I tried the solution with to arguments, doesn't work either.
First and foremost avoid using Array as a variable name because for the most browser it will lead to unexpected behavior.
I think also you need to pass the two arrays in your function as parameters in order compare them.
And you don't need to find the index of element with index i, the i itself is an index.
Array.indexOf(Array[i]) === i
Here is an example of what you might need:
// it is important for the "array" value to start with lower case symbow, because JavaScript is case sensitive language and it already has object called "Array"
var array = [4, 6, 3, 56, 4];
function find(array)
{
// because we are surching for the minimum, the variable that will hold it needs to have the largest possible variable at the begining
var min = Number.MAX_VALUE;
for (var i = 0 ; i < array.length; i++)
{
for (var j=0 ; j < array.length; j++)
{
if (i != j)
{
var sum = array[i] - array[j];
// if it sum is greater than zero and it is the smallest sum so far we will save it in "min"
if (sum >= 0 && min > sum)
{
min = sum;
}
}
}
}
// retun the smallest sum we've encountered
return min;
}
console.log(find(array));
Can anyone explain the solution to me like a 6 year old? I haven't been able to make sense of the solutions. Maybe some code comments?
Thank you.
I've spent the last 2 hours on coderbyte trying to solve this one. Here's the question:
Have the function ArrayAdditionI(arr) take the array of numbers stored
in arr and return the string true if any combination of numbers in the
array can be added up to equal the largest number in the array,
otherwise return the string false. For example: if arr contains [4, 6,
23, 10, 1, 3] the output should return true because 4 + 6 + 10 + 3 =
23. The array will not be empty, will not contain all the same elements, and may contain negative numbers.
I've scoured the internet, read through a bunch of people's solutions from the people's answers on coderbyte itself, but without any comments I'm really struggling to figure out how this is done. I've started over countless times, so I'm not even sure if this last attempt is any better or not.
I understand that I'll need to loop through somehow and test every combination index 5, index 4, index 3, index 2, index 1, AND every combination of less than all of those (ie just index 5 and index 3). I just can't figure out how to do that. If I knew the list would always be an array of 5 numbers, and it required all 5, I would write 5 loops all equally nested inside of one big one, right? However, with the added complexity of not requiring all numbers and not knowing the length of the array for all cases, I am completely stumped. I tried using Math.floor(Math.random() * array.length); to generate a list of numbers... but that didnt work either.
function ArrayAdditionI(arr) {
var longest = arr.sort( function(a,b) { return a-b });
var longest = longest[longest.length - 1];
var sumArr = function (arrb) {
var sum = 0;
for (var z = 0; z < arrb.length; z++){
sum += arrb[z];
}
return sum;
};
for (var i = 0; i > arr.length; i++) {
for (var y = 0; y > arr.length; i++) {
testArr.push(arr[i]);
if (sumArr(testArr) === longest) {
return true;
}
testArr.push(... its 4am and I'm stumped!...)
}}
// code goes here
return false;
}
// keep this function call here
// to see how to enter arguments in JavaScript scroll down
ArrayAdditionI(readline());
A fairly simple to understand and common solution to the problem is as follows. It basically starts by looping forward through the array (loop i) by adding each subsequent number (loop j). If loop j finishes without a solution, loop k begins and removes each subsequent number. Then i increments and the loops start over.
function ArrayAdditionI(arr) {
arr.sort(function(a,b){return a - b})
var largest = arr.pop(); // Set largest to last (largest) array value
var sum = 0;
for (var i = 0; i < arr.length; i++){ // Start outer loop
sum += arr[i];
for (var j = 0; j < arr.length; j++){ // Start inner to begin sum
if (i != j) { // Ensure we don't add the same array index to itself
sum += arr[j];
console.log(sum);
if (sum == largest) {
return true;
}
}
}
for (var k = 0; k < arr.length; k++) { // If no match, start 2nd loop to re-iterate removing index values
if (i != k) {
sum -= arr[k];
console.log(sum);
if (sum == largest) {
return true;
}
}
}
sum = 0; // Reset sum for outer loop
}
return false;
}
The comment by thefourtheye basically told you the name of the problem and what to search for on google.
Solutions in java code would be the following...
1) find all subsets that sum to a particular value
This is the theory and pseudocode.
2) How to implement the Sum of Subsets problem in Java
Change the code to return what you wish if number of sets > 0 .
3) Modify GetAllSubsetByStack in below code to stop when a set is found:
https://codereview.stackexchange.com/questions/36214/find-all-subsets-of-an-int-array-whose-sums-equal-a-given-target
We did a similar recursion for a "MakeChange" algorithm at a meetup I went to last night. This morning I took a look at this problem with fresh eyes after not looking at it for a few weeks. Here's what I came up with.
Essentially: sort the array to biggest to smallest, shift that one off and declare it "goal", then recursively reduce an array by slicing it smaller and smaller each recurse, when the array reaches 0 length, randomize the original array and begin reducing again.
return true if goal = total (ie the reduce)
return false if ive randomized the array more than 1000 times.
function ArrayAdditionI(arr) {
var originalArr = arr.sort(function(a,b) {return b-a});
var goal = arr.shift();
var counter = 0;
function randomArray(array) {
for (var i = array.length - 1; i > 0; i -= 1){
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function recurse(arr) {
if (arr.length == 0){
counter++
var newArr = randomArray(originalArr);
return recurse(newArr);
} else {
var total = arr.reduce(function(a,b) {return a+b});
if (goal == total){
return true
} else if (counter == 1000) {
return false
} else {
newArr = arr.slice(1);
return recurse(newArr);
}
}
}
// code goes here
return recurse(originalArr);
}