In this post I am going to discuss the solution for another great Codility problem.
Because of the copyrights I can't paste the problem description here so to view the problem click here.
As you may know most of the Codility problems are tricky and when Codility marks it as hard you should realize that you are going to squeeze your mind to get it resolved so I really envy those who could solve this issue from the first time in less than 30 mins. sometimes I really wish to contact any of them to see how brilliant they are, However lets start thinking in this problem and how to resolve it.
I am going briefly summarize how I think in this problem and how I resolved it.
first imagine you have this array
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
So I am going to get the position of the first ZERO ( which meets the requirement of the tourist to enjoy swimming in the sea), also I am going to get the position of the last ONE.
{1, 1, 0, 1, 0, 0, 1, 1,0,0}
In our example the position of the first ZERO is 2 and the position of the last ONE is 7.
Now lets get the longest sea trip that starts from the first zero and ends with zero. ( it should end with Zero even if adding ones wont make it fail).
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
Now we realized that the tourist have chance to spend the vacation the way he wants ( first part on the sea and the second part hiking in the mountain)
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
But our tourist here is pretty greedy he is looking for the longest vacation so we should try to expand the vacation as much as we can.
it can be done by iterating on the vacation from the last day to the start day and see if we can add hiking days to the second part without making the sea trip fails also we should add hiking days from the first part to the second part IF AND ONLY IF it will let the second part eligible to get more swim days from the rest of the reaming available days.
In our example we can't add more hiking days from the first part to the second part because it will lead that the second part of the vacation won't meet the criteria so the whole vacation will fail but the second part already eligible to add more days from the reaming days on its right.
so we can add one more day from its right
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
lets get to the first part of the vacation. the question ?? is it eligible to add more days from its left ? the answer simply yes so we should calculate how many days we should add from left ( expand the first part to left).
in our example we can add one more day from the left.
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
Now we got the longest possible vacation.
lets move to translating the description above to a java code.
Because of the copyrights I can't paste the problem description here so to view the problem click here.
As you may know most of the Codility problems are tricky and when Codility marks it as hard you should realize that you are going to squeeze your mind to get it resolved so I really envy those who could solve this issue from the first time in less than 30 mins. sometimes I really wish to contact any of them to see how brilliant they are, However lets start thinking in this problem and how to resolve it.
I am going briefly summarize how I think in this problem and how I resolved it.
first imagine you have this array
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
So I am going to get the position of the first ZERO ( which meets the requirement of the tourist to enjoy swimming in the sea), also I am going to get the position of the last ONE.
{1, 1, 0, 1, 0, 0, 1, 1,0,0}
In our example the position of the first ZERO is 2 and the position of the last ONE is 7.
Now lets get the longest sea trip that starts from the first zero and ends with zero. ( it should end with Zero even if adding ones wont make it fail).
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
Now we realized that the tourist have chance to spend the vacation the way he wants ( first part on the sea and the second part hiking in the mountain)
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
But our tourist here is pretty greedy he is looking for the longest vacation so we should try to expand the vacation as much as we can.
it can be done by iterating on the vacation from the last day to the start day and see if we can add hiking days to the second part without making the sea trip fails also we should add hiking days from the first part to the second part IF AND ONLY IF it will let the second part eligible to get more swim days from the rest of the reaming available days.
In our example we can't add more hiking days from the first part to the second part because it will lead that the second part of the vacation won't meet the criteria so the whole vacation will fail but the second part already eligible to add more days from the reaming days on its right.
so we can add one more day from its right
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
lets get to the first part of the vacation. the question ?? is it eligible to add more days from its left ? the answer simply yes so we should calculate how many days we should add from left ( expand the first part to left).
in our example we can add one more day from the left.
{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}
Now we got the longest possible vacation.
lets move to translating the description above to a java code.
package trekandswim; import java.util.Arrays; /** * * @author ahmad */ public class TrekAndSwim { public static void main(String[] args) { // TODO code application logic here TrekAndSwim tr = new TrekAndSwim(); int A[]; int result = 0; //////////Test the the results A = new int[]{1, 1, 0, 1, 0, 0, 1, 1, 0, 0}; result = tr.solution(A); System.out.println("==========="); System.out.println("The Result is " + result); System.out.println("****************************************"); } public int solution(int[] A) { int firstzero = -1; int lastone = -1; int seaDaysCount = 0; int seaEndIndex = 0; int seaArraySize = 0; int mountainStartIndex = 0; /////get the first zero and last one for (int i = 0; i < A.length; i++) { if (firstzero == -1 && A[i] == 0) { firstzero = i; } if (A[i] == 1) { lastone = i; } } // return 0 if no days for swim or no days for hike or no no hike day after a swim day if (firstzero == -1 || lastone == -1 || firstzero >= lastone) { return 0; } //get the longest sea trip that ends with ZERO int totalNumOfZeros = 0; for (int i = firstzero; i <= lastone; i++) { if (i == firstzero) { seaEndIndex = i; } if (A[i] == 0) { totalNumOfZeros++; } if (A[i] == 0&&seaTripNotFail(i - firstzero + 1, totalNumOfZeros)) { seaDaysCount = totalNumOfZeros; seaEndIndex = i; } } /// get the sea trip size seaArraySize = seaEndIndex - firstzero + 1; if (mountainStartIndex - seaEndIndex > 1) { return 0; } int startItrator = lastone; int tempones = 0; int tempZeros = 0; int tempEffectiveZeros = 0; int extraDays = 0; //check the possiblity of expanding the second part to the right by either adding more hike days from the first part or if the second part already adds elgiable to add more sea days from its right while (startItrator > firstzero) { if (extraDays + lastone >= A.length-1) { break; } if (startItrator > seaEndIndex) { if (A[startItrator] == 1) { tempones++; int newExtraDays = getExtraDays(tempones, tempZeros); if (newExtraDays > extraDays) { extraDays = newExtraDays; } } else if (A[startItrator] == 0) { tempZeros++; } } else { if (A[startItrator] == 1) { tempones++; int newExtraDays = getExtraDays(tempones, tempZeros); if (newExtraDays > extraDays) { int newArraySize = startItrator - firstzero + 1; if (seaTripNotFail(newArraySize, seaDaysCount - tempEffectiveZeros)) { extraDays = newExtraDays; seaArraySize=newArraySize; seaEndIndex=startItrator-1; seaDaysCount=seaDaysCount - tempEffectiveZeros; tempEffectiveZeros=0; } } } else if (A[startItrator] == 0) { tempZeros++; tempEffectiveZeros++; } } startItrator--; } // check if the first part elgiable to expand left or no int expantionValue = arrayExpandLeft(firstzero, seaDaysCount, seaArraySize, A); firstzero -= expantionValue; seaArraySize += expantionValue; int mountainTripDuration=lastone-seaEndIndex+extraDays; return seaArraySize+mountainTripDuration; } /// methods to get number of zeros that we can add to the seond part withought making it fail ( the number of ones should be greater than the number of zeros) int getExtraDays(int numOfOnes, int numOfZeros) { return numOfOnes - numOfZeros - 1; } // method to expand the first part of the trip to the left side int arrayExpandLeft(int firstzero, int seaDaysCount, int seaArraySize, int[] A) { int expantionValue = 0; while (seaTripHasExtraSwimDays(seaArraySize, seaDaysCount) && firstzero > 0) { if (firstzero == 0) { break; } firstzero--; seaArraySize++; expantionValue++; } return expantionValue; } // cheack if the seatrip is ok with this size and this number of zeros boolean seaTripNotFail(int seaArraySize, int numOfZeros) { return numOfZeros - (seaArraySize - numOfZeros) >= 1; } // cheack if the seatrip is elgiable to add more ones boolean seaTripHasExtraSwimDays(int seaArraySize, int numOfZeros) { return numOfZeros - (seaArraySize - numOfZeros) > 1; } }