├── README.md ├── Lesson3_Set.py ├── Lesson8_Trees.py ├── Lesson1_DifficultyTesting.py ├── Lesson6_BinarySearch.py ├── Lesson5_PrefixSumAndTwoPointers.py ├── Lesson4_Dictionary.py ├── Lesson2_LinearSearchFunctions.py └── Lesson7_EventsSort.py /README.md: -------------------------------------------------------------------------------- 1 | # YandexAlgorithms 2 | 3 | Here are my lecture notes after completing the trainings on Algorithms from Yandex. 4 | Hope they will be useful and you enjoy it! 5 | 6 | 7 | -------------------------------------------------------------------------------- /Lesson3_Set.py: -------------------------------------------------------------------------------- 1 | """Define our multi-set. Working with hash functions""" 2 | """Basically we create a two-dimensional array or list of lists, list with 10 lists inside""" 3 | 4 | setsize = 10 5 | newset= [[] for _ in range(setsize)] 6 | 7 | """Add an element to our set""" 8 | def add(x): 9 | # if not find (x) - better way to add. that way there will be no duplicates and we have a usual set 10 | newset[x % setsize].append(x) 11 | 12 | """Find an element in our set""" 13 | def find(x): 14 | for now in newset[x % setsize]: 15 | if now == x: 16 | return True 17 | return False 18 | 19 | """Delete an element in our set""" 20 | def delete(x): 21 | xlist = newset[x % setsize] 22 | for i in range(len(xlist)): 23 | if xlist[i] == x: 24 | # a,b = b,a - swap(a,b) - usual for C++ 25 | #xlist[i], xlist[len(xlist) - 1] = xlist[len(xlist) - 1], xlist[i] 26 | xlist[i] = xlist[len(xlist) - 1] 27 | xlist.pop() 28 | return 29 | """Task 1""" 30 | """Here is a sequence with len N and a number X, all numbers all positive""" 31 | """We need to find two different numbers A and B in our seq, A + B = X or return (0,0) 32 | if there are no such numbers""" 33 | 34 | """Solution with O(N**2) difficulty""" 35 | def twotermswithsumx(nums, x): 36 | for i in range(len(nums)): # run through indexes 37 | for j in range(i + 1, len(nums)): # run through indexes second time, starting from the next right element to i 38 | if nums[i] + nums[j] == x and nums[i] != nums[j]: # compare sum of our elements with indexes i,j with number X, also compare them to each other to define that they are not equal 39 | return nums[i],nums[j] # finally return a pair of numbers with i and j indexes if their sum is equal to X 40 | return 0, 0 # if there are no such numbers return 0,0 41 | 42 | print(twotermswithsumx([2,3,3,4,5,7,1], 6)) 43 | 44 | """Solution with O(N) difficulty""" 45 | def twotermswithsumx2(nums, x): 46 | prevnums = set() # define a set 47 | for nownum in nums: # run through the numbers 48 | if x - nownum in prevnums: # if result of subtraction between number X and current number is in our set 49 | return nownum, x - nownum # we return current number and result of previous subtraction 50 | prevnums.add(nownum) # otherwise we add current number to our set, and back to the loop 51 | return 0, 0 # we return 0,0 if there are no such pair of numbers 52 | 53 | print(twotermswithsumx2([2,3,3,4,5,7,1], 6)) 54 | 55 | """Task 2""" 56 | """Here is a dictionary with N words, len of each word is not greater(>) than K""" 57 | """For every word(total value of words - M) in the text(len < K) one letter can be skipped""" 58 | """We should say for every word(with a possible skipped letter) whether it is in our dictionary or not""" 59 | 60 | """Solution with O(NK**2 + M) difficulty""" 61 | def wordsindict(dictionary,text): 62 | goodwords = set(dictionary) # define a set of words which were in the dictionary 63 | for word in dictionary: # run through the words in the dictionary 64 | for delpos in range(len(word)): # run through the word 65 | goodwords.add(word[:delpos] + word[delpos+1:]) # add to the set concatenation of slices without delpos 66 | 67 | ans = [] # create a new list 68 | for word in list(text.split()): # run through the words in our text 69 | ans.append(word in goodwords) # if current word is in our set we add it to our list 70 | return ans # we return our list with words which are both in the text and in the dictionary 71 | 72 | print(wordsindict(("Hello","OK","Sure", "Mama","Papa", "dog"),"I love my dg")) 73 | -------------------------------------------------------------------------------- /Lesson8_Trees.py: -------------------------------------------------------------------------------- 1 | """Memory manager code""" 2 | 3 | def initmemory(maxn): 4 | memory = [] 5 | for i in range(maxn): 6 | memory.append([0, i+1, 0]) 7 | return [memory, 0] 8 | 9 | def newnode(memstruct): 10 | memory, firstfree = memstruct 11 | memstruct[1] = memory[firstfree][1] 12 | return firstfree 13 | 14 | def delnode(memstruct, index): 15 | memory, firstfree = memstruct 16 | memory[index][1] = firstfree 17 | memstruct[1] = index 18 | 19 | """Binary tree - search realization""" 20 | 21 | def find(memstruct, root, x): 22 | key = memstruct[0][root][0] 23 | if x == key: 24 | return root 25 | elif x < key: 26 | left = memstruct[0][root][1] 27 | if left == -1: 28 | return -1 29 | else: 30 | return find(memstruct, left, x) 31 | elif x > key: 32 | right = memstruct[0][root][2] 33 | if right == - 1: 34 | return -1 35 | else: 36 | return find(memstruct, right, x) 37 | 38 | """Binary tree - add realization""" 39 | def createandfillnode(memstruct, key): 40 | # index = newnode(memstruct) 41 | memstruct[0][index][0] = key 42 | memstruct[0][index][1] = -1 43 | memstruct[0][index][2] = -1 44 | return index 45 | 46 | def add(memstruct, root, x): 47 | key = memstruct[0][root][0] 48 | if x < key: 49 | left = memstruct[0][root][1] 50 | if left == -1: 51 | memstruct[0][root][1] = createandfillnode(memstruct, x) 52 | else: 53 | add(memstruct, left, x) 54 | elif x > key: 55 | right = memstruct[0][root][2] 56 | if right == -1: 57 | memstruct[0][root][2] = createandfillnode(memstruct, x) 58 | else: 59 | add(memstruct, right, x) 60 | 61 | memstruct = initmemory(20) 62 | root = createandfillnode(memstruct, 8) 63 | add(memstruct, root, 10) 64 | add(memstruct, root, 9) 65 | add(memstruct, root, 14) 66 | add(memstruct, root, 13) 67 | add(memstruct, root, 3) 68 | add(memstruct, root, 1) 69 | add(memstruct, root, 6) 70 | add(memstruct, root, 4) 71 | add(memstruct, root, 7) 72 | 73 | 74 | 75 | """Tree in Python""" 76 | #[key, [left], [right]] 77 | #[5, [2, None,[3, None, None]],[7, None, [8, None, None]]] 78 | 79 | 80 | """Create a tree and searching through the tree""" 81 | """Having a serialized tree description, like DUDUUUDDU, we need to make a code for all of the leaves""" 82 | """D - means that we go to the leftmost unvisited child (we suppose that there are two child - 2 or there aren't any of them - 0)""" 83 | """U - means that we go up till we go from the right child. If we came to the top from the left child - we go directly to the right child""" 84 | 85 | def maketree(serialized): 86 | tree = {'left': None,'right': None, 'up': None, 'type': 'root'} 87 | nownode = tree 88 | for sym in serialized: 89 | if sym == 'D': 90 | newnode = {'left': None, 'right': None, 'up' : nownode, 'type': 'left'} 91 | nownode['left'] = newnode 92 | nownode = newnode 93 | elif sym == 'U': 94 | while nownode['type'] == 'right': 95 | nownode = nownode['up'] 96 | nownode = nownode['up'] 97 | newnode = {'left': None, 'right': None, 'up': nownode, 'type': 'right'} 98 | nownode['right'] = newnode 99 | nownode = newnode 100 | return tree 101 | 102 | print(maketree("DDUUDU")) 103 | 104 | def traverse(root, prefix): 105 | if root['left'] is None and root['right'] is None: 106 | return["".join(prefix)] 107 | prefix.append('0') 108 | ans = traverse(root['left'], prefix) 109 | prefix.pop() 110 | prefix.append('1') 111 | 112 | ans.extend(traverse(root['right'], prefix)) 113 | prefix.pop() 114 | return ans 115 | -------------------------------------------------------------------------------- /Lesson1_DifficultyTesting.py: -------------------------------------------------------------------------------- 1 | """Task1""" 2 | """Here is a string (UTF-8 format). We should find the most repeatable symbol""" 3 | """If we have more than one symbol which has the same number of replays we can return any of them""" 4 | 5 | """Solution 0""" 6 | 7 | s = input() 8 | print(max(map(lambda x: (s.count(x), x), s))[1]) 9 | 10 | """Solution 1 O(N**2) difficulty and O(N) memory""" 11 | s = input() # read a line 12 | ans = "" # empty variable 13 | anscnt = 0 # value 0 14 | for i in range(len(s)): # run through the positions in the string 15 | nowcnt = 0 # counter = 0 16 | for j in range(len(s)): # for each position run through the positions in the string once again 17 | if s[i] == s[j]: # if we meet the same symbol 18 | nowcnt += 1 # we add 1 to our counter 19 | if nowcnt > anscnt: # if the value of our counter is greater than previous result 20 | ans = s[i] # we put our symbol to the variable 21 | anscnt = nowcnt # and save the number of replays for it 22 | print(ans) # print our symbol 23 | 24 | """Solution 2 O(NK) difficulty and O(N+K)=O(N) memory""" 25 | s = input() # read a line 26 | ans = "" # empty variable 27 | anscnt = 0 # value 0 28 | for now in set(s): # run through the symbols in the set (no replays) 29 | nowcnt = 0 # counter = 0 30 | for j in range(len(s)): # for each symbol run through the positions in the string 31 | if now == s[j]: # if we meet the same symbol 32 | nowcnt += 1 # we add 1 to our counter 33 | if nowcnt > anscnt: # if the value of our counter is greater than previous result 34 | ans = now # we put our symbol to the variable 35 | anscnt = nowcnt # and save the number of replays for it 36 | print(ans) # print our symbol 37 | 38 | """Solution 3 O(N+K) = O(N) difficulty and O(K) memory""" 39 | s = input() # read a line 40 | ans = "" # empty variable 41 | anscnt = 0 # value 0 42 | dct = {} # create an empty dict 43 | for now in s: # run through the symbols in the string 44 | if now not in dct: # if symbol is not in the dict 45 | dct[now] = 0 # we add this symbol to the dict with key - 0 46 | dct[now] += 1 # we add 1 for each replay 47 | #for key in dct: # run through the keys in dict - not necessary 48 | if dct[now] > anscnt: # if the value is greater than previous result 49 | anscnt = dct[now] # we put our symbol to the variable 50 | ans = now # and save the number of replays for it 51 | print(ans) # print our symbol 52 | 53 | 54 | """Task2""" 55 | """Sum of the sequence""" 56 | 57 | """Solution1""" 58 | seq = list(map(int, input().split())) 59 | if len(seq) == 0: # Here we don't need this special case, our program will work correctly 60 | print(0) 61 | else: 62 | seqsum = seq[0] 63 | for i in range(1, len(seq)): 64 | seqsum += seq[i] 65 | print(seqsum) 66 | 67 | """Solution2""" 68 | seq = list(map(int, input().split())) 69 | seqsum = 0 70 | for i in range(1, len(seq)): 71 | seqsum += seq[i] 72 | print(seqsum) 73 | 74 | """Task3""" 75 | """Maximum of the sequence""" 76 | 77 | """Solution1""" 78 | seq = list(map(int, input().split())) 79 | seqmax = 0 80 | for i in range(len(seq)): 81 | if seq[i] > seqmax: 82 | seqmax = seq[i] 83 | print(seqmax) 84 | 85 | """Solution2""" 86 | seq = list(map(int, input().split())) 87 | seqmax = 0 88 | if len(seq) == 0: # Here we need this special case, otherwise our program will crash with empty seq 89 | print("-inf") 90 | else: 91 | seqmax = seq[0] 92 | for i in range(1,len(seq)): 93 | if seq[i] > seqmax: 94 | seqmax = seq[i] 95 | print(seqmax) 96 | 97 | 98 | """Task4""" 99 | """Quadratic equation""" 100 | from math import sqrt 101 | a,b,c = list(map(int, input().split())) 102 | if a == 0: 103 | if b != 0: 104 | print(-c/b) 105 | if b == 0 and c == 0: 106 | print("Infinite number of solutions") 107 | else: 108 | d = b**2 - 4*a*c 109 | print(sqrt(d)) 110 | if d == 0: 111 | x1 = - b/(2*a) 112 | print(x1) 113 | elif d > 0: 114 | x1 = (-b -sqrt(d))/(2*a) 115 | x2 = (-b +sqrt(d))/(2*a) 116 | if x1 < x2: 117 | print(x1,x2) 118 | else: 119 | print(x2,x1) 120 | 121 | -------------------------------------------------------------------------------- /Lesson6_BinarySearch.py: -------------------------------------------------------------------------------- 1 | """Examples of left and right binsearch""" 2 | def lbinsearch(l, r, check, checkparams): 3 | while l < r: 4 | m = (l + r)//2 5 | if check(m, checkparams): 6 | r = m 7 | else: 8 | l = m + 1 9 | return l 10 | 11 | def rbinsearch(l, r, check, checkparams): 12 | while l < r: 13 | m = (l + r + 1)//2 14 | if check(m, checkparams): 15 | l = m 16 | else: 17 | r = m - 1 18 | return l 19 | 20 | """Task1""" 21 | """The board of school consists of parents, teachers and pupils. The number of parents should be not lower than 1/3 of total number of members. 22 | At the current moment the board consists of N-number of people, and K-number of parents are there""" 23 | """Define how many parents should we add to the board so that our condition is true(not lower 1/3)""" 24 | 25 | """Solution""" 26 | def lbinsearch2(l, r, check, checkparams): 27 | while l < r: 28 | m = (l + r)//2 29 | if check(m, checkparams): 30 | r = m 31 | else: 32 | l = m + 1 33 | return l 34 | 35 | def checkendownment(m, params): 36 | n, k = params 37 | return (k + m) * 3 >= n + m 38 | 39 | """Task2""" 40 | """Yuriy is going to prepare for a job interview. He chose N-number of tasks. On the first day he solve K-number of task. 41 | Each next day he solve one task more than previous day. Define how many days Yuriy will spend for preparation""" 42 | 43 | """Solution""" 44 | def lbinsearch3(l, r, check, checkparams): 45 | while l < r: 46 | m = (l + r)//2 47 | if check(m, checkparams): 48 | r = m 49 | else: 50 | l = m + 1 51 | return l 52 | 53 | def checkendownment2(days, params): 54 | n, k = params 55 | return (k + (k + days - 1)) * days // 2 >= n 56 | 57 | """Task3""" 58 | """Mikhail gives lectures. There is a board size of W*H sentimeters. He need to place N-number of square stickers with cheat sheets on it. The len of sides should be int numbers""" 59 | """Define a max len of side for a sticker, the way that all stickers will be placed on the board""" 60 | 61 | """Solution""" 62 | def rbinsearch2(l, r, check, checkparams): 63 | while l < r: 64 | m = (l + r)//2 65 | if check(m, checkparams): 66 | r = m 67 | else: 68 | l = m + 1 69 | return l 70 | 71 | def checkstickers(size, params): 72 | n, w, h = params 73 | return (w//size) * (h//size) >= n 74 | 75 | 76 | """Task4""" 77 | """Here are sorted and not descending sequence of N numbers and number X""" 78 | """We should define index of the first element which is greater or equal to X. 79 | If there is no such number we should return number N""" 80 | 81 | """Solution""" 82 | def checkisge(index, params): 83 | seq, x = params 84 | return seq[index] >= x 85 | 86 | def findfirstge(seq, x): 87 | ans = lbinsearch(0, len(seq) -1, checkisge,(seq, x)) 88 | if seq[ans] < x: 89 | return len(seq) 90 | return ans 91 | 92 | """Task5""" 93 | """Here are sorted and not descending sequence of N numbers and number X""" 94 | """We should define how many times we meet the number X in the sequence""" 95 | 96 | """Solution""" 97 | 98 | def checkisgt2(index, params): 99 | seq, x = params 100 | return seq[index] > x 101 | 102 | def checkisge2(index, params): 103 | seq, x = params 104 | return seq[index] >= x 105 | 106 | def findfirst2(seq, x, check): 107 | ans = lbinsearch(0, len(seq) -1, check,(seq, x)) 108 | if not check(ans, (seq, x)): 109 | return len(seq) 110 | return ans 111 | 112 | def countx2(seq, x): 113 | indexgt = findfirst2(seq, x, checkisgt2) 114 | indexge = findfirst2(seq, x, checkisge2) 115 | return indexgt - indexge 116 | 117 | """Task6""" 118 | """We have the interest rate on a loan (X% per year). Credit period - N-months and Loan sum - M-rubles""" 119 | """Define a sum of annuity monthly payment """ 120 | 121 | """Solution""" 122 | """At first lets find a monthly perc""" 123 | def checkmonthlyperc(mperc, yperc): 124 | msum = 1 + mperc / 100 125 | ysum = 1 + yperc / 100 126 | return msum ** 12 >= ysum 127 | 128 | def fbinsearch(l, r, eps, check, checkparams): 129 | while l + eps < r: 130 | m = (l + r) / 2 131 | if check(m, checkparams): 132 | r = m 133 | else: 134 | l = m 135 | return l 136 | 137 | x = 12 138 | eps = 0.0001 139 | mperc = fbinsearch(0, x, eps, checkmonthlyperc,x) 140 | 141 | """Lets find a loan sum with binsearch, and as a check we will simulate a process of payment. And reduce the loan body by the result of subtraction between loan payment sum and monthly percentage """ 142 | def checkcredit(mpay, params): 143 | periods, creditsum, mperc = params 144 | for i in range(periods): 145 | percay = creditsum * (mperc / 100) 146 | creditsum -= mpay - percay 147 | return creditsum <= 0 148 | 149 | def fbinsearch2(l, r, eps, check, checkparams): 150 | while l + eps < r: 151 | m = (l + r) / 2 152 | if check(m, checkparams): 153 | r = m 154 | else: 155 | l = m 156 | return l 157 | 158 | 159 | eps = 0.01 160 | m = 10000000 161 | n = 300 # 25 years 162 | monthlypay = fbinsearch2(0, m, eps, checkcredit,(n, m, mperc)) 163 | print(monthlypay) 164 | 165 | 166 | """Task 7""" 167 | """Cyclists which are participate in the bicycle race at some moment in time which called primary found their selves in some places which far from the start position on x1,x2,...xn meters (n - total number of cyclists, not greater than 100 000) 168 | Each cyclist has his own constant speed V1, V2, .... Vn meters per second. All cyclists move into the one direction. We need to define the moment of time when the distance between the leader and the last one will be the shortest""" 169 | 170 | """Solution""" 171 | """Define a function dist(t) which with O(N) difficulty will define a distance between the leader and the last cyclist at the moment of time t. 172 | If dist(t+eps) > dist(t), then our function is rasing and we need to move our left border of the search, otherwise - move right border""" 173 | 174 | def dist(t, params): 175 | x, v = params 176 | minpos = maxpos = x[0] +v[0]*t 177 | for i in range(1,len(x)): 178 | nowpos = x[i] +v[i]*t 179 | minpos = min(minpos, nowpos) 180 | maxpos = max(maxpos, nowpos) 181 | return maxpos - minpos 182 | 183 | def checkasc(t, eps, params): 184 | return dist(t + eps, params) >= dist(t, params) 185 | 186 | def fbinsearch3(l, r, eps, checkasc, params): 187 | while l + eps < r: 188 | m = (l + r)/2 189 | if checkasc(m, eps, params): 190 | r = m 191 | else: 192 | l = m 193 | return l 194 | -------------------------------------------------------------------------------- /Lesson5_PrefixSumAndTwoPointers.py: -------------------------------------------------------------------------------- 1 | """RSQ Solution""" 2 | def makeprefixsum(nums): 3 | prefixsum = [0] * (len(nums) + 1) 4 | for i in range(1, len(nums) + 1): 5 | prefixsum[i] = prefixsum[i-1] + nums[i-1] 6 | return prefixsum 7 | 8 | print(makeprefixsum([2,3,6,8,9])) 9 | 10 | def rsq(prefixsum, l, r): 11 | return prefixsum[r] - prefixsum[l] 12 | 13 | print(rsq(makeprefixsum([2,3,6,8,9]),3,5)) 14 | 15 | """Task1""" 16 | """Here is a sequence with len N and M-number of queries""" 17 | """Queries are - How many zeroes(0) on half-interval [L,R)""" 18 | 19 | """Solution 1 O(NM) difficulty""" 20 | """For each query run through numbers from L to R(not inclusive) and count a number of zeroes""" 21 | def countzeroes(nums, l, r): 22 | cnt = 0 23 | for i in range(l,r): 24 | if nums[i] == 0: 25 | cnt += 1 26 | return cnt 27 | 28 | 29 | """Solution 2 O(N+M) difficulty""" 30 | """For each prefix we count number of zeroes on it(prefixzeroes)""" 31 | """That way, an answer for half-interval [L,R) will be: prefixzeroes[R] - prefixzeroes[L]""" 32 | def makeprefixzeroes(nums): 33 | prefixzeroes =[0] * (len(nums) +1) 34 | for i in range(2, len(nums) +1): 35 | if nums[i-1] == 0: 36 | prefixzeroes[i] = prefixzeroes[i-1] + 1 37 | else: 38 | prefixzeroes[i] = prefixzeroes[i-1] 39 | return prefixzeroes 40 | 41 | def countzeroes1(prefixzeroes, l, r): 42 | return prefixzeroes[r] - prefixzeroes[l] 43 | 44 | """Task2""" 45 | """Here is a sequence with len N. We need to find a number of intervals with 0-sum""" 46 | 47 | """Solution 1 O(N^3) difficulty""" 48 | """Search for all of the Beginnings and Endings for an interval and count a sum of it's elements""" 49 | def countzerosumranges(nums): 50 | cntranges = 0 51 | for i in range(len(nums)): 52 | for j in range(i+1, len(nums) +1): 53 | rangesum = 0 54 | for k in range(i,j): 55 | rangesum += nums[k] 56 | if rangesum == 0: 57 | cntranges += 1 58 | return cntranges 59 | 60 | 61 | """Solution 2 O(N^2) difficulty""" 62 | """Search for all of the Beginnings and will move and Ending for an inteval and count a sum of it's elements""" 63 | def countzerosumranges2(nums): 64 | cntranges = 0 65 | for i in range(len(nums)): 66 | rangesum = 0 67 | for j in range(i, len(nums)): 68 | rangesum += nums[j] 69 | if rangesum == 0: 70 | cntranges += 1 71 | return cntranges 72 | 73 | """Solution 3 O(N) difficulty""" 74 | """Lets count a prefixsums. Same prefixsums means that the sum of the elements on interval with beginning and ending 75 | on positions where prefixsums are the same will be equal to zero""" 76 | def countprefixsums(nums): 77 | prefixsumbyvalue = {0 : 1} # it means that sequence with sum 0 we met 1 time 78 | nowsum = 0 79 | for now in nums: 80 | nowsum += now 81 | if nowsum not in prefixsumbyvalue: 82 | prefixsumbyvalue[nowsum] = 0 83 | prefixsumbyvalue[nowsum] += 1 # for an element in our dict with current prefixsum we raise a number of appearances by 1 84 | return prefixsumbyvalue 85 | 86 | def countzerosumranges3(prefixsumbyvalue): 87 | cntranges = 0 88 | for nowsum in prefixsumbyvalue: # run through all of the prefixsums 89 | cntsum = prefixsumbyvalue[nowsum] 90 | cntranges += cntsum * (cntsum -1) // 2 # count a number of pairs with formula 91 | return cntranges 92 | 93 | 94 | """Task3""" 95 | """Here are sorted sequence with len N and number K. We need to find a number of pairs A,B. B-A > K""" 96 | 97 | """Solution 1 O(N^2) difficulty""" 98 | """Run through all of the pairs of numbers and check the condition""" 99 | def cntpairswithdiffgtk(sortednums, k): 100 | cntpairs = 0 101 | for first in range(len(sortednums)): 102 | for last in range(first, len(sortednums)): 103 | if sortednums[last] - sortednums[first] > k: 104 | cntpairs += 1 105 | return cntpairs 106 | 107 | """Solution 2 O(N) difficulty""" 108 | """Take a min number and find a first suitable greater one. All of the numbers which are greater than the first suitable are suitable too. 109 | Take as a min number the next number, and lets move a pointer of the first suitable greater one from the position where it is""" 110 | def cntpairswithdiffgtk2(sortednums, k): 111 | cntpairs = 0 112 | last = 0 113 | for first in range(len(sortednums)): 114 | while last < len(sortednums) and sortednums[last] - sortednums[first] <= k: # conditions check goes from left to right, so if the first statement isn't true the second one won't be called 115 | last += 1 116 | cntpairs += len(sortednums) - last 117 | return cntpairs 118 | 119 | """Task4""" 120 | """Football player has one numerical characteristic - professionalism. A team called solid if the professionalism of one player is not greater than the sum of 121 | professionalism of any two other players. A team consists of any number of players. 122 | We have a sorted sequence with len N - professionalism of players. We need to find a maximum sum of professionalism for solid team""" 123 | 124 | """Solution 1""" 125 | def bestteamsum(players): 126 | bestsum = 0 127 | nowsum = 0 128 | last = 0 129 | for first in range(len(players)): 130 | while last < len(players) and (last == first or players[first] + players [first + 1] >= players[last]): 131 | nowsum += players[last] 132 | last += 1 133 | bestsum = max(bestsum, nowsum) 134 | nowsum -= players[first] 135 | return bestsum 136 | 137 | 138 | """Task5, Merge!""" 139 | 140 | """Here are two sorted sequences with len N and len M""" 141 | """We need to make one sorted sequence of these two""" 142 | 143 | """Solution 1""" 144 | """Lets set a pointers to the beginning of each of the sequences. Choose the one which pointed on the lower number, put this number to the result and move the pointer""" 145 | def merge(nums1, nums2): 146 | merged = [0] * (len(nums1) + len(nums2)) 147 | first1 = first2 = 0 148 | inf = max(nums1[-1], nums2[-1] +1) 149 | nums1.append(inf) 150 | nums2.append(inf) 151 | for k in range(len(nums1) + len(nums2) -2): 152 | if nums1[first1] <= nums2[first2]: 153 | merged[k] = nums1[first1] 154 | first1 += 1 155 | else: 156 | merged[k] = nums2[first2] 157 | first2 += 1 158 | nums1.pop() 159 | nums2.pop() 160 | 161 | return merged 162 | 163 | 164 | print(merge([2,3,15,99,100,101,102,102],[66,77,78,78,79,200])) 165 | 166 | """Solution 2 O(N+M) difficulty""" 167 | def merge2(nums1, nums2): 168 | merged = [0] * (len(nums1) + len(nums2)) 169 | first1 = first2 = 0 170 | for k in range(len(nums1) + len(nums2)): 171 | if first1 != len(nums1) and (first2 == len(nums2) or nums1[first1] <= nums2[first2]): 172 | merged[k] = nums1[first1] 173 | first1 += 1 174 | else: 175 | merged[k] = nums2[first2] 176 | first2 += 1 177 | return merged 178 | 179 | 180 | print(merge2([2,3,15,99,100,101,102,102],[66,77,78,78,79,200])) 181 | -------------------------------------------------------------------------------- /Lesson4_Dictionary.py: -------------------------------------------------------------------------------- 1 | def countsort(seq): 2 | minval = min(seq) # find minimum in our seq 3 | maxval = max(seq) # find maximum in our seq 4 | k = (maxval - minval + 1) # find k as a result of subtraction between max and min in our seq + 1 5 | count = [0] * k # create an array with 0's multiply k-times 6 | for now in seq: # for each element in our seq 7 | count[now - minval] += 1 # we add 1 to the block in our array with number equal to the result of subtraction between current element and minimum 8 | nowpos = 0 # set a new variable with value 0 9 | for val in range(0, k): # run through values of our blocks in array 10 | for i in range(count[val]): # run through indexes of blocks with values 11 | seq[nowpos] = val + minval # sort an elements, add a value of the block to the minimum 12 | nowpos += 1 # change position + 1 13 | return seq 14 | 15 | print (countsort([23,15,8,99,155,6,7,11,7])) 16 | 17 | 18 | """Task 1""" 19 | """Here are two numbers X, Y without 0 at first position""" 20 | """ We need to check whether it is possible to get a second number from the first one, making changes of num positions""" 21 | 22 | 23 | def isdigitpermutation(x,y): 24 | def countdigits(num): 25 | digitcount = [0] * 10 # we make an array with 10 zeros 26 | while num > 0: # while our num is greater (>1) than 0 27 | lastdigit = num % 10 # we save a last number of it in the the variable (modulo) 28 | digitcount[lastdigit] += 1 # add an 1 to to the box in the array with index of our variable 29 | num //= 10 # and a new number will be a result of the float division by 10 30 | return digitcount # we return an array 31 | 32 | digitsx = countdigits(x) # count a number of occurrences for each digit in our first number 33 | digitsy = countdigits(y) # count a number of occurrences for each digit in our second number 34 | for digit in range(10): # run through each box in our array 35 | if digitsx[digit] != digitsy[digit]: # if number of occurrences for each digit in two numbers is not equal 36 | return False # we return false 37 | return True # else we return true 38 | 39 | 40 | print (isdigitpermutation(2021,1220)) 41 | 42 | """Task 2""" 43 | """We've got a chess board with len NxN with M-number of rooks (rook can beat all squares horizontally or vertically till the nearest occupied)""" 44 | """ We need to define how many pairs of rooks can beat each other. Rooks are set with two numbers I and J which are their coordinates""" 45 | """ 1 <= N <= 10**9, 0 <= M <= 2 * 10**5""" 46 | 47 | """Solution""" 48 | """For each occupied horizontally and vertically square we will save a number of rooks on them""" 49 | """Number of pairs in horizontal or vertical is equal to the number of rooks - 1""" 50 | """Count a total sum by adding all pairs in horizontal and vertical""" 51 | 52 | def countbeatingrooks(rookcoords): 53 | def addrook(roworcol, key): 54 | if key not in roworcol: 55 | roworcol[key] = 0 56 | roworcol[key] += 1 57 | 58 | def countpairs(roworcol): 59 | pairs = 0 60 | for key in roworcol: 61 | pairs += roworcol[key] -1 62 | return pairs 63 | 64 | rooksinrow = {} 65 | rooksincol = {} 66 | for row, col in rookcoords: 67 | addrook(rooksinrow, row) 68 | addrook(rooksincol, col) 69 | return countpairs(rooksinrow) + countpairs(rooksincol) 70 | 71 | print (countbeatingrooks([(3,4),(3,5),(4,3),(6,8),(10,10)])) 72 | 73 | """ If we need to count a number of queens, their coordinates can be set by I+J and I-J in diagonal""" 74 | 75 | """Task 3""" 76 | """Here is a string S""" 77 | """We need to receive a histogram as an output""" """Codes of symbols are sorted""" 78 | """ S = Hello, world! -->""" 79 | 80 | """ #""" 81 | """ ##""" 82 | """##########""" 83 | """ !,Hdelorw """ 84 | 85 | """Solution""" 86 | """For each symbol in the dictionary we count how many times it meets""" 87 | """Find the most most frequent one and run through the amount from this number till the 1""" 88 | """Run through all sorted keys and if the number of keys is greater than our counter - output an #""" 89 | 90 | def printchart(s): 91 | symcount = {} 92 | maxsymcount = 0 93 | for sym in s: 94 | if sym not in symcount: 95 | symcount[sym] = 0 96 | symcount[sym] += 1 97 | maxsymcount = max(maxsymcount, symcount[sym]) 98 | sorteduniqsyms = sorted(symcount.keys()) 99 | for row in range(maxsymcount, 0, -1): 100 | for sym in sorteduniqsyms: 101 | if symcount[sym] >= row: 102 | print('#', end ='') 103 | else: 104 | print(' ', end ='') 105 | print() 106 | print(''.join(sorteduniqsyms)) 107 | 108 | printchart("Hello world!") 109 | 110 | """Task 4""" 111 | """Group words by the same letters""" 112 | """Sample Input: ["eat", "tea", "tan", "ate", "nat", "bat"]""" 113 | """Sample Output: [["ate", "eat", "tea",], ["nat", "tan"], ["bat"]]""" 114 | 115 | """Solution 1""" 116 | def groupwords(words): 117 | groups = {} 118 | for word in words: 119 | sortedword = "".join(sorted(word)) ### see below 120 | if sortedword not in groups: 121 | groups[sortedword] = [] 122 | groups[sortedword].append(word) 123 | ans = [] 124 | for sortedword in groups: 125 | ans.append(groups[sortedword]) 126 | return ans 127 | 128 | print(groupwords(["eat", "tea", "tan", "ate", "nat", "bat"])) 129 | 130 | # We suppose if len of word will be greater than N, sort will take O(NlogN) 131 | # Amount of different chars in word is K <= N, We can count amount of each one for O(N) difficulty 132 | # And then sort for O(KlogK), theoretically... 133 | 134 | """Solution2""" 135 | def groupwords2(words): 136 | def keybyword(word): 137 | return "".join(sorted(word)) # it could work slow on practice 138 | 139 | groups = {} 140 | for word in words: 141 | groupkey = keybyword(word) 142 | if groupkey not in groups: 143 | groups[groupkey] = [] 144 | groups[groupkey].append(word) 145 | ans = [] 146 | for groupkey in groups: 147 | ans.append(groups[groupkey]) 148 | return ans 149 | 150 | print(groupwords2(["eat", "tea", "tan", "ate", "nat", "bat"])) 151 | 152 | """Solution3""" 153 | # Works slow. Kind of weird optimization ;)) 154 | def groupwords3(words): 155 | def keybyword(word): 156 | symcnt = {} 157 | for sym in word: 158 | if sym not in symcnt: 159 | symcnt[sym] = 0 160 | symcnt[sym] += 1 161 | lst = [] 162 | for sym in sorted(symcnt.keys()): 163 | lst.append(sym) 164 | lst.append(str(symcnt[sym])) 165 | return "".join(lst) # here we have a list like a3b1 from aaba 166 | 167 | groups = {} 168 | for word in words: 169 | groupkey = keybyword(word) 170 | if groupkey not in groups: 171 | groups[groupkey] = [] 172 | groups[groupkey].append(word) 173 | ans = [] 174 | for groupkey in groups: 175 | ans.append(groups[groupkey]) 176 | return ans 177 | 178 | print(groupwords3(["eat", "tea", "tan", "ate", "nat", "bat"])) 179 | -------------------------------------------------------------------------------- /Lesson2_LinearSearchFunctions.py: -------------------------------------------------------------------------------- 1 | seq1 = [2,7,8,0,3,5,15,7,0,5,15,10,11] 2 | print ("The length of a seq: ", len(seq1)) 3 | 4 | for i in range(len(seq1)-1,-1,-1): 5 | print ("pos:", i, "number:", seq1[i]) 6 | if seq1[i] == 2: 7 | print ("Bingo!") 8 | else: 9 | print ("There is no such number!") 10 | 11 | """Linear Search""" 12 | 13 | """Task1""" 14 | """Here is a sequence with length N, find a first(left) 15 | position of x in it""" 16 | 17 | def findx(seq, x): 18 | for i in range(0,len(seq)-1): # run through the indexes from 0! till the end 19 | ans = -1 # put some value to make a check (to be sure that we meet an element first time) 20 | if ans == -1 and seq[i] == x: # if we meet it first time and the element is the one we search for 21 | ans = i # put an index of the element into the answer 22 | return ("pos:", ans) # return position 23 | 24 | print(findx([2,7,8,0,3,5,15,7,0,5,15,10,11],5)) 25 | 26 | 27 | """Task2""" 28 | """Here is a sequence with length N, find a last(right) 29 | position of x in it""" 30 | 31 | def findrightx(seq, x): 32 | for i in range(len(seq)-1, 0, -1):# run through the indexes from the end to 0! 33 | ans = -1 # put some value to make a check (to be sure that we meet an element first time) 34 | if ans == -1 and seq[i] == x: # if we meet it first time and the element is the one we search for 35 | ans = i # put an index of the element into the answer 36 | return ("pos:", ans) # return position 37 | 38 | 39 | print(findrightx([2,7,8,0,3,5,15,7,0,5,15,10,11],7)) 40 | 41 | """Task3""" 42 | """Find a maximum in a sequence with length N(N>0)""" 43 | 44 | def findmax(seq): 45 | ans = 0 # put an index of max element 46 | for i in range(1,len(seq)): # run through the indexes from 1 till the end 47 | if seq[i] > seq[ans]: # compare current element and best(max) 48 | ans = i # put an index of new max element(rewrite) 49 | return seq[ans] # return a max element 50 | 51 | print(findmax([2,7,8,0,3,5,15,7,0,5,15,10,11])) 52 | 53 | """Task4""" 54 | """Here is a sequence with length N(N>1)""" 55 | """Find a second maximum(which will be a maximum if we delete one maximum!)""" 56 | 57 | def findmax2(seq): 58 | max1 = max(seq[0],seq[1]) # find a max from elements on indexes 0,1 and set a value to variable max1 59 | max2 = min(seq[0],seq[1]) # find a min from elements on indexes 0,1 and set a value to variable max2 60 | for i in range(2,len(seq)): # run through the indexes from 2 till the end 61 | if seq[i] > max1: # compare current element with value of max1, and if it is greater (>) than max1 62 | max2 = max1 # set a value of max1 to variable max2 then 63 | max1 = seq[i] # set a value of current element to variable max1 64 | elif seq[i] > max2: # also if value of current element is greater (>) than value of variable max2 65 | max2 = seq[i] # set a value of current element to variable max2 66 | return max2 # return value of variable max2 67 | 68 | print(findmax2([2,7,8,0,3,5,15,16,16,7,0,5,15,10,11])) 69 | 70 | """Task5""" 71 | """Here is a sequence with length N""" 72 | """Find a minimum even number or return -1 if there is no such number""" 73 | 74 | def findmineven(seq): 75 | ans = -1 # put some value to make a check (to be sure that we meet an element first time) 76 | """flag = False""" # also possible and better way, create a boolean variable 77 | for i in range(len(seq)): # run through the elements 78 | if seq[i]%2 == 0 and (ans == -1 or seq[i] < ans): # or use this statement - (not flag or seq[i] < ans): # if modulo = 0 and also if we meet an element first time or value of element is lower (<) than value in variable ans 79 | ans = seq[i] # set a value of element to variable ans 80 | #and also this statement - (flag = True) # change a value of boolean variable to True 81 | return ans # return value of variable ans 82 | 83 | print(findmineven([7,1,3,5,15,7,16,1,5,15,11])) 84 | 85 | """Task6""" 86 | """Here is a sequence of words""" 87 | """Return all the shortest ones via space""" 88 | def shortwords(words): 89 | minlen = len(words[0]) # set a value of length of first element(0 index) to variable minlen 90 | for word in words: # run through elements 91 | if len(word) < minlen: # if length of current element is lower (<) than value of variable minlen then 92 | minlen = len(word) # set a value of length of current element to variable minlen 93 | ans = [] # set a value of empty list[] to variable ans 94 | for word in words: # run through elements second time 95 | if len(word) == minlen: #if length of current element is equal to the value of variable minlen then 96 | ans.append(word) # append(add) current element to the list[] ans 97 | return " ".join(ans) # return the list[] ans with elements join via space 98 | 99 | print(shortwords(["baba","ba","la","lollo","no","yes","go"])) 100 | 101 | 102 | """Task7""" 103 | """ Pitecraft! We have got an island which is made of blocks 1x1 with different height of columns. Outside there is the sea.""" 104 | """ The rain fell down, and after it all of our lowlands are full of water. Excessive water flows directly to the sea, water level stays the same """ 105 | """ Find a number of blocks which consists of the water""" 106 | def isleflood(h): 107 | maxpos = 0 # assume that height of the first element is max, and set it's index 0 to the variable maxpos 108 | for i in range(len(h)):# run through the indexes of all elements(blocks) 109 | if h[i] > h[maxpos]:# if value of the current element is greater (>) than value of element with index maxpos(0 index first turn): 110 | maxpos = i # rewrite the index of max element, and set to index of current element 111 | ans = 0 # set a value (0) to new variable answer (here we are collecting blocks of water) 112 | nowm = 0 # set a value (0) - to new variable nowm (new maximum) 113 | for i in range(maxpos): # run through the indexes of all elements from the left till our maxpos(index of max element) 114 | if h[i] > nowm: # if value of the current element is greater (>) than value of element nowm(0 - first turn): 115 | nowm = h[i] # set a value of current element to the variable nowm 116 | ans += nowm - h[i] # add to the total value of blocks of water(variable ans) the difference between nowm(new maximum) and current element 117 | nowm = 0 # once again set a value (0) - to new variable nowm (new maximum) 118 | for i in range(len(h)-1,maxpos,-1):# run through the indexes of all elements from right till our maxpos(index of max element) 119 | if h[i] > nowm: # if value of the current element is greater (>) than value of element nowm(0 - first turn): 120 | nowm = h[i] # set a value of current element to the variable nowm 121 | ans += nowm - h[i] # add to the total value of blocks of water(variable ans) the difference between nowm(new maximum) and current element 122 | return ans # return value of total blocks of water 123 | 124 | print(isleflood([7,1,3,5,15,7,16,1,5,15,11])) 125 | 126 | """Task 8""" 127 | """ RLE. Here is a string of letters A-Z. It can be empty""" 128 | """ We need to write a function which will return the string without duplicates, and replace them with a values of total number of duplicates for each char!""" 129 | """ At first, let's see how to solve an easier problem, We just want to replace duplicates""" 130 | def easypeasy(s): 131 | lastsym = s[0] #set a char with index 0 to a variable lastsym 132 | ans = [] # set a value of empty list to a variable ans 133 | for i in range(1,len(s)): # run through the indexes of char 134 | if s[i] != lastsym: # if current char not equal to our last char saved in variable lastsym then 135 | ans.append(lastsym) # append(add) current char to the list[] ans 136 | lastsym = s[i] # set current char as lastsym 137 | ans.append(lastsym) # add lastsym to the result in list[] ans 138 | return "".join(ans) #concatenate chars without space 139 | 140 | print(easypeasy("AAAoooooEEEjjjKKlolOKoooKK")) 141 | 142 | """This is our solution for general case""" 143 | 144 | def rle(s): 145 | def pack(s, cnt): 146 | if cnt > 1: 147 | return s + str(cnt) 148 | return s 149 | lastsym = s[0] #set a char with index 0 to a variable lastsym 150 | lastpos = 0 #set a position of a char as 0 151 | ans= [] # set a value of empty list to a variable ans 152 | for i in range(1,len(s)):# run through the indexes of char 153 | if s[i] != lastsym: # if current char not equal to our last char saved in variable lastsym then 154 | ans.append(pack(lastsym,i-lastpos))# we call a function pack and add a result of it to the list[] ans 155 | lastpos = i # set an index of current char as lastpos 156 | lastsym = s[i] # set current char as lastsym 157 | ans.append(pack(s[lastpos],len(s)-lastpos)) # add call a function pack and add a result of it to list[] ans 158 | return "".join(ans) #concatenate chars without space 159 | """How pack function is working here. First time we put as arguments lastsym on first place and result of subtraction between current index(i) 160 | and index of last position as a second argument. If this result is greater (>) than 1 we return lastsym + string value of previous subtraction (this result). If it is not true, we return lastsym""" 161 | """Second time after the loop we call this function again. And put as arguments a char with index of lastpos at first place, and as a second argument we put the result of subtraction between value of len(s) 162 | and index of last position. That way we check if lastsym has duplicates and if it is so, we add a number of them to lastsym or just return lastsym""" 163 | 164 | print(rle("AAAoooooEEEjjjKKlolOKoooKK")) 165 | -------------------------------------------------------------------------------- /Lesson7_EventsSort.py: -------------------------------------------------------------------------------- 1 | """Task1""" 2 | """Web-site was visited by N-number of visitors""" 3 | """For each visitor we know TimeIn, TimeOut. We suppose that visitor was at the web-site from TimeIn till TimeOut inclusively""" 4 | """Lets count max number of visitors that were online simultaneously""" 5 | 6 | """Solution""" 7 | """For each visitor we create two events - enter(in) and exit(out)""" 8 | """Every event is a pair, where the first number is time of the event, second one is the type of the event""" 9 | 10 | def maxvisitorsonline(n, tin, tout): 11 | events = [] 12 | for i in range(n): 13 | events.append((tin[i], -1))# man in, and -1 is lower(< 1) - (priority 1) 14 | events.append((tout[i], 1))# man out, and 1 is greater(> -1) - (priority 2) 15 | events.sort() 16 | online = 0 17 | maxonline = 0 18 | for event in events: 19 | if event[1] == -1: # if priority of event is 1(lowest number here) 20 | online += 1 21 | elif event[1] == 1: 22 | online -= 1 23 | maxonline = max(online, maxonline) 24 | return maxonline 25 | 26 | print(maxvisitorsonline(5,[7.15,7.20,9.00,11.00,11.30],[9.00,9.17,11.25,16.00,17.00])) 27 | 28 | """Task2""" 29 | """Web-site was visited by N-number of visitors""" 30 | """For each visitor we know TimeIn, TimeOut. We suppose that visitor was at the web-site from TimeIn till TimeOut inclusively""" 31 | """We should define time interval when at least one visitor were online""" 32 | 33 | """Solution""" 34 | """If we came to the event with a positive counter of people number, then there was someone online before current event and previous one""" 35 | """We will add a time interval between these events to the answer""" 36 | 37 | def timewithvisitors(n, tin, tout): 38 | events = [] 39 | for i in range(n): 40 | events.append((tin[i], -1))# man in, and -1 is lower(< 1) - (priority 1) 41 | events.append((tout[i], 1))# man out, and 1 is greater(> -1) - (priority 2) 42 | events.sort() 43 | online = 0 44 | notemptytime = 0 45 | for i in range(len(events)): 46 | if online > 0: 47 | notemptytime += events[i][0] - events[i-1][0] 48 | elif events[i][1] == -1: 49 | online += 1 50 | else: 51 | online -= 1 52 | return notemptytime 53 | 54 | print(timewithvisitors(5,[7.15,7.20,9.00,11.00,11.30],[9.00,9.17,11.25,16.00,17.00])) 55 | 56 | """Task3""" 57 | """Web-site was visited by N-number of visitors""" 58 | """For each visitor we know TimeIn, TimeOut. We suppose that visitor was at the web-site from TimeIn till TimeOut inclusively""" 59 | """Boss visited the web-site M-times, at time-moments "Boss" and watched how many people were online. Boss visits are sorted by time""" 60 | """We should define which values of the counter of people online he saw.""" 61 | 62 | """Solution""" 63 | """Lets create a new event - entrance of the Boss and if this event happens we will save a current number of visitors online""" 64 | 65 | def bosscounters(n, tin, tout, m, tboss): 66 | events = [] 67 | for i in range(n): 68 | events.append((tin[i], -1))# man in, and -1 is lower(< 1) - (priority 1) 69 | events.append((tout[i], 1))# man out, and 1 is greater(> -1) - (priority 3) 70 | for i in range(m): 71 | events.append((tboss[i], 0))# boss in, and 0 is before man out and after man in - (priority 2) 72 | events.sort() 73 | online = 0 74 | bossans = [] 75 | for i in range(len(events)): 76 | if events[i][1] == -1: 77 | online += 1 78 | elif events[i][1] == 1: 79 | online -= 1 80 | else: 81 | bossans.append(online) 82 | return bossans 83 | 84 | print(bosscounters(5,[7.15,7.20,9.00,11.00,11.30],[9.00,9.17,11.25,16.00,17.00],3,[7.45,11.27,14.00])) 85 | 86 | 87 | 88 | """Task 4""" 89 | """There are N-number of parking places on the parking in the shopping center(numbered from 1 to N)""" 90 | """There were M-number of cars during the day. Some of them are long-one and they occupied some of the parking places which are next to each other""" 91 | """For each car we know TimeIn and TimeOut, and two numbers - start number and the last number of parking place which were occupied""" 92 | """If in some moment in time one car moved from the parking place, than we suggest that parking place is empty and at the same moment in time it can be occupied by another car""" 93 | """We should define if there was a time moment when all of the parking places were occupied""" 94 | 95 | """Solution""" 96 | """Our events are - car arrival and car departure. Departure should be before arrival! We will hold an occupied parking places. And if after some event counter is equal to N, then there were such moments when all of the parking places were occupied """ 97 | 98 | def isparkingfull(cars, n): 99 | events = [] 100 | for car in cars: 101 | timein, timeout, placefrom, placeto = car 102 | events.append((timein, 1, placeto - placefrom +1)) 103 | events.append((timeout, -1, placeto - placefrom +1)) 104 | events.sort() 105 | occupied = 0 106 | for i in range(len(events)): 107 | if events[i][1] == -1: 108 | occupied -= events[i][2] 109 | elif events[i][1] == 1: 110 | occupied += events[i][2] 111 | if occupied == n: 112 | return True 113 | return False 114 | 115 | 116 | print(isparkingfull(([7.15,18.00,1,2],[11.00,11.45,3,3],[11.30,14.00,4,5],[7.00,9.15,5,5],[16.00,18.45,4,4]),5)) 117 | 118 | """Task 5""" 119 | """There are N-number of parking places on the parking in the shopping center(numbered from 1 to N)""" 120 | """There were M-number of cars during the day. Some of them are long-one and they occupied some of the parking places which are next to each other""" 121 | """For each car we know TimeIn and TimeOut, and two numbers - start number and the last number of parking place which were occupied""" 122 | """If in some moment in time one car moved from the parking place, than we suggest that parking place is empty and at the same moment in time it can be occupied by another car""" 123 | """We should define if there was a time moment when all of the parking places were occupied. Also we should define min number of cars which occupied all of the parking places""" 124 | """If there is no such moment - we should return M+1""" 125 | 126 | """Solution""" 127 | """Lets add one more counter for number of cars. And when all parking places are occupied we will refresh a min number of cars""" 128 | 129 | def mincarsonfullparking(cars, n): 130 | events = [] 131 | for car in cars: 132 | timein, timeout, placefrom, placeto = car 133 | events.append((timein, 1, placeto - placefrom +1)) 134 | events.append((timeout, -1, placeto - placefrom +1)) 135 | 136 | events.sort() 137 | print(events) 138 | occupied = 0 139 | nowcars = 0 140 | mincars = len(cars) + 1 141 | for i in range(len(events)): 142 | if events[i][1] == -1: 143 | occupied -= events[i][2] 144 | nowcars -= 1 145 | elif events[i][1] == 1: 146 | occupied += events[i][2] 147 | nowcars += 1 148 | if occupied == n: 149 | mincars = min(mincars,nowcars) 150 | return mincars 151 | 152 | 153 | print(mincarsonfullparking(([7.15,18.00,1,2],[11.00,11.45,3,3],[11.30,14.00,4,5],[7.00,9.15,5,5],[16.00,18.45,4,4]),5)) 154 | 155 | """Task 6""" 156 | """There are N-number of parking places on the parking in the shopping center(numbered from 1 to N)""" 157 | """There were M-number of cars during the day. Some of them are long-one and they occupied some of the parking places which are next to each other""" 158 | """For each car we know TimeIn and TimeOut, and two numbers - start number and the last number of parking place which were occupied""" 159 | """If in some moment in time one car moved from the parking place, than we suggest that parking place is empty and at the same moment in time it can be occupied by another car""" 160 | """We should define if there was a time moment when all of the parking places were occupied. Also we should define min number of cars which occupied all of the parking places""" 161 | """Also we should define numbers of these cars in a priority they were specified in the list. If there is no such moment when all parking spaces were occupied - we should return an empty list""" 162 | 163 | """Solution""" 164 | """Lets add a number of car to the events. If there is a new minimum, we just copy a current state to the answer """ 165 | 166 | 167 | def mincarsonfullparking2(cars, n): 168 | events = [] 169 | for i in range(len(cars)): 170 | timein, timeout, placefrom, placeto = cars[i] 171 | events.append((timein, 1, placeto - placefrom +1, i)) 172 | events.append((timeout, -1, placeto - placefrom +1, i)) 173 | events.sort() 174 | occupied = 0 175 | nowcars = 0 176 | mincars = len(cars) + 1 177 | carnums = set() 178 | bestcarnums = set() 179 | for i in range(len(events)): 180 | if events[i][1] == -1: 181 | occupied -= events[i][2] 182 | nowcars -= 1 183 | carnums.remove(events[i][3]) 184 | elif events[i][1] == 1: 185 | occupied += events[i][2] 186 | nowcars += 1 187 | carnums.add(events[i][3]) 188 | if occupied == n and nowcars < mincars: 189 | bestcarnums = carnums.copy() 190 | mincars = nowcars 191 | return sorted(bestcarnums) 192 | 193 | 194 | print(mincarsonfullparking2(([7.15,18.00,1,2],[11.00,11.45,3,3],[11.30,14.00,4,5],[7.00,9.15,5,5],[16.00,18.45,4,4]),5)) 195 | 196 | """Solution 2, Effective""" 197 | 198 | def mincarsonfullparking3(cars,n): 199 | events = [] 200 | for i in range(len(cars)): 201 | timein, timeout, placefrom, placeto = cars[i] 202 | events.append((timein, 1, placeto - placefrom +1, i)) 203 | events.append((timeout, -1, placeto - placefrom +1, i)) 204 | events.sort() 205 | occupied = 0 206 | nowcars = 0 207 | mincars = len(cars) + 1 208 | for i in range(len(events)): 209 | if events[i][1] == -1: 210 | occupied -= events[i][2] 211 | nowcars -= 1 212 | elif events[i][1] == 1: 213 | occupied += events[i][2] 214 | nowcars += 1 215 | if occupied == n and nowcars < mincars: 216 | mincars = nowcars 217 | carnums = set() 218 | nowcars = 0 219 | for i in range(len(events)): 220 | if events[i][1] == -1: 221 | occupied -= events[i][2] 222 | nowcars -= 1 223 | carnums.remove(events[i][3]) 224 | elif events[i][1] == 1: 225 | occupied += events[i][2] 226 | nowcars += 1 227 | carnums.add(events[i][3]) 228 | if occupied == n and nowcars == mincars: 229 | return sorted(carnums) 230 | return set() 231 | 232 | print(mincarsonfullparking3(([7.15,18.00,1,2],[11.00,11.45,3,3],[11.30,14.00,4,5],[7.00,9.15,5,5],[16.00,18.45,4,4]),5)) 233 | --------------------------------------------------------------------------------