I have two arrays and for each number in the first array I need to find the largest number from the second array that fits into that number and break the first number into its components. Since 25 from the second array is the largest number that fits into 80 of the first, I need to transform 80 into two numbers - 75, 5. Likewise for 6 and 5 the result should be 5, 1. So the end result should be an array [75, 5, 5, 1]
let arr = [80, 6]
let arr2 = [25, 5]
for (let x of arr) {
for (let y of arr2) {
if (x / y > 1 && x / y < 4) {
let mlt = Math.floor(x / y)
largestFit = y * mlt
arr.splice(arr.indexOf(x), 1, largestFit)
}
}
}
console.log(arr)
The code above gives [75, 5] so thought I could add one more splice operation to insert the remainders, but doing this arr.splice(arr.indexOf(x + 1), 0, x - largestFit) just crashes the code editor. Why isn't this working and what is the solution? Thank you.
It is not advised to splice an array that is being iterated, and it is the reason why your loop got suck sometimes.
Instead build a new array, so it doesn't affect the iteration on the input array.
If you first sort the second array in descending order, you can then find the first value in that array that fits the amount, and be sure it is the greatest one. For sorting numerically in descending order, you can use sort with a callback function.
Once you have found the value to subtract, you can use the remainder operator (%) to determine what is left over after this subtraction.
function breakDown(amounts, coins) {
// Get a sorted copy (descending) of denominations:
coins = [...coins].sort((a, b) => b - a);
const result = []; // The results are stored here
for (let amount of amounts) {
for (let coin of coins) {
if (coin <= amount) {
result.push(amount - amount % coin);
amount %= coin;
}
}
if (amount) result.push(amount); // remainder
}
return result;
}
// Example 1
console.log(breakDown([80, 6], [25, 5]));
// Example 2
console.log(breakDown([100, 90, 6], [100, 75, 15, 5, 1]));
Explanations
The coins are sorted in descending order so that when we search for a fitting coin from left to right, we can be sure that if we find one, it will be the greatest one that fits, not just any. So for instance, if our amount is 7 and we have coins 2 and 5, we don't want to use coin 2 just yet -- we want to use coin 5 first. So if we sort those coins into [5, 2], and then start looking for the first coin that is smaller than our amount, we will be sure to find 5 first. The result would not be as expected if we would have found 2 first.
We can calculate the remainder of a division with the % operator, and there is a shortcut for when we want to assign that remainder back to the amount: it is the %= operator. amount %= coin is short for amount = amount % coin.
When the inner loop completes, it might be that amount is not zero, i.e. there is still an amount that remains that cannot be consumed by any available coin. In that case we want to still have that remainder in the result array, so we push it.
Often, the amount will already be zero when the loop ends. This will be ensured when the smallest coin is the smallest unit of amount one can expect. For instance if the amount is expressed as an integer, and the smallest coin is 1, then there will never be any remainder left when the inner loop has completed. If however the smallest coin would be 2, and we are left with an a amount of 1, then there is no way to reduce that amount to zero, so after the loop ends, we could be stuck with that remainder. And so we have this code to deal with that:
if (amount) result.push(amount)
Floating point
Be careful with using non-integers: floating point arithmetic does not always lead to expected results, because numbers like 0.1 cannot be accurately represented in floating point. You can end up with a non-zero amount after the inner loop finishes, when zero would have been expected. That amount will be tiny like 1e-15, and really indicates there was such an inaccuracy at play.
When calculating with monetary amounts, it is common practice to do that in number of cents, so to make all calculations based on integers. This will give reliable results.
I found the issue. After the first splice() operation indexOf(x) was returning -1, since x's are being replaced, so the solution is to assign indexOf(x) to a variable and use that variable for both splice() operations.
let arr = [80, 6]
let arr2 = [25, 5]
for (let x of arr) {
for (let y of arr2) {
if (x / y > 1 && x / y < 4) {
let mlt = Math.floor(x / y)
largestFit = y * mlt
let idx = arr.indexOf(x)
arr.splice(idx, 1, largestFit)
arr.splice(idx + 1, 0, x - largestFit)
}
}
}
console.log(arr)
Related
I understand that this is more of a problem solving than a coding question as such, so my apologies if this post breaks any rules here, but does anyone have any idea how best to go about this?
I am trying to solve the problem, but there is a logical error in my code, or rather I have not considered all the conditions, tell me how to find it.
The problem: An adventurer found himself in a dungeon full of treasures. However, before entering he activated a trap, which in t minutes will flood the entire room.
You are given an array of chests, where chests[i] is the number of treasures in the chest. The explorer can either pick up treasure i, taking one minute, or move to the next chest (i+1), which also takes one minute. He starts at position zero, it is not necessary to reach the end of the array.
Determine the maximum amount of treasure the hero can collect. by writing function getResult(chests,t):Integer
Input:
chests - number of treasures in chests, 2<length(chests)<20, 0<chests[i]<100
t - number of minutes to flood, 0<t<20
Output:
Integer - maximum number of treasures collected
Example 1:
chests = [1, 4, 2] t = 3
getResult(chests, t) = 5 // In the first minute the hero collected treasure from the first chest,
in the second minute, he moved to the next chest, in the third minute, he gets the treasure from it
Example 2:
chests = [7, 8, 9] t = 2
getResult(chests, t) = 8 // In the first minute, the hero goes to the second chest and gets the treasure from it,
than taking the treasure in the first chest
below are my reasons, and code.
the horizontal side of the matrix is moves and captures. They don't differ, because it takes the same amount of time to move or capture an item.
1 unit per move or capture. The chests are arranged vertically, in order of increasing number of moves to the chest, so we can say
If n (number of chests)=4, the values in the chests are in order of distance of moves with the contents of 1, 4, 3, 5
It is possible to take any[j,i] chest in i moves. In 10 moves it is possible to take all items, the point is that the number of moves n for taking
chest is a triangular number, i.e. the sum of the first n natural numbers. The formula for calculating a triangular number is: 1/2 * n * (n+1)
We build a matrix, put the inputs [1, 4, 3, 5] there, and place all the sums of those there, too, as chests.
If one cell of the matrix contains more than 1 chest, we choose maximum.
all combinations without regard to direction, (i.e. 2+3=3+2 without regard to such permutations)
summary matrix: chests and their combinations and steps to get
1__2__3__4__5__6__7__8__9_10
first chest 1, | | | | | | | | |
second chest 0, 4, 5 | | | | | | |
third chest 0, 0, 3, 4, 7, 8, | | | |
fourth chest 0, 0, 0, 5, 6, 9,10, 9 12 13
there are combinations not included in the matrix,
i.e. 4c+1c,2c>4c+3 (throw out the equal in moves option 4+3 chest, this is not the maximum)
So, form a one-dimensional array to select the best (maximal) combinations for each move
maxs_in_onerow=[1,4,5,5,7,9,10,9,12,13]
count sum of elements up to t-1
compare with the element with the number t
ANSWER: sumofchests(0,t-1)>maxs_in_onerow(t) ? return sumofchests(0,t-1) : maxs_in_onerow(t)
// fill in the backpack, output the result
function getResult(chests, t) {
function transpose(a) { //helper func
// Calculate the width and height of the Array
let w = a.length || 0;
let h = a[0] instanceof Array ? a[0].length : 0;
// In case it is a zero matrix, no transpose routine needed.
if(h === 0 || w === 0) { return []; }
let i, j, t = [];
// Loop through every item in the outer array (height)
for(i=0; i<h; i++) {
// Insert a new row (array)
t[i] = [];
// Loop through every item per item in outer array (width)
for(j=0; j<w; j++) {
// Save transposed data.
t[i][j] = a[j][i];
}
}
return t;
}
function sumofsteps(c = chests) {
if (!Array.isArray(c)) c=Array.from({length:c})
return (c.length * (c.length + 1)) / 2;
}
function sumofchests(c = chests) {
return c.reduce((partialSum, a) => partialSum + a, 0);
}
const J = sumofsteps(chests);
const I = (chests.length);
// console.log(`${chests.length}, ${J}, ${I}`);
//create a matrix with the size of the number of chests
//for as many moves as it takes to get all the chests=J
let matrix = Array.from({ length: I }, () => new Array(J).fill(0));
let maxs_in_onerow = [];
// fill with values
let prevstepI = 0;
chests.forEach((element,index) => {
let cchests=chests.slice(0,index)
//the side of the matrix, the moves for moving and taking chests, grows like half a square
for (let i = prevstepI; i <=cchests.length; i++) {
// matrix side, chests,
// nothing before the diagonal, skip
if (i<index) continue
if (i===index) { //diagonal, minimum moves to take
prevstepI=i
matrix[index][i]=element
}
let _x=0
while (_x<i) {
matrix[_x].forEach((el , ind ) => { /* ... */
if (el > 0) {matrix[index][i+ind+1]=element + el}
})
//create combinations of chests
_x+=1
if (_x===i) break
}
}
});
// form maxs_in_onerow=[1,4,5,5,7,9,10,9,12,13]
let jmartix=[]
jmartix=transpose(matrix)
for (let j = 0; j < J; j++) {
let cur=Math.max.apply(null, jmartix[j])
maxs_in_onerow.push(cur);
}
// fill in the backpack, output the result
let res;
if (t === 1) res = chests[0];
if (t >= J) res = sumofchests(chests);
if (t<J) {
let res1=Math.max.apply(null,maxs_in_onerow.slice(0,t))
let res2=sumofchests(maxs_in_onerow.slice(0,t-1))
res = res1>res2 ? res1 : res2
}
// console.log( `${matrix}, ${totalsteps()}, t: ${t}, maxs: ${maxs_in_onerow}, res: ${res} ` );
return res;
}
console.log(` input: [1, 4, 2], 3 \n response: ${getResult([1, 4, 2], 3)}`);
console.log(` input: [7, 8, 9], 2 \n response: ${getResult([7, 8, 9], 2)}`);
My sleep-deprived brain is not up trying to interpret your code or your reasoning. Instead, here's a simple recursive solution:
const maxTreasure = ([c, ...cs], t) =>
t <= 0 || c == undefined
? 0
: c == 0
? maxTreasure (cs, t - 1)
: Math. max (c + maxTreasure ([0, ...cs], t - 1), maxTreasure (cs, t - 1) )
console .log (`maxTreasure ([1, 4, 2], 3) //=> ${maxTreasure ([1, 4, 2], 3)}`);
console .log (`maxTreasure ([7, 8, 9], 2) //=> ${maxTreasure ([7, 8, 9], 2)}`);
We check whether the time has run out or if there are no more chests found, and if so, simply return 0. If the first chest is empty, we have no reasonable alternative than to move on to the next one, so we reduce the time by one and recur with the remaining chests. Otherwise we have to choose the better of two possibilities: taking the current chests' treasures or moving on to the next one. We use Math .max to select one of these, and calculate them by recursion. In one case, we include the current chest (c) and recur with a list of chests that replaces the current chest's value with zero. In the other, we move on to the remaining chests. In either case, we reduce the time by one.
So we have base cases, and three potential recursive calls. In each of those calls, we're reducing the time by 1, so we will eventually reach the case t <= 0.
That same foggy brains isn't going to do the analysis of time complexity here. I wouldn't be surprised if this is horribly inefficient; it's likely of exponential complexity in the number of chests. But it's simple and a good start at thinking of the problem logically. If it turns out too inefficient for real world use (ha!) we can come back at a solution using bottom-up dynamic programming... and that may be what you're attempting.
But I would always start simply, and often recursion is simplest.
For clarity sake, this is what I mean. I want to look for the two least numbers in an array(sorted) that will generate a particular number. The steps go thus:
Loop through the array and each time set a current value that other
numbers will be deducted from.
Keep doing that till you find the numbers that match the problem and return them.
Example. I need two numbers that when subtracted from the array will give a result of 2.
let givenArray = [1, 4, 8, 10];
The subtraction should go thus: 4 - 1 = 3(doesn't match); //continue
8 - 4 = 1(doesn't match);// continue
8 - 1 = 7(doesn't match); //continue
10 - 8 = 2(match found); //stop and return 8, 10.
NOTE: This same array may contain a 6 and 8 or 8 and 10 that will both yield 2 but 6 and 8 should be returned instead. The way the array is generated isn't of much importance.
P.S: I eventually solved it yesterday but I won't mind other ideas on how to go about it.
This solution takes the advantage of a hash table and uses a single loop approach for getting the two values out of an array to balance two values.
First, take the absolute delta of the two values of arrayA and take this for getting the values out of the greater array.
Then reduce the greater array arrayB by checking if the needed value exist and if the sum is smaller then a previously found set.
The argument for checking is build out of the absolute delta of delta and v, the actual value of the array or by taking the sum of delta and v.
The last point, and to make this all working, the actual value v is included into the hash table, for a later look up.
The result is either an array of two values, which balance the other two values or undefined, if no values are found.
var arrayA = [3, 5],
arrayB = [2, 9, 5, 4],
delta = Math.abs(arrayA[0] - arrayA[1]),
values = {},
result = arrayB.reduce((r, v) => {
function check(w) {
if (!values[w] || r && r[0] + r[1] < v + w) return;
r = [w, v];
}
check(Math.abs(delta - v));
check(delta + v);
values[v] = true;
return r;
}, undefined);
console.log(result);
I'm not sure I understood correctly, but perhaps this is what you need:
let result = arrayA[1] - arrayA[0];
let i, j;
for (i = arrayB.length - 1; i >= 1; i--) { // Set the first value
for (j = arrayB.length - 1; j >= 1; j--) { // Set the second value
if (i !== j) {
if (
arrayB[i] - arrayB[j] === result // Check substraction
|| arrayB[i] + arrayB[j] === result // Check addition
) return [arrayB[i], arrayB[j]];
}
}
}
lets say I have an array with different item-prices.
var myItemsEuro = [0.34, 0.11, 0.5, 0.33, 0.05, 0.13, 0.23, 3.22, 1.94]
I would like to have function like this:
function getTradeItems(0.89) { //The price of the item I want to buy
//Calculate, which of my items should be used to buy the item for 0.89€
return [0, 3, 6] //The position of my items in the array, which added together equal 0.90€
}
To clear things up:
I have a box of items with pricetags on them (myItemsEuro). I want to buy an item, using my items as a payment. The other party will accept my trade, if I overpay with atleast one cent.
The function should work, so i can pass the other guy's price to it (0.89 for example) and it returns, which items I will have to give away. The combination of these items must be above 0.89 cents (atleast 0.9), but should be as low as possible!
I am quite new to JS, and I was thinking about calculating every single combination of my items and then use the one that has the lowest difference to the buyprice. This seems really complicated to me and I don't even know how I would make it calculate every single combination and also save which items were used for the calculation.
Is there any way to achieve this a bit more efficient? I don't really expect any perfectly working code here, a little bit of help to get into the right direction would also be nice.
Any help is appreciated! :)
Edit:
Sorry for missing my own attempt. It's just that I have no idea how I should solve this at all. And no - not homework - this is supposed to be part of a chromeextension I am working on!
var myItemsEuro = [0.34, 0.11, 0.5, 0.33, 0.05, 0.13, 0.23, 3.22, 1.94]
function getTradeItems(marketPrice) {
var result = 0;
var positions = [];
for(i = 0; i < myItemsEuro.length; i++) {
result += myItemsEuro[i]; //add numbers from the array
positions.push(i); //save the used numbers position
if(result > marketPrice) { //if result is greater than marketPrice...
console.log(result)
console.log(positions)
return positions; //return positions in the array
}
}
}
getTradeItems(1.31);
Edit:
Sorting the array and then adding up numbers doesn't give a solution.
var x = 1.18;
//Sorted by numbers
var myItemsEuro = [0.05, 0.11, 0.13, 0.20, 0.35, 0.50, 0.60, 0.69, 0.75];
//Add together and stop when sum > x:
0.05 + 0.11 + 0.13 + 0.20 + 0.35 + 0.50 = 1.34
//Best solution would be adding [6] and [8] from the array
0.50 + 0.69 = 1.19
You could use a brute force approach and test all combinations of the items if they are greater or equal of the target.
The base consideration is to take a counter from zero up to 2values.length and check if the actual 2index is part of the counter with a bitwise AND &. If so, take the value from the index and put it into the parts array.
Then build the sum of the parts and check if sum is greater or equal of target and possibly smaller than sum in result array, then move the result to the result array. If sum is equal to result[0].sum, then push the actual parts and sum to the result.
This proposal works with unsorted values, but could be more efficient, if the values which are greater then the target value are not included in the array to work on.
Another draw back is the fact, that bitwise arithmetic works only with 32 bit, that means arrays with more items than 32 are not possible use.
var values = [0.34, 0.11, 0.5, 0.33, 0.05, 0.13, 0.23, 3.22, 1.94],
target = 0.90,
i,
l = 1 << values.length,
result = [],
parts,
sum;
for (i = 0; i < l; i++) {
parts = values.filter(function (_, j) {
return i & 1 << j;
});
sum = parts.reduce(function (a, b) { return a + b; }, 0);
if (sum >= target) {
if (!result.length || sum < result[0].sum) {
result = [{ parts: parts, sum: sum }];
continue;
}
if (sum === result[0].sum) {
result.push({ parts: parts, sum: sum });
}
}
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would suggest some measures to take:
Fractional numbers can cause floating point precision issues, so it is better to first convert every value to an integer (i.e. value in cents)
Perform a recursive search, where at each recursion level you'll decide whether or not to take the item at the corresponding index.
Think of situations where you might have multiple solutions: maybe in those cases you want to give precedence to solutions that use fewer items. So you would need to keep track of the number of items selected.
The solution I propose here will backtrack as soon as it is clear there is no sense in continuing adding items. There are at least two situations where you can draw this conclusion (of stopping the recursive search):
When the sum of the values selected so far is already greater than the target value, then there is no sense in adding more items (via recursion)
If after adding an item at position i, it becomes clear that adding all of the remaining items (via recursion) leads to a sum that is lower than the target, then it makes no sense to not select the item at position i, and repeat the recursive search, as that certainly will not reach the target value either.
Here is the suggested code:
function getTradeItems(target, items) {
var best = -1e20, // should be maximised up to -1 if possible
bestTaken = [], // indices of the best selection
bestCount = 0, // number of selected items in best solution
// Multiply all amounts by 100 to avoid floating point inaccuracies:
cents = items.map( euro => Math.round(euro * 100) );
function recurse(target, i, count) {
if (target < 0) { // Found potential solution
// Backtrack if this is not better than the best solution
// found so far. If a tie, then minimise the number of selected items
if (target < best ||
target === best && count > bestCount) return false;
best = target;
bestTaken = [];
bestCount = count;
return true;
}
// Give up when there's not enough item value available
if (i >= cents.length) return null;
// Include the item at index i:
var res1 = recurse(target - cents[i], i+1, count+1);
// If we could not reach the target, don't lose time retrying
// without this item:
if (res1 === null) return null;
// Exclude the item at index i:
var res0 = recurse(target, i+1, count);
// If neither led to a solution...
if (!res0 && !res1) return false;
// If the best was to include the item, remember that item
if (!res0) bestTaken.push(i);
return true;
}
recurse(Math.round(target * 100), 0);
return bestTaken.reverse();
}
// Sample input
var myItemsEuro = [0.05, 0.11, 0.13, 0.20, 0.35, 0.50, 0.60, 0.69, 0.75];
var x = 1.18
// Get the best item selection
var result = getTradeItems(x, myItemsEuro);
// Output result
console.log('Selected: ', result.join()); // 5, 7
// Show corresponding sum: (1.19)
console.log('Sum: ', result.reduce( (sum, i) => sum + myItemsEuro[i], 0).toFixed(2));
I came across the algorithm below for shuffling an array in Javascript. It seems to differ from the Fisher–Yates shuffle in that the range of available "swaps" increases with the for-loop counter. This appears to be the opposite of how the Fisher-Yates version behaves. I'm curious as to whether this is a valid algorithm. Is it the Fisher-Yates in disguise? Is it biased?
If anyone could provide some code to test the frequency of the permutations it generates that would be a bonus.
<script>
var shuffle = function (myArray) {
var random = 0;
var temp = 0;
console.log(myArray);
for (i = 1; i < myArray.length; i++) {
random = Math.round(Math.random() * i);
console.log(random + '\n');
temp = myArray[i];
myArray[i] = myArray[random];
myArray[random] = temp;
console.log(myArray);
}
return myArray;
}
var arr = [1, 2, 3, 4];
shuffle(arr);
</script>
No, it's not a fair shuffle.
Math.random() * i is a uniform random floating point value between 0 and i, but Math.round(Math.random() * i) does not pick integers between 0 and i equally. For example, when i is 2, the values in the range [0, 0.5) round to 0, values in the range [0.5, 1.5) round to 1, and values in the range (1.5, 2) round to 2. That means instead of picking 0, 1 and 2 equally often, 1 is picked with probability 0.5, and 0 and 2 are picked with probability 0.25 each.
Math.floor(Math.random * (i + 1)) would be correct.
You can verify this statistically: shuffle the array [0, 1, 2] 10000 times and see how often 2 remains at the end of the array. It should be around 3333, but because of the bias it'll be more like 2500.
Other than that, the algorithm is correct and could be described as a Fisher-Yates in reverse. You can prove it correct by induction. The base case of n=1 is trivial. The induction step is also relatively easy: if you've got a uniformly random permutation of n items, and then insert the n+1'th item at a uniformly random index from 0 to n+1, then you've got a random permutation of n+1 items.
I am doing a challenge on Coderbyte and I would be grateful for any advice on my question:
The challenge given to me:
"Using the JavaScript language, 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. "
The way I attempted to solve it: http://jsfiddle.net/reLsg0fg/
function ArrayAdditionI(arr){
var newArr=arr.sort(); // sorted from smallest to largest.
var largestNum=newArr.slice(-1); // Gets the last number, which would be the largest.
var loopArr=arr.sort().pop(); // Takes out the largest number for adding later.
var result=0;
for(var i=0; i<loopArr.length; i++){ // loops through all numbers.
if(result/largestNum !== 1){ //when you divide a number by itself it will be 1.
result+=loopArr[i]; // keep adding each number until get largest number.
}else if(result === largestNum){
return true;
}
}
return false;
}
// TESTS
console.log("-----");
console.log(ArrayAdditionI([4,6,23,10,1,3]));
console.log(ArrayAdditionI([5,7,16,1,2]));
console.log(ArrayAdditionI([3,5,-1,8,12]));
I'm supposed to get true, false, true. But I get false, false, false as if something is wrong within my loop. JSFiddle: http://jsfiddle.net/reLsg0fg/
I would appreciate any suggestions. Thank you ^^
Sort Array using
arr.sort(function (a, b) { return a - b })
I have tried to solve this problem with a for loop but I missed the fact that the challenge
is not asking that all numbers need to add up to equal the largest num, but it is also possible to
add up to the largest num if we take some numbers out. Thus I decided to solve with recursion.
Tips:
* The Math.max.apply() method takes an array and returns the largest number. Note that it usually works on strings as Math.max().
* the sort() method can take a parameter to further expand it's purpose. Usually it only
sorts strings, but to sort numbers we include a function that finds which number is bigger.
* First get the largest number.
* Sort the array and remove the largest number to be used for recursion later.
* Create a recursion function that checks if the numbers add up to the largest number, and if not, check that if some numbers in array are subtracted from the largest num they are equal to the largest number.
function ArrayAdditionI(array){
var largestNum = Math.max.apply(0, array); // gets the largest number in array.
array.sort(function(a,b){ return a-b;}).pop(); // sorts array and removes last(largest) number.
function recursionCheck(arr, sum){
// the base case when array empty.
if(arr.length === 0){
return sum === 0;
}
var arrBeginNum=arr[0];
// for every recursion take away one number(the first one in this case).
arr = arr.slice(1);
// first check if numbers sum up to largest num if not, check if removing numbers adds up to largest num.
return recursionCheck(arr, sum) || recursionCheck(arr, sum - arrBeginNum);
}
// recursion needs to be called for it to start.
return recursionCheck(array, largestNum);
}
// TESTS
console.log("-----");
console.log(ArrayAdditionI([1,2,3,5,4])); ==> true
console.log(ArrayAdditionI([21,10,12,9,2])); ==> true
console.log(ArrayAdditionI([4,6,23,10,1,3])); ===> true
console.log(ArrayAdditionI([5,7,16,1,2])); ===> false
console.log(ArrayAdditionI([3,5,-1,8,12])); ===> true
This might not be the complete solution yet, but here are the JavaScript-Problems:
largestNum was an array in you algorithm
.sort() was not working
function ArrayAdditionI(arr){
var largestNum = Math.max.apply(0, arr); // Gets the last number, which would be the largest.
arr.sort(function(a, b){return a-b})
arr.pop(); // Takes out the largest number for adding later.
var result=0;
Also use if(result !== largestNum) {, Division is expensive and might have unexpected results with floating-point numbers.
Thats it for your JavaScript. But I am pretty sure the Algorithm is wrong - but I think this is up to you
Note that the example [4, 6, 23, 10, 1, 3] => 4 + 6 + 10 + 3 = 23 is not just adding up the lowest to the biggest value to try and match it.
A possible example of a solution for the problem.
How this works:
First sort all items descending
Shift the first element to largest
Call the recursive function y with the reduced array, the largest value and a variable which holds an empty array for the successfully added items.
The recursive function works basically in two parts
Test if the remaining sum is zero, if so the result is achieved and return true, which finished the function.
If not iterate through the array and
Make a copy from the array
Get the value from the position with splice
Test, if the value is smaller or equal the remaining sum and the result of the call of y with the shorted array, sum minus value and a new array with the used items and the acual item.
If true return true and finish the function.
If not finished before return false.
function x(array) {
function y(a, s, result) {
var aa, i, v;
if (s === 0) {
document.write('<pre>result: ' + JSON.stringify(result, 0, 4) + '</pre>');
return true;
}
for (i = 0; i < a.length; i++) {
aa = a.slice();
v = aa.splice(i, 1)[0];
if (v <= s && y(aa, s - v, result.concat(v))) {
return true;
}
}
return false;
}
var largest,
r = [];
array.sort(function (a, b) { return b - a; });
largest = array.shift();
document.write('largest value: ' + largest + '<br>');
return y(array, largest, r);
}
document.write(x([4, 6, 23, 10, 1, 3]) + '<hr>');
document.write(x([5, 7, 16, 1, 2]) + '<hr>');
document.write(x([3, 5, -1, 8, 12]));
Thanks #mar
Here is a version in Kotlin if someone needs
private fun returnResult(arr: Array<Int>): Boolean {
arr.sort()
val largestNumber = arr.last()
val arrWithoutLargest = arr.dropLast(1).toTypedArray()
return recursionCheck(arrWithoutLargest, largestNumber)
}
private fun recursionCheck(arr: Array<Int>, sum:Int): Boolean {
if (arr.isEmpty()) return sum == 0
val arrBeginNum = arr[0]
val arr2 = arr.drop(1).toTypedArray()
return recursionCheck(arr2, sum) || recursionCheck(arr2, sum - arrBeginNum)
}