3
I was solving a problem that was basically:
A prisoner was sentenced to perform a job where he was to break all the stones that were provided to him, but he could not use any tool for it. To accomplish the task, he decided that the best option would be to break two stones beating each other, until only one stone or none remains. In addition, the prisoner decided to break the biggest stones first, therefore in descending order.
If the prisoner hits two stones that are the same size, both stones are broken, and if one stone is smaller than the other, the size of the larger stone is reduced by the size of the smaller stone (e.g., 6-3 = 3).
Given the information, write a function that returns the size of the last broken stone by the prisoner, or 0 if there are no remaining stones.
That said, the problem provides an amount of test cases to validate the solution.
As an example, a test-case provides the array [4, 2, 3, 5]
which, when ordered, would result in the vector [2, 3, 4, 5]
and would have the following sequence of calculations:
5 - 4 = 1
1 - 3 = 2 (a pedra 3 reduz seu tamanho em 1 unidade)
2 - 2 = 0
Portanto, resultado final: 0
Another example, an array [10, 40, 20, 30, 35, 70]
would be ordered to [10, 20, 30, 35, 40, 70]
and would have the following stages:
70 - 40 = 30
30 - 35 = -5 (portanto, 5)
5 - 30 = -25 (portanto, 25)
25 - 20 = 5
5 - 10 = -5 (portanto, 5)
Resultado final: 5
The function created to solve the problem was:
const lastStoneWeight = arr => {
arr = arr.sort(compareValues);
let current;
return arr.reduceRight((sum = 0, value) => {
current = sum - value;
return current < 0 ? -current : current;
});
};
const compareValues = (a, b) => a < b ? -1 : a > b ? 1 : 0;
This function worked for some of the test cases (as mentioned above), but it did not work for others, as one that provides the array:
[
32,
46188086,
339992587,
742976890,
801915058,
393898202,
717833291,
843435009,
361066046,
884145908,
668431192,
586679703,
792103686,
85425451,
246993674,
134274127,
586374055,
923288873,
292845117,
399188845,
842456591,
410257930,
333998862,
16561419,
624279391,
459765367,
969764608,
508221973,
82956997,
437034793,
553121267,
554066040,
199416087
];
The result (according to the test site) is 64 thousand and few (I do not remember the exact amount), while I reached 10556317.
I imagined that maybe my approach using reduce was not the correct one, so I implemented the function differently, having the same result:
function lastStoneWeight(arr) {
arr = arr.sort(compareValues);
let current;
while (arr.length > 1) {
current = arr[arr.length - 1] - arr[arr.length - 2];
arr[arr.length - 2] = current < 0 ? -current : current;
arr.pop();
}
return arr[0];
};
Would it be possible to explain why the correct solution is not being found? Which edge-case I could not approach with the solutions presented?
EDIT: An alternative version of the compareValues function:
function compareValues(a, b) {
if (a < b) return -1
if (a > b) return 1
return 0
}
It is a subtraction problem and subtraction is not a commutative operation. Ex: 7 - 3 = 4 however 3 - 7 = -4
arr = arr.sort(compareValues);
you change the order of the terms by generating a new sequence operations resulting in a different value than intended.– Augusto Vasques
Ordering is a requirement of the problem, the stones must be in an order where the larger ones must be broken first. About subtraction not be cumulative operation: Exactly why I introduced the fragment "Return Current < 0 ? -Current : Current;", since 7 -3 is the same as - (3 - 7)
– Marcos de Andrade
The first example "[2, 3, 4, 5]" the final result would not be "0"? Ex: (5-4) => (1 - 3) => (2 - 2) => 0 , can you tell the exact value of the third case (where the array has 33 elements)? I tested here and for "[2,.
– RDyego
It’s true, sorry, I ended up putting the example wrong (I’m editing the text to make this change, thank you!). The example of the problem was [3, 4, 5] (which resulted in 2), I tested with [2, 3, 4, 5] (the platform enabled Custom Test Cases by the user) and ended up exemplifying erroneously. I no longer have access to the problem but, as I had said in the description, the answer was around 64,000. And I came to the same result as you, which left me stuck.
– Marcos de Andrade
Milestones, what is the value of the function
compareValues
? I could edit the answer by including it in the code? :)– Luiz Felipe
compareValues is an Anonymous Function. The native Array.Sort function requires a comparative function (between two values) to apply between all values of an array. I used the new ES5 (Arrow Functions) syntax to omit Return, so maybe it’s not so clear. I will make an Edit with a previous syntax version of the same function
– Marcos de Andrade
I do not believe that this function is the problem, since the values were correctly ordered in all the tested examples. In addition, this function is described in the Mozilla MDN Web Docs documentation (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)
– Marcos de Andrade
Yeah, I’m aware of that. I just wanted you to put in the variable so I could run my tests. Anyway. I implemented a new function from scratch, and the result of the last test-case returned
659043
. That one output is correct? Where can I check the test cases?– Luiz Felipe
Yes, that is the correct output! Unfortunately the test-cases were only available on the platform (Hacker Rank) through a private access by email (single use, therefore, I no longer have access). The test was applied to know the knowledge base of developers who will participate in a Meetup / hands-on of a company in my city, so they can shape the content so that participants have a better experience
– Marcos de Andrade
Honestly, I performed this question on Stack Overflow because I would like to understand why I couldn’t solve the problem, purely for personal improvement, and I appreciate your help so far :)
– Marcos de Andrade
As I said above, I have already solved the problem with a new function. I’m still trying to figure out why yours works on some and goes wrong on others...
– Luiz Felipe