I felt it’s not obvious why the smallest sum of sides is related to the square root, at least not to me. Other comments simply state this as a fact without providing an explanation. Which should be short if it’s that simple. So I first provided a mathematical proof that this is the case.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
def solution(N): # Smallest perimeter is made of numbers on either side sqrt(N). That is, the smallest ones, closest ones to sqrt(N). # This was gleaned by looking at the example case provided. ''' Mathematical proof: 1. We note all potential scenarios can be sorted according to the following pattern, starting with case a, where one side is equal to the area and the other side equal to 1. N = area N = A * B a. A = N, B = 1 b. A = N / 2, B = 2 --> Hypothesis says "The sides of this rectangle should be only integers." So next B can only be 1, and next one 2, then 3 etc. c. A = N / 3, B = 3 2. Case a gives Perimeter (P) = (N+1)2 = 2N + 2. Case b, (N/2 + 2)2 = N + 4, c, (N/3 + 3)2 = 2/3*N + 6 etc. We now try and compare each case to each other. a > b as: 2N + 2 > 2N / 2 + 4. But our pattern also meets the following condition: B < A. We don't consider the other half of the set, where B > A, because multiplication is commutative. Which means A * B = B * A. So, because B < A, case b means 2 < N / 2. Going back, we get 2N > N + 2. But as we agreed that 2 < N, 2N > N + 2 is always true (qed). b > c 2N / 2 + 4 > 2N / 3 + 6 N > 2N/3 + 2 The only way 2N/3 + 2 = N is if 2 = N/3; but 3 < N/3 (B < A), and 2 < 3, so 2 < N/3. So, 2N/2 + 4 > 2N/3 + 6 is always true (qed). ... so each case following will necessarily give a perimeter smaller than the one before. 3. Conclusion: the smallest perimeter is the one for the largest B, where B < A. This is where B < sqrt(N) and A > sqrt(N). ''' area = N if area == 1: return 4 for i in range(int(math.sqrt(area)), area + 1): if area % i == 0: sideA = area / i sideB = i break perimeter = int(2 * (sideA + sideB)) return perimeter |

What got 100% was simply going through each integer number till you reach the square root. Which also has a time of O(sqrt(N)), obviously, but Codility thinks this is better than using math.sqrt(N).

1 2 3 4 5 6 7 8 9 10 11 12 13 |
def solution(N): area = N if area == 1: return 4 i = 1 while i * i <= area: if area % i == 0: sideA = area / i sideB = i i += 1 perimeter = int(2 * (sideA + sideB)) return perimeter |

Assume you found the slice with minimal average. Assume the first two consecutive elements of the slice have higher average. If you take out (any) elements with higher average from the (or any) slice, then your reduced slice now has lower average (This is intuitive but should be proven. See proof below). Thus, having first two consecutive elements with higher average (to take out) contradicts the initial assumption that you found the slice with minimal average.

Intermediate conclusion:

As long as you can take out two consecutive first elements, then either their average is lower or equal to the slice’s, or the reduced slice’s average is lower, which contradicts the initial assumption that you found the slice with minimal average.

It is given that a slice must contain at least 2 elements. Thus, a slice from which you can take out first two consecutive elements has more than three elements.

Conclusion:

For any slice with the minimal average, it is either of size 3, or there is a slice of size 2 with that minimal average.

S0 = (a0+a1+a2+…an)/n

S1 = (a2+…an)/(n-2)

S2 = (a0+a1)/2

==> S2 = ((n)S0-(n-2)S1)/2

S2 > S0 ==> ((n)S0-(n-2)S1)/2 > S0 ==> S1 < S0.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
def solution(H): heights = H # geometric logic: the blocks need to be cuboid, all sides are rectagular. Nothing fancy, means that the angles # need to be 90 deg. # Translated into code, any time your height changes, you start a new block. # Going up, would lead to a 270 deg angle, # while going down, the same. # Your ground level is 0 when you start. But doesn't have to stay that way. To reduce the number of blocks, you # raise the ground level to the lowest common floor. You build blocks on that while you can, that is # while you don't go # any lower. # Do blocks need to be individual objects? You only need to count them, so no. blocks_count = 0 levels = [0] for i in heights: # Going down. if i < levels[-1]: # If you drop to a level already attained, there is no change of angle, so no new block. This will be the # continuation of a block already counted. Simply dropping does not create a new block, while simply rising # always does create a new block. This asymmetry is a consequence of moving from left to right. levels.pop() while i < levels[-1]: levels.pop() if i > levels[-1]: blocks_count += 1 levels.append(i) # Going up. elif i > levels[-1]: blocks_count += 1 levels.append(i) return blocks_count |

Thank you, Sheng for pointing out that this is a common trap, to assume that any for-while is O(n^2). Actually wrote down your comment, hopefully to never repeat this mistake again.

Indeed, like Sheng said, most times the while gets executed is n times. Worst case, when the while-loop has the largest number of fish to go through, is when you have n-1 downstreamers and one upstreamer at the end, bigger than all.

The last fish, the upstreamer, eats them one by one in the while loop. This means your program goes through all the n fish once in the for-loop, then once more through all the downstreamers in the while-loop. So thats n + (n-1). Technically, Sheng is right to say that while gets executed n times, as any while or for-loop will have the test executed one more time compared to its loop body.

At any rate, this is 2n (or 2n +1, to be more precise) number of times the for + while statements are evaluated in total. So worst case is 2n, therefore O(n).

]]>Your solution is way more elegant than mine but I set out not to use anything as complex as a dictionary.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
def nested(S): if len(S) == 0: return 1 if len(S) % 2 != 0: return 0 # Stack represents unsolved business, brackets waiting to be closed. stack = [] o = ["(", "[", "{"] c = [")", "]", "}"] l = [S[i] for i in range(len(S))] for i in l: # First, filter: does it get stacked or not? Only gets stacked if previous in stack not # forming a pair # or if it is an open # bracket. if i in c: if len(stack) == 0: return 0 if stack[-1] in o: if c.index(i) == o.index(stack[-1]): stack.pop() else: return 0 else: stack.append(i) else: stack.append(i) if len(stack) == 0: return 1 else: return 0 |

1 2 3 4 5 6 7 8 |
def missingnum(a): st=min(a) en=max(a) b=set(range(1,en+2)) if (en<1 or st>1) : return 1 else: return min(b-set(a)) |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
int solution(int N, string &S, string &T) { int q = N / 2 * N / 2; int lf {q}; int rf {q}; int lb {q}; int rb {q}; int prev = 0; for (char x : S) { if (x == ' ') prev = 0; if (x >= 'A' && x <= 'Z') { int val = x - 'A'; prev--; if (prev < N/2 && val < N/2) { lf--; } else if (prev < N/2 && val >= N/2) { rf--; } else if (prev >= N/2 && val < N/2) { lb--; } else { rb--; } } if (x >= '0' && x <= '9') { prev = (prev * 10 ) + x - '0'; } } int avl_lf = min (lf, rb); int avl_rb = avl_lf; int avl_rf = min (rf, lb); int avl_lb = avl_rf; for (char x : T) { if (x == ' ') prev = 0; if (x >= 'A' && x <= 'Z') { int val = x - 'A'; prev--; if (prev < N/2 && val < N/2) { avl_lf--; } else if (prev < N/2 && val >= N/2) { avl_rf--; } else if (prev >= N/2 && val < N/2) { avl_lb--; } else { avl_rb--; } if (avl_lf < 0 || avl_rf < 0 || avl_lb < 0 || avl_rb < 0) return -1; } if (x >= '0' && x <= '9') { prev = (prev * 10 ) + x - '0'; } } return avl_lf + avl_rb + avl_rf + avl_lb; } |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
int solution(int N, string &S, string &T) { int q = N / 2 * N / 2; int lf {q}; int rf {q}; int lb {q}; int rb {q}; int prev = 0; for (char x : S) { if (x == ' ') prev = 0; if (x >= 'A' && x <= 'Z') { int val = x - 'A'; if (prev < N/2 && val < N/2) { lf--; } else if (prev < N/2 && val >= N/2) { rf--; } else if (prev >= N/2 && val < N/2) { lb--; } else { rb--; } } if (x >= '0' && x <= '9') { prev = (prev * 10 ) + x - '0' - 1; } } int avl_lf = min (lf, rb); int avl_rb = avl_lf; int avl_rf = min (rf, lb); int avl_lb = avl_rf; for (char x : T) { if (x == ' ') prev = 0; if (x >= 'A' && x <= 'Z') { int val = x - 'A'; if (prev < N/2 && val < N/2) { avl_lf--; } else if (prev < N/2 && val >= N/2) { avl_rf--; } else if (prev >= N/2 && val < N/2) { avl_lb--; } else { avl_rb--; } if (avl_lf < 0 || avl_rf < 0 || avl_lb < 0 || avl_rb < 0) return -1; } if (x >= '0' && x <= '9') { prev = (prev * 10 ) + x - '0' - 1; } } return avl_lf + avl_rb + avl_rf + avl_lb; } |

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <climits> int solution(vector<int> &A) { int max_depth {}; int max_lvl = {}; int min_lvl = INT_MAX; for (unsigned int i {}; i < A.size(); i++) { if (A[i] >= max_lvl) { int loc_depth = max_lvl - min_lvl; max_depth = max(loc_depth, max_depth); min_lvl = INT_MAX; max_lvl = A[i]; } else if (A[i] < min_lvl) { min_lvl = A[i]; } else if (A[i] > min_lvl) { int loc_depth = A[i] - min_lvl; max_depth = max(loc_depth, max_depth); } } return max_depth; } |

WRONG ANSWER

got 705082704 expected 1000000000

So, what have I done? I submitted a search on Google with the two following terms:

codility 705082704

Then I found your post. I don’t understand this, because I am 99.99% that my code is correct. I am testing millions (literally) of cases and my code seems to be correct. I would understand a mistake if the result 705,082,704 was bigger than 1,000,000,000 (because when the result is bigger than 1,000,000,000 it should return 1,000,000,000), but IT ISN’T, 705,082,704 is lower than 1,000,000,000. I don’t understand it…

]]>