├── .gitignore ├── LICENSE ├── README.md └── solutions ├── arrays ├── cyclic_rotation.py ├── odd_occurrences_in_array.py └── odd_occurrences_in_array_xor.py ├── caterpillarmethod ├── count_distinct_slices.py └── min_abs_sum_of_two.py ├── countingelements ├── frog_river_one.py └── max_counters.py ├── dynamicprogramming └── number_solitaire.py ├── euclideanalgorithm └── chocolates_by_numbers.py ├── greedyalgorithms ├── max_non_overlapping_segments.py └── tie_ropes.py ├── leader └── dominator.py ├── maximumsliceproblem └── max_profit.py ├── prefixsums ├── count_div.py ├── countdivconsole.txt └── passing_cars.py ├── primeandcompositenumbers ├── flags.py └── flags_faster.py ├── sorting ├── number_of_disc_intersections_alt.py └── numer_of_disc_intersections.py ├── stacksandqueues ├── brackets.py └── fish.py └── timecomplexity ├── perm_missing_elem.py └── tape_equilibrium.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | .idea/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 James Cutajar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CodilityInPython 2 | Solutions for Codility puzzles in Python 3 | 4 | The udemy course for this repo can be found at: 5 | 6 | https://www.udemy.com/beat-the-codility-coding-interview-in-python/?couponCode=3E8YU5Z 7 | 8 | All of these can be tested at: 9 | https://codility.com/programmers/lessons/ 10 | 11 | Please do get in touch if you find any suggestions/improvements! 12 | 13 | Follow me on https://twitter.com/cutajarj 14 | 15 | And checkout my blog at: www.cutajarjames.com 16 | 17 | Hopefully this is the only bug contained in this repo: 18 | ``` 19 | .--. .--. 20 | _ ` \ / ` _ 21 | `\.===. \.^./ .===./` 22 | \/`"`\/ 23 | , | | , 24 | / `\|`-.-'|/` \ 25 | / | \ | \ 26 | .-' ,-'`| ; |`'-, '-. 27 | | | \| | 28 | | | ;| | 29 | | \ // | 30 | | `._//' | 31 | jgs .' `. 32 | _,' `,_ 33 | 34 | ``` -------------------------------------------------------------------------------- /solutions/arrays/cyclic_rotation.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Arrays > CyclicRotation 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(A, K): 6 | result = [None] * len(A) 7 | 8 | for i in range(len(A)): 9 | result[(i + K) % len(A)] = A[i] 10 | 11 | return result 12 | 13 | print(solution([1, 2, 3, 4, 5], 2)) 14 | 15 | print(solution([1, 2, 3, 4, 5], 5)) 16 | -------------------------------------------------------------------------------- /solutions/arrays/odd_occurrences_in_array.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Arrays > OddOccurrencesInArray 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | 6 | def solution(A): 7 | numbers = set([]) 8 | for n in A: 9 | if n in numbers: 10 | numbers.discard(n) 11 | else: 12 | numbers.add(n) 13 | return numbers.pop() 14 | 15 | 16 | print(solution([9, 3, 9, 3, 9, 7, 9])) 17 | 18 | -------------------------------------------------------------------------------- /solutions/arrays/odd_occurrences_in_array_xor.py: -------------------------------------------------------------------------------- 1 | # This is the alternative (consumes less memory) solution for Arrays > OddOccurrencesInArray 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | 6 | def solution(A): 7 | result = 0 8 | for i in range(0, len(A)): 9 | result ^= A[i] 10 | return result 11 | 12 | 13 | print(solution([1, 4, 4, 1, 6, 8, 6])) 14 | 15 | -------------------------------------------------------------------------------- /solutions/caterpillarmethod/count_distinct_slices.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Caterpillar Method > CountDistinctSlices 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(M, A): 6 | total_slices = 0 7 | in_current_slice = [False] * (M + 1) 8 | head = 0 9 | for tail in range(0, len(A)): 10 | while head < len(A) and (not in_current_slice[A[head]]): 11 | in_current_slice[A[head]] = True 12 | total_slices += (head - tail) + 1 13 | head += 1 14 | total_slices = 1000000000 if total_slices > 1000000000 else total_slices 15 | in_current_slice[A[tail]] = False 16 | return total_slices 17 | 18 | 19 | print(solution(9, [2, 4, 1, 7, 4, 9, 7, 3, 5, 5, 8, 7, 1])) 20 | 21 | print(solution(6, [3, 4, 5, 5, 2])) 22 | -------------------------------------------------------------------------------- /solutions/caterpillarmethod/min_abs_sum_of_two.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Caterpillar Method > MinAbsSumOfTwo 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | 5 | 6 | def solution(A): 7 | min_abs_sum = 2000000000 8 | A = sorted(A) 9 | head = 0 10 | tail = len(A) - 1 11 | while head <= tail: 12 | min_abs_sum = min(min_abs_sum, abs(A[head] + A[tail])) 13 | if A[head] + A[tail] < 0: 14 | head += 1 15 | else: 16 | tail -= 1 17 | return min_abs_sum 18 | 19 | 20 | print(solution([-7, 3, -1, 5, -11, 4, -9, 14, 17, -2])) # Solution should be 1 21 | print(solution([8, 3, 5, 16, 11])) # Solution should be 6 22 | print(solution([-7, -5, -6, -2, -9])) # Solution should be 4 23 | print(solution([-7, 3, -6, 1, 0, -9])) # Solution should be 0 24 | print(solution([-22, 3, 4, 5])) # Solution should be 6 25 | -------------------------------------------------------------------------------- /solutions/countingelements/frog_river_one.py: -------------------------------------------------------------------------------- 1 | # This is the solution for CountingElements > FrogRiverOne 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(X, A): 6 | river_positions = [False] * (X + 1) 7 | for time in range(len(A)): 8 | pos = A[time] 9 | if not river_positions[pos]: 10 | river_positions[pos] = True 11 | X -= 1 12 | if X == 0: return time 13 | return -1 14 | 15 | 16 | print(solution(5, [1, 3, 1, 4, 2, 3, 5, 4])) 17 | 18 | print(solution(1, [1, 1, 1])) 19 | 20 | print(solution(3, [1, 2, 1])) 21 | -------------------------------------------------------------------------------- /solutions/countingelements/max_counters.py: -------------------------------------------------------------------------------- 1 | # This is the solution for CountingElements > MaxCounters 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | 5 | def solution(N, A): 6 | counters = [0] * N 7 | start_line = 0 8 | current_max = 0 9 | for i in A: 10 | x = i - 1 11 | if i > N: 12 | start_line = current_max 13 | elif counters[x] < start_line: 14 | counters[x] = start_line + 1 15 | else: 16 | counters[x] += 1 17 | if i <= N and counters[x] > current_max: 18 | current_max = counters[x] 19 | for i in range(0, len(counters)): 20 | if counters[i] < start_line: 21 | counters[i] = start_line 22 | return counters 23 | 24 | print (solution(5, [3, 4, 4, 6, 1, 4, 4])) 25 | -------------------------------------------------------------------------------- /solutions/dynamicprogramming/number_solitaire.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Dynamic programming > NumberSolitaire 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | # Note here we have the evolution of the algorithm. Only the last function is the correct one. 5 | 6 | def solutionRecursive(A): 7 | return max_sum_six_distances(A, 0) 8 | 9 | 10 | def max_sum_six_distances(a, position): 11 | if position == len(a) - 1: 12 | return a[position] 13 | else: 14 | max_forward = min(len(a) - position, 6) 15 | current_max = -100000 16 | for i in range(1, max_forward): 17 | local_max = max_sum_six_distances(a, position + i) 18 | current_max = max(current_max, local_max) 19 | return current_max + a[position] 20 | 21 | 22 | def solutionMemoize(A): 23 | values = [-100000] * len(A) 24 | return max_sum_six_distancesMem(A, 0, values) 25 | 26 | 27 | def max_sum_six_distancesMem(a, position, values): 28 | if position == len(a) - 1: 29 | return a[position] 30 | if values[position] == -100000: 31 | max_forward = min(len(a) - position, 6) 32 | current_max = -100000 33 | for i in range(1, max_forward): 34 | local_max = max_sum_six_distancesMem(a, position + i, values) 35 | current_max = max(current_max, local_max) 36 | values[position] = current_max + a[position] 37 | return values[position] 38 | 39 | 40 | def solution(A): 41 | values = [0] * len(A) 42 | values[len(A) - 1] = A[len(A) - 1] 43 | for i in range(len(A) - 2, -1, -1): 44 | values[i] = A[i] + find_max_between(values, i + 1, 6) 45 | return values[0] 46 | 47 | 48 | def find_max_between(values, start, length): 49 | max = values[start] 50 | upto = min(start + length, len(values)) 51 | for i in range(start, upto): 52 | if values[i] > max: 53 | max = values[i] 54 | return max 55 | 56 | 57 | print(solutionRecursive([1, -2, 0, 9, -1, -2, 5, -4])) 58 | print(solutionRecursive([1, -2, 0, 9, -1, -2, 5, -4, -5, -1, -10, -5, -6, -4, -2])) 59 | 60 | print(solutionMemoize([1, -2, 0, 9, -1, -2, 5, -4])) 61 | print(solutionMemoize([1, -2, 0, 9, -1, -2, 5, -4, -5, -1, -10, -5, -6, -4, -2])) 62 | 63 | print(solution([1, -2, 0, 9, -1, -2, 5, -4])) 64 | print(solution([1, -2, 0, 9, -1, -2, 5, -4, -5, -1, -10, -5, -6, -4, -2])) 65 | -------------------------------------------------------------------------------- /solutions/euclideanalgorithm/chocolates_by_numbers.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Euclidean Algorithm > Chocolate by Numbers 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | 6 | def find_gcd(a, b): 7 | if b == 0: 8 | return a 9 | else: 10 | return find_gcd(b, a % b) 11 | 12 | 13 | def solution(N, M): 14 | return N // find_gcd(N, M) 15 | 16 | 17 | print(solution(10, 4)) 18 | 19 | print(solution(9, 6)) 20 | 21 | print(solution(10, 11)) 22 | 23 | -------------------------------------------------------------------------------- /solutions/greedyalgorithms/max_non_overlapping_segments.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Greedy algorithms > MaxNonoverlappingSegments 2 | # The problem is equivalent to the Activity Selection Problem, 3 | # where you have to choose the maximum non overlapping tasks. 4 | # 5 | # This is marked as PAINLESS difficulty 6 | 7 | def solution(A, B): 8 | last_end_segment = -1 9 | chosen_count = 0 10 | for i in range(len(A)): 11 | if A[i] > last_end_segment: 12 | chosen_count += 1 13 | last_end_segment = B[i] 14 | return chosen_count 15 | 16 | 17 | print(solution([1, 3, 7, 9, 1], [5, 6, 8, 9, 10])) 18 | 19 | print(solution([1, 3, 5, 7, 9], [2, 4, 6, 8, 10])) 20 | 21 | print(solution([], [])) 22 | -------------------------------------------------------------------------------- /solutions/greedyalgorithms/tie_ropes.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Greedy > TieRopes 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | 6 | def solution(K, A): 7 | count = 0 8 | rope_length = 0 9 | for rope in A: 10 | rope_length += rope 11 | if rope_length >= K: 12 | count += 1 13 | rope_length = 0 14 | return count 15 | 16 | 17 | print(solution(4, [1, 2, 3, 4, 1, 1, 3])) 18 | -------------------------------------------------------------------------------- /solutions/leader/dominator.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Leader > Dominator 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(A): 6 | consecutive_size = 0 7 | candidate = 0 8 | for item in A: 9 | if consecutive_size == 0: 10 | candidate = item 11 | consecutive_size += 1 12 | elif candidate == item: 13 | consecutive_size += 1 14 | else: 15 | consecutive_size -= 1 16 | occurrence = A.count(candidate) 17 | if occurrence > (len(A)/2): 18 | return A.index(candidate) 19 | else: 20 | return -1 21 | 22 | 23 | print(solution([3,0,1,1,4,1,1])) 24 | -------------------------------------------------------------------------------- /solutions/maximumsliceproblem/max_profit.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Maximum Slice Problem > Max Profit 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(A): 6 | global_max_sum = 0 7 | local_max_sum = 0 8 | for i in range(1, len(A)): 9 | d = A[i] - A[i - 1] 10 | local_max_sum = max(d, local_max_sum + d) 11 | global_max_sum = max(local_max_sum, global_max_sum) 12 | return global_max_sum 13 | 14 | 15 | # -2160, 112, 243, -353, 354 16 | print(solution([23171, 21011, 21123, 21366, 21013, 21367])) 17 | 18 | -------------------------------------------------------------------------------- /solutions/prefixsums/count_div.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Prefix Sums > Count Div 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | 5 | from math import ceil, floor 6 | 7 | 8 | def solution(A, B, K): 9 | n_start = ceil(A / K) 10 | n_end = floor(B / K) 11 | return n_end - n_start + 1 12 | 13 | 14 | print(solution(6, 11, 2)) 15 | -------------------------------------------------------------------------------- /solutions/prefixsums/countdivconsole.txt: -------------------------------------------------------------------------------- 1 | >>> 6 / 2 2 | 3.0 3 | >>> 7 / 2 4 | 3.5 5 | >>> from math import ceil, floor 6 | >>> ceil(7 / 2) 7 | 4 8 | >>> 11 / 2 9 | 5.5 10 | >>> ceil(6 / 2) 11 | 3 12 | >>> 11 / 2 13 | 5.5 14 | >>> floor(11 / 2) 15 | 5 16 | >>> floor(10 / 2) 17 | 5 18 | >>> floor(11 / 2) - ceil(6 / 2) + 1 19 | 3 20 | -------------------------------------------------------------------------------- /solutions/prefixsums/passing_cars.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Prefix Sums > Passing Cars 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(A): 6 | suffix_sum = [0] * (len(A) + 1) 7 | for i in range(len(A) - 1, -1, -1): 8 | suffix_sum[i] = A[i] + suffix_sum[i + 1] 9 | 10 | count = 0 11 | for i in range(len(A)): 12 | if A[i] == 0: 13 | count += suffix_sum[i] 14 | if count > 1000000000: 15 | return -1 16 | 17 | return count 18 | 19 | 20 | print(solution([0, 1, 0, 1, 1])) 21 | -------------------------------------------------------------------------------- /solutions/primeandcompositenumbers/flags.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Prime And Composite > Flags 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | 5 | 6 | def solution(A): 7 | peaks = [0] * len(A) 8 | next_peak = len(A) 9 | peaks[len(A) - 1] = next_peak 10 | for i in range(len(A) - 2, 0, -1): 11 | if A[i - 1] < A[i] and A[i + 1] < A[i]: 12 | next_peak = i 13 | peaks[i] = next_peak 14 | peaks[0] = next_peak 15 | 16 | current_guess = 0 17 | next_guess = 0 18 | while can_place_flags(peaks, next_guess): 19 | current_guess = next_guess 20 | next_guess += 1 21 | return current_guess 22 | 23 | 24 | def can_place_flags(peaks, flags_to_place): 25 | current_position = 1 - flags_to_place 26 | for i in range(flags_to_place): 27 | if current_position + flags_to_place > len(peaks) - 1: 28 | return False 29 | current_position = peaks[current_position + flags_to_place] 30 | return current_position < len(peaks) 31 | 32 | 33 | test_trail = [1,5,3,4,3,4,1,2,3,4,6,2] 34 | print(solution(test_trail)) 35 | 36 | -------------------------------------------------------------------------------- /solutions/primeandcompositenumbers/flags_faster.py: -------------------------------------------------------------------------------- 1 | from math import sqrt 2 | 3 | 4 | def solution(A): 5 | peaks = [0] * len(A) 6 | next_peak = len(A) 7 | peaks[len(A) - 1] = next_peak 8 | for i in range(len(A) - 2, 0, -1): 9 | if A[i - 1] < A[i] and A[i + 1] < A[i]: 10 | next_peak = i 11 | peaks[i] = next_peak 12 | peaks[0] = next_peak 13 | 14 | upper_guess = int(sqrt(len(A))) + 2 15 | lower_guess = 0 16 | 17 | while lower_guess < upper_guess - 1: 18 | current_guess = int((lower_guess + upper_guess) / 2) 19 | if can_place_flags(peaks, current_guess): 20 | lower_guess = current_guess 21 | else: 22 | upper_guess = current_guess 23 | 24 | return lower_guess 25 | 26 | 27 | def can_place_flags(peaks, flags_to_place): 28 | current_position = 1 - flags_to_place 29 | for i in range(flags_to_place): 30 | if current_position + flags_to_place > len(peaks) - 1: 31 | return False 32 | current_position = peaks[current_position + flags_to_place] 33 | return current_position < len(peaks) 34 | 35 | test_trail = [1,5,3,4,3,4,1,2,3,4,6,2] 36 | print(solution(test_trail)) 37 | 38 | -------------------------------------------------------------------------------- /solutions/sorting/number_of_disc_intersections_alt.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Sorting > NumberOfDiscIntersections 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | 5 | class Disc(): 6 | def __init__(self, low_x, high_x): 7 | self.low_x = low_x 8 | self.high_x = high_x 9 | 10 | def index_less_than(sortedDiscList, i, start, last): 11 | mid = start + (last - start) // 2 12 | if last <= start and sortedDiscList[mid].low_x > i: 13 | return mid - 1 14 | elif last <= start: 15 | return mid 16 | elif sortedDiscList[mid].low_x > i: 17 | return index_less_than(sortedDiscList, i, start, mid - 1) 18 | else: 19 | return index_less_than(sortedDiscList, i, mid + 1, last) 20 | 21 | def solution(A): 22 | discs = [] 23 | for i in range(len(A)): 24 | discs.append(Disc(i - A[i], i + A[i])) 25 | discs = sorted(discs, key=lambda d: d.low_x) 26 | total = 0 27 | for i in range(len(discs)): 28 | total += index_less_than(discs, discs[i].high_x + 0.5, 0, len(discs) - 1) - i 29 | if total > 10000000: 30 | total = -1 31 | break 32 | return total 33 | 34 | print(solution([1, 5, 2, 1, 4, 0])) 35 | 36 | print(solution([0] * 100000)) 37 | -------------------------------------------------------------------------------- /solutions/sorting/numer_of_disc_intersections.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Sorting > NumberOfDiscIntersections 2 | # 3 | # This is marked as RESPECTABLE difficulty 4 | 5 | class DiscLog(): 6 | def __init__(self, x, start_end): 7 | self.x = x 8 | self.start_end = start_end 9 | 10 | def solution(A): 11 | discHistory = [] 12 | for i in range(len(A)): 13 | discHistory.append(DiscLog(i - A[i], 1)) 14 | discHistory.append(DiscLog(i + A[i], -1)) 15 | discHistory.sort(key=lambda d: (d.x, -d.start_end)) 16 | intersections = 0 17 | active_intersections = 0 18 | for log in discHistory: 19 | active_intersections += log.start_end 20 | if log.start_end > 0: 21 | intersections += active_intersections - 1 22 | if intersections > 10000000: 23 | return -1 24 | return intersections 25 | 26 | print(solution([1, 5, 2, 1, 4, 0])) 27 | 28 | print(solution([0] * 100000)) 29 | 30 | -------------------------------------------------------------------------------- /solutions/stacksandqueues/brackets.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Stacks And Queues > Brackets 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | 6 | def solution(S): 7 | valid = True 8 | stack = [] 9 | for c in S: 10 | if c == "[" or c == "(" or c == "{": 11 | stack.append(c) 12 | elif c == ")": 13 | valid = False if not stack or stack.pop() != "(" else valid 14 | elif c == "]": 15 | valid = False if not stack or stack.pop() != "[" else valid 16 | elif c == "}": 17 | valid = False if not stack or stack.pop() != "{" else valid 18 | return 1 if valid and not stack else 0 19 | 20 | 21 | print(solution("()[]{}()[]{}")) 22 | 23 | print(solution("()]]")) 24 | -------------------------------------------------------------------------------- /solutions/stacksandqueues/fish.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Stacks And Queues > Fish 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(A, B): 6 | stack = [] 7 | survivors = 0 8 | for i in range(len(A)): 9 | weight = A[i] 10 | if B[i] == 1: 11 | stack.append(weight) 12 | else: 13 | weightdown = stack.pop() if stack else -1 14 | while weightdown != -1 and weightdown < weight: 15 | weightdown = stack.pop() if stack else -1 16 | if weightdown == -1: 17 | survivors += 1 18 | else: 19 | stack.append(weightdown) 20 | return survivors + len(stack) 21 | 22 | print(solution([4, 8, 2, 6, 7], [0, 1, 1, 0, 0])) 23 | 24 | print(solution([4, 3, 2, 1, 5], [0, 1, 0, 0, 0])) -------------------------------------------------------------------------------- /solutions/timecomplexity/perm_missing_elem.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Time Complexity > PermMissingElem 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | 6 | def solution(A): 7 | actual_sum = 0 8 | for number in A: 9 | actual_sum += number 10 | max_number = len(A) + 1 11 | expected_sum = (max_number * (max_number + 1) // 2) 12 | return expected_sum - actual_sum 13 | 14 | 15 | print(solution([2, 3, 1, 5])) 16 | 17 | print(solution([1, 2, 3, 4, 5, 6, 7, 8, 9])) 18 | 19 | print(solution([])) 20 | -------------------------------------------------------------------------------- /solutions/timecomplexity/tape_equilibrium.py: -------------------------------------------------------------------------------- 1 | # This is the solution for Time Complexity > TapeEquilibrium 2 | # 3 | # This is marked as PAINLESS difficulty 4 | 5 | def solution(A): 6 | sum_left = A[0] 7 | sum_right = sum(A) - A[0] 8 | diff = abs(sum_left - sum_right) 9 | for i in range(1, len(A)-1): 10 | sum_left += A[i] 11 | sum_right -= A[i] 12 | current_diff = abs(sum_left - sum_right) 13 | if diff > current_diff: 14 | diff = current_diff 15 | return diff 16 | 17 | 18 | print(solution([3, 1, 2, 4, 3])) 19 | 20 | 21 | --------------------------------------------------------------------------------