Codility Tape Equilibrium Getting Zero on Some Cases

Tape Equilibrium Codility Training: Why Does It Return 0?

Change initialization code to

int smallest = 0;
int left = 0;
int right = 0;

And everything should be ok. The reason is that you've got undefined behavior. Also the reason is not in the

if (N == 1) return 0;

You can add something like

printf("%d - %d\n", P, smallest);

to the end of the for loop and see the result at every step. Also you would see the warnings from the compiler

Compiler output:

func.c: In function 'solution':

func.c:19:14: warning: 'left' may be used uninitialized in this function [-Wmaybe-uninitialized]

     left += val;
^

func.c:13:15: warning: 'right' may be used uninitialized in
this function [-Wmaybe-uninitialized]

     right += A[i];
^

Tape-Equilibrium Codility Training

Your solution is already O(N). You need to remove the abs from sumleft and sumright.

if (Math.abs( sumleft - sumright ) < ans)
{
ans = Math.abs( sumleft - sumright );
}

Also before the second for loop,

ans =Math.abs( sumleft - sumright );

It should work.

TapeEquilibrium, Solution Failing Two Edge Cases

Any integer P, such that 0 < P < N, splits this tape into two non-empty parts

The "non-empty" is crucial here. If you would try printing both parts in the second loop you would see that in the last iteration the second part is empty.

All you need to do is skip the last iteration in you loop:

public int solution(int[] A) {
int pval = Integer.MAX_VALUE;
int sum = 0;
int pone = 0;
int ptwo = 0;
int currdiff = 0;
for(int i = 0; i<A.length; i++ ){
sum += A[i];
}

ptwo = sum;
for(int j = 0; j< A.length-1; j++){ //<- notice -1 here
pone += A[j];
ptwo -= A[j];
currdiff = Math.abs(ptwo - pone);
if(currdiff < pval)
pval = currdiff;
}
return pval;
}

Issues in my Codility example test - Find the first missing positive number in an array

You can simplify the problem down by recognizing that you just need to keep track of the integers you've seen in array that your given. You also need to account for edge cases for when the array is empty or the value you get would be greater than your max allowed value. Finally, you need to ensure O(n) complexity, you can't keep looping for every value you come across. This is where the boolean array comes in handy. See below -

public static int solution(int[] A) 
{
int min = 1;
int max = 100000;
boolean[] vals = new boolean[max+1];

if(A.length == 0)
return min;

//mark the vals array with the integers we have seen in the A[]
for(int i = 0; i < A.length; i++)
{
if(A[i] < max + 1)
vals[A[i]] = true;
}

//start at our min val and loop until we come across a value we have not seen in A[]
for (int i = 1; i < max; i++)
{
if(vals[i] && min == i)
min++;
else if(!vals[i])
break;
}

if(min > max)
return max;

return min;
}

The worst case for looping is A.length + max which is O(N)

How Codility calculates the complexity? Example: Tape-Equilibrium Codility Training

Let f and g be functions.

The Big-O notation f in O(g) means that you can find a constant number c such that f(n) ≤ c⋅g(n). So if your algorithm has complexity 2N (or XN for a constant X) this is in O(N) due to c = 2 (or c = X) holds 2N ≤ c⋅N = 2⋅N (or XN ≤ c⋅N = X⋅N).

TapeEquilibrium task from Codility, failing to pass 100% tests, performance and correctness (76% total score)

So, I ended up looking at the solution of yusheng123, which is in python, but his code is so easy to understand.
Now I realize I was doing things so badly: I was trying to debug or fix a solution that was poorly thought.
The solution by this guy, was somewhat similar to the one I followed at last, but with huge differences.
I was comparing the first and the last element of the array, and then adding numbers to the head, or the tail (accumulators), depending on whether the difference between those two would be smaller, was awful: too complicated, too focused on the structure received, and most importantly, not abstracting myself from the array itself (the partitions!) to find a proper way to solve the problem: the fact that you have to find those partitions, doesn't mean you have to actually kinda create your own two arrays, even though I was accumulating from both ends, I now see it is not decoupled at all from the problem itself, I was not creating the arrays per se, but the procedure to accomplish that, would be the same followed by my moronic approach.

If, in contrast, I emphasize in the difference there is between the head (being only the first element), and the tail (being the sum of all the other elements of the array), then I'm in a higher abstraction level, and the fact that I can just iterate through the array from beginning to end, and get to the solution, says a lot in juxtaposition.
So, in the future, when I will see myself doing something similar to what I did, I'll say to me: "How can you follow a simpler plan (a simpler iteration in this particular case) and still content yourself by following the idea you thought of but not pushing it too hard (as I did in this case)? Don't throw your idea to the garbage yet, discard your complicated code though, make it simpler, and try to isolate the, maybe plausible idea from the implementation for now, until you find something that clicks in your mind, since many rules, and questions have to be asked to accomplish what you are trying to." Excuse me if I use this answer to speak to my future self and not talk about the code itself entirely.

Continuing with the brilliant solution I found online, the strategy (of setting the head as the first element of the array, and the tail as the sum of the rest of the array), would continue by setting as the initial value of the smallest difference, to the one there is between the head and the sum of the rest of the elements, and then you just iterate through the array, and add the current element to the head accumulator, and decrease that value from the rest (tail accumulator), while checking that if the new difference between those two is smaller than the one saved in the beginning, then it should be override by the new value (which is what we wanted to find in the first place, this is the value that the function will return at the end -or at the beginning if there's 0, 1 or 2 elements in the array-).

There are no wagons adding to locomotives (I see now how stupid I must sounded in your own voices, subvocalizing what I wrote). There is no need for such silly analogies in this simple problem, with such an easy, and elegant solution. Right there: I will be able to spot that I'm doing something wrong in the future in a similar situation.

There is so much order in this approach. A higher level of abstraction. If there were bugs they would be easy to find, and so on. This is "my" final code.

public int solution(int[] A)
{
int head = A[0], tail = A.Sum() - head;
int min_diff = Math.Abs(head - tail);
for (int i = 1; i < A.Length; i++)
{
if (Math.Abs(head - tail) < min_diff)
min_diff = Math.Abs(head - tail);
head += A[i];
tail -= A[i];
}
return min_diff;
}

Of course, the final score of this solution is 100%. Just so beautiful and simple.



Related Topics



Leave a reply



Submit