├── isIdentityMatrix ├── README.md └── isIdentityMatrix.py ├── shapeArea ├── area.png ├── shapeArea.py └── README.md ├── Arcade_The_Core └── Corner_of_0s_and_1s │ ├── killKthBit │ ├── solver.py │ └── README.md │ ├── mirrorBits │ ├── solver.py │ └── README.md │ ├── secondRightmostZeroBit │ ├── solver.py │ └── README.md │ ├── rangeBitCount │ ├── solver.py │ └── README.md │ ├── swapAdjacentBits │ ├── solver.py │ └── README.md │ └── arrayPacking │ ├── README.md │ └── solver.py ├── Quora-Bot-2 ├── example.png ├── solver.py └── README.md ├── MinesweeperGame ├── example.png ├── README.md └── minesweeper.py ├── avoidObstacles ├── example.png ├── avoidObstacles.py └── README.md ├── SortedBinaryTreeLeaves ├── tree.png ├── README.md └── solver.py ├── rotateImage ├── rotateImage.py └── README.md ├── Quora-Bot-3_Knapsack_with_Dynamic_Programming ├── example.png ├── solver.py └── README.md ├── Thumbtack-Bot ├── thumbtack-bot-task1 │ ├── solver.py │ └── README.md └── thumbtack-bot-task2 │ ├── solver.py │ └── README.md ├── arrayChange ├── README.md └── arrayChange.py ├── firstDuplicate ├── firstDuplicate.py └── README.md ├── sortByHeight ├── sortByHeight.py └── README.md ├── climbingStairs ├── solver.py └── README.md ├── tellTime ├── README.md └── tellTime.py ├── LinkedLists ├── removeKFromList │ ├── README.md │ └── removeKFromList.py └── addTwoHugeNumbers │ ├── README.md │ └── addTwoHugeNumbers.py ├── phoneCall ├── phoneCall.py └── README.md ├── README.md ├── palindromeRearranging ├── palindromeRearranging.py └── README.md ├── isIPv4Address ├── isIPv4Address.py └── README.md ├── groupingDishes ├── solver.py └── README.md ├── incrementCipher ├── incrementCipher.py └── README.md ├── minSubstringWithAllChars ├── README.md └── solver.py ├── boxBlurImage ├── boxBlurImage.py └── README.md ├── firstNotRepeatingCharacter ├── README.md └── firstNotRepeatingCharacter.py ├── arraysAreSimilar ├── arraysAreSimilar.py └── README.md ├── HasPathWithGivenSum ├── solver.py └── README.md ├── reverseParentheses ├── reverseParentheses.py └── README.md ├── makingAnagrams ├── README.md └── makingAnagrams.py ├── IsCryptarithmSolution ├── isCryptSolution.py └── README.md ├── findPathInMatrix ├── README.md └── findPathInMatrix.py ├── EvenTextWrap ├── README.md └── solver.py ├── IsTreeSymmetric ├── solver.py └── README.md ├── Quora-Bot-1 ├── solver.py └── README.md └── Sudoku2 ├── sudoku2.py └── README.md /isIdentityMatrix/README.md: -------------------------------------------------------------------------------- 1 | Check if the given matrix is an identity matrix. 2 | -------------------------------------------------------------------------------- /shapeArea/area.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvitsios/codesignal-my-solutions/HEAD/shapeArea/area.png -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/killKthBit/solver.py: -------------------------------------------------------------------------------- 1 | def killKthBit(n, k): 2 | return n & ~(1 << (k -1)) 3 | -------------------------------------------------------------------------------- /Quora-Bot-2/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvitsios/codesignal-my-solutions/HEAD/Quora-Bot-2/example.png -------------------------------------------------------------------------------- /MinesweeperGame/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvitsios/codesignal-my-solutions/HEAD/MinesweeperGame/example.png -------------------------------------------------------------------------------- /avoidObstacles/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvitsios/codesignal-my-solutions/HEAD/avoidObstacles/example.png -------------------------------------------------------------------------------- /SortedBinaryTreeLeaves/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvitsios/codesignal-my-solutions/HEAD/SortedBinaryTreeLeaves/tree.png -------------------------------------------------------------------------------- /rotateImage/rotateImage.py: -------------------------------------------------------------------------------- 1 | def rotateImage(a): 2 | 3 | a = list(zip(*a)) 4 | a = [list(l[::-1]) for l in a] 5 | 6 | return a -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/mirrorBits/solver.py: -------------------------------------------------------------------------------- 1 | def mirrorBits(a): 2 | 3 | s = str(bin(a)).replace('0b', '') 4 | 5 | return int(s[::-1], 2) 6 | -------------------------------------------------------------------------------- /shapeArea/shapeArea.py: -------------------------------------------------------------------------------- 1 | def shapeArea(n): 2 | 3 | area = 1 4 | 5 | for i in xrange(2, n+1): 6 | area += (i-1)*4 7 | 8 | return area -------------------------------------------------------------------------------- /Quora-Bot-3_Knapsack_with_Dynamic_Programming/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvitsios/codesignal-my-solutions/HEAD/Quora-Bot-3_Knapsack_with_Dynamic_Programming/example.png -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/secondRightmostZeroBit/solver.py: -------------------------------------------------------------------------------- 1 | def secondRightmostZeroBit(n): 2 | return 2**([m.start() for m in re.finditer(r"0", str(bin(n))[::-1][:-2])][1]) 3 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/rangeBitCount/solver.py: -------------------------------------------------------------------------------- 1 | def rangeBitCount(a, b): 2 | 3 | s = 0 4 | for n in range(a, b+1): 5 | s += str(bin(n)).count('1') 6 | 7 | return s 8 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/swapAdjacentBits/solver.py: -------------------------------------------------------------------------------- 1 | def swapAdjacentBits(n): 2 | return int(''.join([str(bin(n))[::-1][i:i+2].replace('b','0') for i in range(0, len(str(bin(n)))-2, 2)][::-1]), 2) 3 | 4 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/arrayPacking/README.md: -------------------------------------------------------------------------------- 1 | **Problem definition**: 2 | [https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/KeMqde6oqfF5wBXxf](https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/KeMqde6oqfF5wBXxf) 3 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/arrayPacking/solver.py: -------------------------------------------------------------------------------- 1 | def arrayPacking(a): 2 | 3 | res = 0 4 | for i in range(len(a)): 5 | 6 | b = a[i] 7 | 8 | b = b << 8 * i 9 | 10 | res = res | b 11 | 12 | return res 13 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/killKthBit/README.md: -------------------------------------------------------------------------------- 1 | **Problem definition**: 2 | [https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/b5z4P2r2CGCtf8HCR](https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/b5z4P2r2CGCtf8HCR) 3 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/swapAdjacentBits/README.md: -------------------------------------------------------------------------------- 1 | **Problem definition**: 2 | [https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/dShYZZT4WmvpmfpgB](https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/dShYZZT4WmvpmfpgB) 3 | -------------------------------------------------------------------------------- /avoidObstacles/avoidObstacles.py: -------------------------------------------------------------------------------- 1 | def avoidObstacles(inputArray): 2 | 3 | for i in range(1, max(inputArray)): 4 | divs = any([x for x in inputArray if not x%i]) 5 | if not divs: 6 | return i 7 | 8 | return max(inputArray) + 1 -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/secondRightmostZeroBit/README.md: -------------------------------------------------------------------------------- 1 | **Problem definition**: 2 | [https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/9nSj6DgqLDsBePJha](https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/9nSj6DgqLDsBePJha) 3 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/mirrorBits/README.md: -------------------------------------------------------------------------------- 1 | **Problem definition**: 2 | [https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/e3zfPNTwTa9qTQzcX/solutions/u9uwoqvbxDjySywCo](https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/e3zfPNTwTa9qTQzcX/solutions/u9uwoqvbxDjySywCo) 3 | -------------------------------------------------------------------------------- /Arcade_The_Core/Corner_of_0s_and_1s/rangeBitCount/README.md: -------------------------------------------------------------------------------- 1 | **Problem definition**: 2 | [https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/eC2Zxu5H5SnuKxvPT/solutions/dYdoA6a4mC4fJQZT2](https://app.codesignal.com/arcade/code-arcade/corner-of-0s-and-1s/eC2Zxu5H5SnuKxvPT/solutions/dYdoA6a4mC4fJQZT2) 3 | -------------------------------------------------------------------------------- /Thumbtack-Bot/thumbtack-bot-task1/solver.py: -------------------------------------------------------------------------------- 1 | def ratingThreshold(threshold, ratings): 2 | 3 | manual_list = [] 4 | 5 | for i in range(len(ratings)): 6 | s = sum(ratings[i]) / float(len(ratings[i])) 7 | 8 | if s < threshold: 9 | manual_list += [i] 10 | 11 | return manual_list -------------------------------------------------------------------------------- /arrayChange/README.md: -------------------------------------------------------------------------------- 1 | You are given an array of integers. On each move you are allowed to increase exactly one of its element by one. Find the minimal number of moves required to obtain a strictly increasing sequence from the input. 2 | 3 | **Example** 4 | 5 | For `inputArray = [1, 1, 1]`, the output should be 6 | `arrayChange(inputArray) = 3`. 7 | -------------------------------------------------------------------------------- /firstDuplicate/firstDuplicate.py: -------------------------------------------------------------------------------- 1 | def firstDuplicate(a): 2 | 3 | d = {} 4 | found = 0 5 | 6 | for i in range(len(a)): 7 | if a[i] in d: 8 | d[a[i]] += 1 9 | else: 10 | d[a[i]] = 1 11 | 12 | if(d[a[i]] == 2): 13 | return a[i] 14 | 15 | if not found: 16 | return -1 17 | 18 | -------------------------------------------------------------------------------- /sortByHeight/sortByHeight.py: -------------------------------------------------------------------------------- 1 | def sortByHeight(a): 2 | 3 | t = [i for i in range(len(a)) if a[i] == -1] 4 | persons = list( set(range(len(a))) - set(t) ) 5 | 6 | p_arr = [ a[i] for i in persons] 7 | p_arr.sort() 8 | 9 | cnt = 0 10 | for i in persons: 11 | a[i] = p_arr[cnt] 12 | cnt += 1 13 | 14 | return a -------------------------------------------------------------------------------- /sortByHeight/README.md: -------------------------------------------------------------------------------- 1 | Some people are standing in a row in a park. There are trees between them which cannot be moved. Your task is to rearrange the people by their heights in a non-descending order without moving the trees. 2 | 3 | **Example** 4 | 5 | For `a = [-1, 150, 190, 170, -1, -1, 160, 180]`, the output should be 6 | `sortByHeight(a) = [-1, 150, 160, 170, -1, -1, 180, 190]`. 7 | -------------------------------------------------------------------------------- /climbingStairs/solver.py: -------------------------------------------------------------------------------- 1 | def climbingStairs(n, d={}, ways = 0): 2 | 3 | steps = [1, 2] 4 | 5 | if n == 1: 6 | return 1 7 | elif n == 2: 8 | return 2 9 | 10 | if n in d: 11 | ways += d[n] 12 | else: 13 | ways += climbingStairs(n-1, d, ways) + climbingStairs(n-2, d, ways) 14 | d[n] = ways 15 | 16 | return ways -------------------------------------------------------------------------------- /rotateImage/README.md: -------------------------------------------------------------------------------- 1 | You are given an n x n 2D matrix that represents an image. Rotate the image by 90 degrees (clockwise). 2 | 3 | **Example** 4 | 5 | For 6 | 7 | ``` 8 | a = [[1, 2, 3], 9 | [4, 5, 6], 10 | [7, 8, 9]] 11 | ``` 12 | 13 | the output should be 14 | 15 | ``` 16 | rotateImage(a) = 17 | [[7, 4, 1], 18 | [8, 5, 2], 19 | [9, 6, 3]] 20 | ``` 21 | -------------------------------------------------------------------------------- /isIdentityMatrix/isIdentityMatrix.py: -------------------------------------------------------------------------------- 1 | def isIdentityMatrix(matrix): 2 | flag = True 3 | 4 | for i in range(len(matrix)): 5 | for j in range(len(matrix[i])): 6 | 7 | if i == j: 8 | if matrix[i][j] != 1: 9 | return False 10 | elif matrix[i][j] != 0: 11 | return False 12 | 13 | return flag 14 | -------------------------------------------------------------------------------- /tellTime/README.md: -------------------------------------------------------------------------------- 1 | Given a digital time, your task is to return a string that represents this time in regular English. The time should be rounded to the nearest multiple of `5`. 2 | 3 | **Example** 4 | 5 | * For `time_str = "12:00"`, the output should be 6 | `tellTime = "It's twelve o'clock"`. 7 | 8 | * For `time_str = "08:42"`, the output should be 9 | `tellTime = "It's twenty to nine"` 10 | 11 | -------------------------------------------------------------------------------- /arrayChange/arrayChange.py: -------------------------------------------------------------------------------- 1 | def arrayChange(inputArray): 2 | 3 | moves = 0 4 | 5 | for i in range(len(inputArray)-1): 6 | 7 | left = inputArray[i] 8 | right = inputArray[i+1] 9 | 10 | if left >= right: 11 | tmp_moves = left - right + 1 12 | inputArray[i+1] += tmp_moves 13 | moves += tmp_moves 14 | 15 | return moves -------------------------------------------------------------------------------- /LinkedLists/removeKFromList/README.md: -------------------------------------------------------------------------------- 1 | Given a singly linked list of integers `l` and an integer `k`, remove all elements from list `l` that have a value equal to `k`. 2 | 3 | **Example** 4 | 5 | * For `l = [3, 1, 2, 3, 4, 5]` and `k = 3`, the output should be 6 | `removeKFromList(l, k) = [1, 2, 4, 5]`; 7 | 8 | * For `l = [1, 2, 3, 4, 5, 6, 7]` and `k = 10`, the output should be 9 | `removeKFromList(l, k) = [1, 2, 3, 4, 5, 6, 7]`. -------------------------------------------------------------------------------- /phoneCall/phoneCall.py: -------------------------------------------------------------------------------- 1 | def phoneCall(min1, min2_10, min11, s): 2 | 3 | minutes = 0 4 | 5 | rate = min1 6 | while s > 0: 7 | 8 | minutes += 1 9 | 10 | if minutes == 2: 11 | rate = min2_10 12 | elif minutes > 10: 13 | rate = min11 14 | 15 | s -= rate 16 | if s < 0: 17 | minutes -= 1 18 | 19 | return minutes -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## CodeSignal 2 | 3 | (former CodeFights) 4 | 5 | [https://app.codesignal.com/](https://app.codesignal.com/) 6 | 7 | Problems from _Arcade_, _Challenges_ and __battles against Bots__ with my solutions in Python. 8 | 9 | 10 | For all problems, the following libraries are considered to be automatically imported: 11 | ``` 12 | import math 13 | import string 14 | import re 15 | import random 16 | import functools 17 | ``` 18 | -------------------------------------------------------------------------------- /climbingStairs/README.md: -------------------------------------------------------------------------------- 1 | You are climbing a staircase that has `n` steps. You can take the steps either `1` or `2` at a time. Calculate how many distinct ways you can climb to the top of the staircase. 2 | 3 | **Example** 4 | 5 | For `n = 1`, the output should be 6 | `climbingStairs(n) = 1`; 7 | 8 | For `n = 2`, the output should be 9 | `climbingStairs(n) = 2`. 10 | 11 | You can either climb `2` steps at once or climb `1` step two times. -------------------------------------------------------------------------------- /palindromeRearranging/palindromeRearranging.py: -------------------------------------------------------------------------------- 1 | def palindromeRearranging(inputString): 2 | 3 | char_occur = {} 4 | 5 | for c in inputString: 6 | if c not in char_occur: 7 | char_occur[c] = 1 8 | else: 9 | char_occur[c] += 1 10 | 11 | odd_occ = [l for l in char_occur if char_occur[l] % 2] 12 | if len(odd_occ) > 1: 13 | return False 14 | else: 15 | return True -------------------------------------------------------------------------------- /isIPv4Address/isIPv4Address.py: -------------------------------------------------------------------------------- 1 | def isIPv4Address(inputString): 2 | 3 | nums = inputString.split('.') 4 | if len(nums) != 4: 5 | return False 6 | 7 | nums = [n for n in nums if n != '' and not re.search('[^0-9]',n)] 8 | if len(nums) != 4: 9 | return False 10 | 11 | outliers = [x for x in nums if int(x) > 255 or int(x) < 0] 12 | if len(outliers) == 0: 13 | return True 14 | else: 15 | return False -------------------------------------------------------------------------------- /palindromeRearranging/README.md: -------------------------------------------------------------------------------- 1 | Given a string, find out if its characters can be rearranged to form a palindrome. 2 | 3 | **Example** 4 | 5 | For `inputString = "aabb"`, the output should be 6 | `palindromeRearranging(inputString) = true`. 7 | 8 | We can rearrange `"aabb"` to make `"abba"`, which is a palindrome. 9 | 10 | Other examples: 11 | 12 | * `palindromeRearranging('abbcabb') = true`. 13 | 14 | * `palindromeRearranging('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabc') = false`. 15 | 16 | -------------------------------------------------------------------------------- /groupingDishes/solver.py: -------------------------------------------------------------------------------- 1 | def groupingDishes(dishes): 2 | 3 | d = {} 4 | 5 | for l in dishes: 6 | dish = l[0] 7 | for i in l[1:]: 8 | if i not in d: 9 | d[i] = [dish] 10 | else: 11 | d[i] += [dish] 12 | 13 | print(d) 14 | 15 | out = [] 16 | 17 | for i in sorted(d): 18 | if len(d[i]) > 1: 19 | out += [[i] + sorted(d[i])] 20 | 21 | return out -------------------------------------------------------------------------------- /incrementCipher/incrementCipher.py: -------------------------------------------------------------------------------- 1 | def incrementCipher(s, nums): 2 | 3 | for ni in nums: 4 | 5 | cnt = 1 6 | index = ni * cnt - 1 7 | 8 | while index < len(s): 9 | 10 | incr_idx = ord(s[index]) + 1 11 | if incr_idx == 123: 12 | incr_idx = 97 13 | 14 | s = s[:index] + chr(incr_idx) + s[index+1:] 15 | 16 | cnt += 1 17 | index = ni * cnt - 1 18 | 19 | return s 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /minSubstringWithAllChars/README.md: -------------------------------------------------------------------------------- 1 | Minimum substring with all characters 2 | --- 3 | 4 | You have two strings, `s` and `t`. The string `t` contains only unique elements. Find and return the minimum consecutive substring of `s` that contains all of the elements from `t`. 5 | 6 | It's guaranteed that the answer exists. If there are several answers, return the one which starts from the smallest index. 7 | 8 | ###Example 9 | For `s ="adobecodebanc"` and `t = "abc"`, the output should be 10 | `minSubstringWithAllChars(s, t) = "banc"`. 11 | -------------------------------------------------------------------------------- /boxBlurImage/boxBlurImage.py: -------------------------------------------------------------------------------- 1 | def boxBlur(image): 2 | 3 | m = len(image)-2 4 | n = len(image[0])-2 5 | blur_img = [ [0] * n for _ in range(m)] 6 | 7 | for i in range(1, m+1): 8 | for j in range(1, n+1): 9 | 10 | indexes = [[i-1, j-1], [i-1, j], [i-1, j+1], [i, j-1], [i, j], [i, j+1], [i+1, j-1], [i+1, j], [i+1, j+1]] 11 | 12 | avg = int(math.floor(sum([image[k][l] for (k,l) in indexes]) / 9)) 13 | blur_img[i-1][j-1] = avg 14 | 15 | return blur_img -------------------------------------------------------------------------------- /avoidObstacles/README.md: -------------------------------------------------------------------------------- 1 | You are given an array of integers representing coordinates of obstacles situated on a straight line. 2 | 3 | Assume that you are jumping from the point with coordinate `0` to the right. You are allowed only to make jumps of the same length represented by some integer. 4 | 5 | Find the minimal length of the jump enough to avoid all the obstacles. 6 | 7 | **Example** 8 | 9 | For `inputArray = [5, 3, 6, 7, 9]`, the output should be 10 | `avoidObstacles(inputArray) = 4`. 11 | 12 | Check out the image below for better understanding: 13 | 14 | ![example](example.png) 15 | -------------------------------------------------------------------------------- /firstNotRepeatingCharacter/README.md: -------------------------------------------------------------------------------- 1 | Given a string `s`, find and return the first instance of a non-repeating character in it. If there is no such character, return `'_'`. 2 | 3 | **Example** 4 | 5 | * For `s = "abacabad"`, the output should be 6 | `firstNotRepeatingCharacter(s) = 'c'`. 7 | 8 | There are `2` non-repeating characters in the string: `'c'` and `'d'`. Return c since it appears in the string first. 9 | 10 | * For `s = "abacabaabacaba"`, the output should be 11 | `firstNotRepeatingCharacter(s) = '_'`. 12 | 13 | There are no characters in this string that do not repeat. 14 | 15 | 16 | -------------------------------------------------------------------------------- /shapeArea/README.md: -------------------------------------------------------------------------------- 1 | Below we will define an `n`-interesting polygon. Your task is to find the area of a polygon for a given `n`. 2 | 3 | A `1`-interesting polygon is just a square with a side of length `1`. An n-interesting polygon is obtained by taking the `n - 1`-interesting polygon and appending `1`-interesting polygons to its rim, side by side. You can see the `1`-, `2`-, `3`- and `4`-interesting polygons in the picture below. 4 | 5 | ![area](area.png) 6 | 7 | **Example** 8 | 9 | * For `n = 2`, the output should be 10 | `shapeArea(n) = 5` 11 | * For `n = 3`, the output should be 12 | `shapeArea(n) = 13` 13 | -------------------------------------------------------------------------------- /LinkedLists/removeKFromList/removeKFromList.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list: 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.value = x 5 | # self.next = None 6 | 7 | def removeKFromList(head, k): 8 | 9 | if head == None: 10 | return head 11 | elif head.value == k: 12 | head = head.next 13 | 14 | n = head 15 | 16 | while n != None and n.next != None: 17 | if n.next.value == k: 18 | n.next = n.next.next 19 | else: 20 | n = n.next 21 | 22 | if n != None and n.value == k: 23 | head = head.next 24 | 25 | return head 26 | -------------------------------------------------------------------------------- /Thumbtack-Bot/thumbtack-bot-task2/solver.py: -------------------------------------------------------------------------------- 1 | def proCategorization(pros, preferences): 2 | 3 | pref_dict = {} 4 | for i in range(len(pros)): 5 | 6 | name = pros[i] 7 | 8 | prefs = preferences[i] 9 | for j in range(len(prefs)): 10 | p = prefs[j] 11 | 12 | if p not in pref_dict: 13 | pref_dict[p] = [name] 14 | else: 15 | pref_dict[p] += [name] 16 | 17 | 18 | out_list = [] 19 | 20 | for k in sorted(pref_dict): 21 | tmp = [[k], pref_dict[k]] 22 | out_list += [tmp] 23 | 24 | return out_list -------------------------------------------------------------------------------- /arraysAreSimilar/arraysAreSimilar.py: -------------------------------------------------------------------------------- 1 | def areSimilar(a, b): 2 | 3 | left = None 4 | right = None 5 | 6 | areSimilar = True 7 | 8 | mism = 0 9 | for i in range(len(a)): 10 | 11 | if a[i] != b[i]: 12 | mism += 1 13 | else: 14 | continue 15 | 16 | if mism == 1: 17 | left = a[i] 18 | right = b[i] 19 | elif mism == 2: 20 | if left == b[i] and right == a[i]: 21 | continue 22 | else: 23 | return False 24 | elif mism > 2: 25 | areSimilar = False 26 | break 27 | 28 | return areSimilar 29 | 30 | -------------------------------------------------------------------------------- /MinesweeperGame/README.md: -------------------------------------------------------------------------------- 1 | In the popular Minesweeper game you have a board with some mines and those cells that don't contain a mine have a number in it that indicates the total number of mines in the neighboring cells. Starting off with some arrangement of mines we want to create a Minesweeper game setup. 2 | 3 | **Example** 4 | 5 | For 6 | 7 | ``` 8 | matrix = [[true, false, false], 9 | [false, true, false], 10 | [false, false, false]] 11 | ``` 12 | 13 | the output should be 14 | 15 | ``` 16 | minesweeper(matrix) = [[1, 2, 1], 17 | [2, 1, 1], 18 | [1, 1, 1]] 19 | ``` 20 | 21 | Check out the image below for better understanding: 22 | 23 | ![img](example.png) -------------------------------------------------------------------------------- /LinkedLists/addTwoHugeNumbers/README.md: -------------------------------------------------------------------------------- 1 | You're given `2` huge integers represented by linked lists. Each linked list element is a number from `0` to `9999` that represents a number with exactly `4` digits. The represented number might have leading zeros. Your task is to add up these huge integers and return the result in the same format. 2 | 3 | **Example** 4 | 5 | * For `a = [9876, 5432, 1999]` and `b = [1, 8001]`, the output should be 6 | `addTwoHugeNumbers(a, b) = [9876, 5434, 0]`. 7 | 8 | Explanation: `987654321999 + 18001 = 987654340000`. 9 | 10 | * For `a = [123, 4, 5]` and `b = [100, 100, 100]`, the output should be 11 | `addTwoHugeNumbers(a, b) = [223, 104, 105]`. 12 | 13 | Explanation: `12300040005 + 10001000100 = 22301040105`. -------------------------------------------------------------------------------- /firstNotRepeatingCharacter/firstNotRepeatingCharacter.py: -------------------------------------------------------------------------------- 1 | def firstNotRepeatingCharacter(s): 2 | 3 | occ_dict = {} 4 | index_dict = {} 5 | 6 | for i in range(len(s)): 7 | 8 | ch = s[i] 9 | 10 | if ch in occ_dict: 11 | occ_dict[ch] += 1 12 | else: 13 | occ_dict[ch] = 1 14 | 15 | if ch not in index_dict: 16 | index_dict[ch] = i 17 | 18 | 19 | one_occ = [k for (k,v) in occ_dict.items() if v == 1] 20 | if len(one_occ) < 1: 21 | return '_' 22 | 23 | index_dict = dict([(k,v) for (k,v) in index_dict.items() if k in one_occ]) 24 | min_ch = min(index_dict, key= index_dict.get) 25 | 26 | return min_ch 27 | -------------------------------------------------------------------------------- /firstDuplicate/README.md: -------------------------------------------------------------------------------- 1 | Given an array `a` that contains only numbers in the range from `1` to `a.length`, find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return `-1`. 2 | 3 | Example 4 | 5 | For `a = [2, 3, 3, 1, 5, 2]`, the output should be 6 | `firstDuplicate(a) = 3`. 7 | 8 | There are `2` duplicates: numbers `2` and `3`. The second occurrence of `3` has a smaller index than than second occurrence of `2` does, so the answer is `3`. 9 | 10 | For `a = [2, 4, 3, 5, 1]`, the output should be 11 | `firstDuplicate(a) = -1`. 12 | -------------------------------------------------------------------------------- /HasPathWithGivenSum/solver.py: -------------------------------------------------------------------------------- 1 | # Definition for binary tree: 2 | # class Tree(object): 3 | # def __init__(self, x): 4 | # self.value = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | 9 | def hasPathWithGivenSum(t, s): 10 | 11 | if t is None: 12 | if s == 0: 13 | return 1 14 | else: 15 | return 0 16 | else: 17 | ans = 0 18 | subSum = s - t.value 19 | 20 | if subSum == 0 and t.left == None and t.right == None : 21 | return 1 22 | 23 | if t.left is not None: 24 | ans = ans or hasPathWithGivenSum(t.left, subSum) 25 | 26 | if t.right is not None: 27 | ans = ans or hasPathWithGivenSum(t.right, subSum) 28 | 29 | return ans -------------------------------------------------------------------------------- /reverseParentheses/reverseParentheses.py: -------------------------------------------------------------------------------- 1 | def reverseParentheses(s): 2 | 3 | bracket_pairs = [] 4 | left_brackets_stack = [] 5 | 6 | for i in range(len(s)): 7 | char = s[i] 8 | if char == '(': 9 | left_brackets_stack += [i] 10 | elif char == ')': 11 | left_bracket = left_brackets_stack[-1] 12 | del left_brackets_stack[-1] 13 | 14 | bracket_pairs += [(left_bracket, i)] 15 | 16 | #print(bracket_pairs) 17 | 18 | for b in bracket_pairs: 19 | left, right = b 20 | 21 | subs = s[left:right] 22 | subs = subs[::-1] 23 | s = s[:left]+subs+s[right:] 24 | #print(s) 25 | 26 | s = s.replace(')', '') 27 | s = s.replace('(', '') 28 | return(s) 29 | 30 | -------------------------------------------------------------------------------- /arraysAreSimilar/README.md: -------------------------------------------------------------------------------- 1 | Two arrays are called similar if one can be obtained from another by swapping at most one pair of elements in one of the arrays. 2 | 3 | Given two arrays `a` and `b`, check whether they are similar. 4 | 5 | **Example** 6 | 7 | * For `a = [1, 2, 3]` and `b = [1, 2, 3]`, the output should be 8 | `areSimilar(a, b) = true`. 9 | 10 | The arrays are equal, no need to swap any elements. 11 | 12 | * For `a = [1, 2, 3]` and `b = [2, 1, 3]`, the output should be 13 | `areSimilar(a, b) = true`. 14 | 15 | We can obtain `b` from `a` by swapping `2` and `1` in `b`. 16 | 17 | * For `a = [1, 2, 2]` and `b = [2, 1, 1]`, the output should be 18 | `areSimilar(a, b) = false`. 19 | 20 | Any swap of any two elements either in `a` or in `b` won't make `a` and `b` equal. 21 | -------------------------------------------------------------------------------- /makingAnagrams/README.md: -------------------------------------------------------------------------------- 1 | Alice is taking a cryptography class and finding anagrams to be very useful. We consider two strings to be anagrams of each other if the first string's letters can be rearranged to form the second string. In other words, both strings must contain the same exact letters in the same exact frequency For example, `bacdc` and `dcbac` are anagrams, but `bacdc` and `dcbad` are not. 2 | 3 | Alice decides on an encryption scheme involving two large strings where encryption is dependent on the minimum number of character deletions required to make the two strings anagrams. Can you help her find this number? 4 | 5 | Given two strings, and , that may or may not be of the same length, determine the minimum number of character deletions required to make and anagrams. Any characters can be deleted from either of the strings. 6 | -------------------------------------------------------------------------------- /IsCryptarithmSolution/isCryptSolution.py: -------------------------------------------------------------------------------- 1 | def isCryptSolution(crypt, solution): 2 | # a + b = c 3 | a = crypt[0] 4 | b = crypt[1] 5 | c = crypt[2] 6 | ch_dict = {} 7 | 8 | for s in solution: 9 | ch_dict[s[0]] = int(s[1]) 10 | 11 | hasLeadingZeros = False 12 | if ch_dict[a[0]] == 0 or ch_dict[b[0]] == 0 or ch_dict[c[0]] == 0: 13 | hasLeadingZeros = True 14 | 15 | n1 = ''.join([str(ch_dict[i]) for i in a]) 16 | n2 = ''.join([str(ch_dict[i]) for i in b]) 17 | n3 = ''.join([str(ch_dict[i]) for i in c]) 18 | 19 | if int(n1) + int(n2) == int(n3): 20 | if hasLeadingZeros and int(n3) == 0 and len(n3) == len(str(int(n3))): 21 | return True 22 | elif hasLeadingZeros: 23 | return False 24 | else: 25 | return True 26 | else: 27 | return False 28 | -------------------------------------------------------------------------------- /incrementCipher/README.md: -------------------------------------------------------------------------------- 1 | You are given a string `s`, which consists only of lowercase English letters, and an array of numbers, `nums`. For each `ni = nums[i]`, increment every `nith` letter in the given string - i.e. the letters with indices `s[ni]`, `s[2 · ni]`, `s[3 · ni]` and so on (`1`-based). For letters, incrementing means changing the letter to the next one in the alphabet. For example, `a` becomes `b`, `b` becomes `c`, and `z` cycles to `a`. 2 | 3 | **Example** 4 | 5 | For `s = "abc"` and `nums = [1, 2, 3]`, the output should be 6 | `incrementCipher(s, nums) = "bde"`. 7 | 8 | First, we should increment every `1st` letter, so we just increment every letter and get `s = "bcd"`. Then we increment every `2nd` letter and get `s = "bdd"` (since the length of `s` is `3`, there is only one such letter). And then, after incrementing every `3rd` letter, we get the answer: `s = "bde"`. 9 | -------------------------------------------------------------------------------- /reverseParentheses/README.md: -------------------------------------------------------------------------------- 1 | You have a string `s` that consists of English letters, punctuation marks, whitespace characters, and brackets. It is guaranteed that the parentheses in `s` form a regular bracket sequence. 2 | 3 | Your task is to reverse the strings contained in each pair of matching parentheses, starting from the innermost pair. The results string should not contain any parentheses. 4 | 5 | **Example** 6 | 7 | * For string `s = "a(bc)de"`, the output should be 8 | `reverseParentheses(s) = "acbde"`. 9 | 10 | * For string `s = "a(bcdefghijkl(mno)p)q"`, the output should be 11 | `reverseParentheses(s) = "apmnolkjihgfedcbq"`. 12 | 13 | * For string `s = "co(de(fight)s)"`, the output should be 14 | `reverseParentheses(s) = "cosfighted"`. 15 | 16 | * For string `s = "Code(Cha(lle)nge)"`, the output should be 17 | `reverseParentheses(s) = "CodeegnlleahC"`. 18 | -------------------------------------------------------------------------------- /findPathInMatrix/README.md: -------------------------------------------------------------------------------- 1 | You are given an `n × m` matrix, which contains all the integers from `1` to `n * m`, inclusive, each exactly once. 2 | 3 | Initially you are standing in the cell containing the number `1`. On each turn you are allowed to move to an adjacent cell, i.e. to a cell that shares a common side with the one you are standing on now. It is prohibited to visit any cell more than once. 4 | 5 | Check if it is possible to visit all the cells of the matrix in the order of increasing numbers in the cells, i.e. get to the cell with the number `2` on the first turn, then move to `3`, etc. 6 | 7 | **Example** 8 | 9 | * For 10 | ``` 11 | matrix = [[1, 4, 5], 12 | [2, 3, 6]] 13 | ``` 14 | 15 | the output should be 16 | 17 | `findPath(matrix) = true` 18 | 19 | * For 20 | ``` 21 | matrix = [[1, 3, 6], 22 | [2, 4, 5]] 23 | ``` 24 | 25 | the output should be 26 | `findPath(matrix) = false`. 27 | -------------------------------------------------------------------------------- /boxBlurImage/README.md: -------------------------------------------------------------------------------- 1 | Last night you had to study, but decided to party instead. Now there is a black and white photo of you that is about to go viral. You cannot let this ruin your reputation, so you want to apply box blur algorithm to the photo to hide its content. 2 | 3 | The algorithm works as follows: each pixel `x` in the resulting image has a value equal to the average value of the input image pixels' values from the `3 × 3` square with the center at `x`. All pixels at the edges are cropped. 4 | 5 | As pixel's value is an integer, all fractions should be rounded down. 6 | 7 | **Example** 8 | 9 | For 10 | ``` 11 | 12 | image = [[1, 1, 1], 13 | [1, 7, 1], 14 | [1, 1, 1]] 15 | 16 | ``` 17 | 18 | the output should be `boxBlur(image) = [[1]]`. 19 | 20 | In the given example all boundary pixels were cropped, and the value of the pixel in the middle was obtained as `(1 + 1 + 1 + 1 + 7 + 1 + 1 + 1 + 1) / 9 = 15 / 9 = ~rounded down~ = 1`. 21 | -------------------------------------------------------------------------------- /isIPv4Address/README.md: -------------------------------------------------------------------------------- 1 | An IP address is a numerical label assigned to each device (e.g., computer, printer) participating in a computer network that uses the Internet Protocol for communication. There are two versions of the Internet protocol, and thus two versions of addresses. One of them is the IPv4 address. 2 | 3 | IPv4 addresses are represented in dot-decimal notation, which consists of four decimal numbers, each ranging from `0` to `255`, separated by dots, e.g., `172.16.254.1`. 4 | 5 | Given a string, find out if it satisfies the IPv4 address naming rules. 6 | 7 | **Example** 8 | 9 | * For `inputString = "172.16.254.1"`, the output should be 10 | `isIPv4Address(inputString) = true; 11 | 12 | * For `inputString = "172.316.254.1"`, the output should be 13 | `isIPv4Address(inputString) = false`. 14 | 15 | `316 is not in range `[0, 255]`. 16 | 17 | * For `inputString = ".254.255.0"`, the output should be 18 | `isIPv4Address(inputString) = false`. 19 | 20 | There is no first number. -------------------------------------------------------------------------------- /SortedBinaryTreeLeaves/README.md: -------------------------------------------------------------------------------- 1 | You are given a recursive notation of a binary tree: each node of a tree is represented as a set of three elements: 2 | 3 | * value of the node; 4 | * left subtree; 5 | * right subtree. 6 | 7 | So, a tree can be written as `(value left_subtree right_subtree)`. If a node doesn't exist then it is represented as an empty set: `()`. For example, here is a representation of a tree in the given picture: 8 | 9 | ``` 10 | (2 (7 (2 () ()) (6 (5 () ()) (11 () ()))) (5 () (9 (4 () ()) ()))) 11 | ``` 12 | 13 | Your task is to obtain a list of nodes, that are the most distant from the tree root, in the order from left to right. 14 | 15 | ![tree](tree.png) 16 | 17 | In the notation of a node its value and subtrees are separated by exactly one space character. 18 | 19 | ** Example ** 20 | 21 | For 22 | 23 | ``` 24 | tree = "(2 (7 (2 () ()) (6 (5 () ()) (11 () ()))) (5 () (9 (4 () ()) ())))" 25 | ``` 26 | 27 | the output should be 28 | `treeBottom(tree) = [5, 11, 4]`. 29 | 30 | -------------------------------------------------------------------------------- /phoneCall/README.md: -------------------------------------------------------------------------------- 1 | Some phone usage rate may be described as follows: 2 | 3 | * first minute of a call costs `min1` cents, 4 | * each minute from the 2nd up to 10th (inclusive) costs `min2_10` cents 5 | * each minute after 10th costs `min11` cents. 6 | 7 | You have `s` cents on your account before the call. What is the duration of the longest call (in minutes rounded down to the nearest integer) you can have? 8 | 9 | 10 | **Example** 11 | 12 | For `min1 = 3`, `min2_10 = 1`, `min11 = 2` and `s = 20`, the output should be 13 | `phoneCall(min1, min2_10, min11, s) = 14`. 14 | 15 | Here's why: 16 | 17 | * the first minute costs `3` cents, which leaves you with `20 - 3 = 17` cents; 18 | * the total cost of minutes `2` through `10` is `1 * 9 = 9`, so you can talk `9` more minutes and still have `17 - 9 = 8` cents; 19 | * each next minute costs `2` cents, which means that you can talk `8 / 2 = 4` more minutes. 20 | 21 | Thus, the longest call you can make is `1 + 9 + 4 = 14` minutes long. 22 | 23 | -------------------------------------------------------------------------------- /EvenTextWrap/README.md: -------------------------------------------------------------------------------- 1 | Given an array of words and a length `l`, format the text such that each line has exactly `l` characters and is fully justified on both the left and the right. Words should be packed in a greedy approach; that is, pack as many words as possible in each line. Add extra spaces when necessary so that each line has exactly `l` characters. 2 | 3 | Extra spaces between words should be distributed as evenly as possible. If the number of spaces on a line does not divide evenly between words, the empty slots on the left will be assigned more spaces than the slots on the right. For the last line of text and lines with one word only, the words should be left justified with no extra space inserted between them. 4 | 5 | ** Example ** 6 | 7 | For 8 | 9 | `words = ["This", "is", "an", "example", "of", "text", "justification."]` 10 | and `l = 16`, the output should be 11 | 12 | ``` 13 | textJustification(words, l) = ["This is an", 14 | "example of text", 15 | "justification. "] 16 | ``` -------------------------------------------------------------------------------- /minSubstringWithAllChars/solver.py: -------------------------------------------------------------------------------- 1 | def minSubstringWithAllChars(s, t): 2 | 3 | if len(t) == 0 or len(s) == 0: 4 | return '' 5 | 6 | if len(t) == 1 and t in s: 7 | return t 8 | 9 | all_substrings = [] 10 | start_idx = 0 11 | 12 | while True: 13 | cur_substr = '' 14 | char_cnt=0 15 | visited_chars = dict([(k, 0) for k in t]) 16 | 17 | for i in range(len(s)): 18 | if s[i] in t: 19 | visited_chars[s[i]] = 1 20 | char_cnt += 1 21 | 22 | if char_cnt >= 1: 23 | cur_substr += s[i] 24 | 25 | if char_cnt == 2: 26 | char_cnt += 1 27 | start_idx = i 28 | 29 | if all([v==1 for k,v in visited_chars.items()]): 30 | s = s[start_idx:] 31 | all_substrings.append(cur_substr) 32 | break 33 | 34 | if not all([v==1 for k,v in visited_chars.items()]): 35 | break 36 | 37 | min_substr = min(all_substrings, key=len) 38 | return min_substr 39 | -------------------------------------------------------------------------------- /EvenTextWrap/solver.py: -------------------------------------------------------------------------------- 1 | import textwrap 2 | 3 | def textJustification(words, l): 4 | 5 | s = ' '.join(words) 6 | lines = textwrap.wrap(s, l, break_long_words=False) 7 | 8 | if len(lines) == 0: 9 | return [' '* l] 10 | elif len(lines) == 1: 11 | return [lines[0] + ' '*(l - len(lines[0]))] 12 | 13 | out = [] 14 | for i in range(len(lines)-1): 15 | 16 | w = lines[i].split() 17 | 18 | diff = l - (len(lines[i])) 19 | spaces_arr = [1] * (len(w) - 1) 20 | 21 | if len(spaces_arr) > 0: 22 | idx = 0 23 | while diff > 0: 24 | idx %= len(spaces_arr) 25 | spaces_arr[idx] += 1 26 | diff -= 1 27 | idx += 1 28 | 29 | st = '' 30 | for k in range(len(w)-1): 31 | st += w[k] 32 | st += ' ' * spaces_arr[k] 33 | st += w[-1] + ' ' * diff 34 | out += [st] 35 | 36 | 37 | out += [lines[-1] + ' '*(l - len(lines[-1]))] 38 | 39 | return out -------------------------------------------------------------------------------- /Thumbtack-Bot/thumbtack-bot-task1/README.md: -------------------------------------------------------------------------------- 1 | In Thumbtack, users are able to rate Pros based on their experience working with them. Each rating is an integer ranging from `1` to `5`, and all ratings are averaged to produce a single number rating for any given Pro. Those Pros who have a rating lower than a specified `threshold` are manually reviewed by Thumbtack staff to ensure high quality of service. 2 | 3 | You're given a list of `ratings` for some Pros. Find out which Pros should be manually reviewed. 4 | 5 | Example 6 | 7 | For `threshold = 3.5` and 8 | 9 | ``` 10 | 11 | ratings = [[3, 4], 12 | [3, 3, 3, 4], 13 | [4]] 14 | 15 | ``` 16 | 17 | the output should be `ratingThreshold(threshold, ratings) = [1]`. 18 | 19 | Assume that we have `3` Pros that have received the following ratings: `[3, 4], [3, 3, 3, 4]` and `[4]`. Then 20 | And if `threshold = 3.5` the answer is `ratingThreshold(threshold, ratings) = [1]`. 21 | The first Pro's rating is `3.5`, the second one's is `3.25`, and the last one's is `4`, so only the second Pro should be reviewed manually (the output is their 0-based index). 22 | -------------------------------------------------------------------------------- /LinkedLists/addTwoHugeNumbers/addTwoHugeNumbers.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list: 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.value = x 5 | # self.next = None 6 | # 7 | def get_num(a): 8 | cnt_a = 1 9 | a_num = '' 10 | while a.next != None: 11 | 12 | if cnt_a: 13 | cnt_a = 0 14 | a_num += str(a.value) 15 | else: 16 | a_num += ('0' * (4 - len(str(a.value)))) + str(a.value) 17 | 18 | a = a.next 19 | a_num += ('0' * (4 - len(str(a.value)))) + str(a.value) 20 | 21 | return int(a_num) 22 | 23 | def addTwoHugeNumbers(a, b): 24 | 25 | a_num = get_num(a) 26 | b_num = get_num(b) 27 | #print(a_num) 28 | #print(b_num) 29 | 30 | sm = str(a_num + b_num) 31 | #print(sm) 32 | 33 | ret_list = [] 34 | sm = sm[-1::-1] 35 | for i in range(0,len(sm), 4): 36 | num = sm[i:i+4] 37 | num = int(num[-1::-1]) 38 | 39 | ret_list += [num] 40 | 41 | ret_list = ret_list[-1::-1] 42 | 43 | return ret_list -------------------------------------------------------------------------------- /tellTime/tellTime.py: -------------------------------------------------------------------------------- 1 | def tellTime(time_str): 2 | 3 | t = "It's " 4 | 5 | h, m = time_str.split(':') 6 | h = int(h) 7 | m = int(m) 8 | 9 | if (m % 5) >= 3: 10 | m = (m // 5) * 5 + 5 11 | if m == 60: 12 | m = 0 13 | h += 1 14 | else: 15 | m = (m // 5) * 5 16 | 17 | 18 | 19 | dh = {0: 'twelve', 1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine', 10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'one'} 20 | 21 | dm = {5: 'five', 10: 'ten', 15: 'quarter', 20: 'twenty', 25: 'twenty five', 30: 'half'} 22 | 23 | 24 | if m == 0: 25 | t += dh[h]+" o'clock" 26 | elif m < 31: 27 | h = h % 12 28 | t += dm[m]+" past "+ dh[h] 29 | else: 30 | h += 1 31 | h = h % 12 32 | m = 60 - m 33 | t += dm[m]+" to "+dh[h] 34 | 35 | 36 | return t -------------------------------------------------------------------------------- /Thumbtack-Bot/thumbtack-bot-task2/README.md: -------------------------------------------------------------------------------- 1 | Thumbtack helps Professionals (Pros) grow their business by identifying new customers. Upon registering on Thumbtack, a Pro specifies which categories of services they provide. To help match customer requests with qualified Pros, Thumbtack maintains a list of Pros grouped by service categories. 2 | 3 | Given a list of `pros` and their category `preferences`, return the list of Pros for each category. 4 | 5 | **Example** 6 | 7 | For `pros = ["Jack", "Leon", "Maria"]` and 8 | 9 | ``` 10 | preferences = [["Computer repair", "Handyman", "House cleaning"], 11 | ["Computer lessons", "Computer repair", "Data recovery service"], 12 | ["Computer lessons", "House cleaning"]] 13 | 14 | ``` 15 | 16 | the output should be 17 | 18 | ``` 19 | proCategorization(pros, preferences) = [[["Computer lessons"], ["Leon", "Maria"]], 20 | [["Computer repair"], ["Jack", "Leon"]], 21 | [["Data recovery service"], ["Leon"]], 22 | [["Handyman"], ["Jack"]], 23 | [["House cleaning"], ["Jack", "Maria"]]] 24 | 25 | ``` 26 | -------------------------------------------------------------------------------- /makingAnagrams/makingAnagrams.py: -------------------------------------------------------------------------------- 1 | def number_needed(a, b): 2 | 3 | def absol(a): 4 | if a >= 0: 5 | return a 6 | else: 7 | return (-1)*a 8 | 9 | char_to_del = 0 10 | 11 | a_dict = {} 12 | b_dict = {} 13 | 14 | for ch_a in a: 15 | if ch_a not in a_dict: 16 | a_dict[ch_a] = 1 17 | else: 18 | a_dict[ch_a] += 1 19 | 20 | 21 | for ch_b in b: 22 | if ch_b not in b_dict: 23 | b_dict[ch_b] = 1 24 | else: 25 | b_dict[ch_b] += 1 26 | 27 | all_chars = list(set(list(a_dict.keys()) + list(b_dict.keys()))) 28 | 29 | for c in all_chars: 30 | if c not in a_dict: 31 | a_dict[c] = 0 32 | if c not in b_dict: 33 | b_dict[c] = 0 34 | 35 | for c in all_chars: 36 | a_ch = int(a_dict[c]) 37 | b_ch = int(b_dict[c]) 38 | #print(a_ch, b_ch) 39 | diff = a_ch - b_ch 40 | if diff < 0: 41 | diff *= -1 42 | char_to_del += diff 43 | #print(c, '-', a_dict[c], '-', b_dict[c]) 44 | 45 | return char_to_del 46 | 47 | a = input().strip() 48 | b = input().strip() 49 | 50 | print(number_needed(a, b)) 51 | -------------------------------------------------------------------------------- /Quora-Bot-2/solver.py: -------------------------------------------------------------------------------- 1 | edges_dict = {} 2 | visited_nodes = {} 3 | 4 | def expected_time(j, t): 5 | 6 | global visited_nodes 7 | connected_edges = edges_dict[j] 8 | 9 | visited_nodes[j] = 1 10 | connected_edges = [x for x in connected_edges if x not in visited_nodes] 11 | 12 | q = len(connected_edges) 13 | if q == 0: 14 | return t[j] 15 | else: 16 | time = 0 17 | for k in connected_edges: 18 | time += expected_time(k, t) 19 | 20 | time = t[j] + time/float(q) 21 | 22 | return time 23 | 24 | 25 | def relatedQuestions(n, t, edges): 26 | 27 | if n == 1: 28 | return 0 29 | 30 | global visited_nodes 31 | 32 | for pair in edges: 33 | 34 | left, right = pair[0], pair[1] 35 | left1, right1 = pair[1], pair[0] 36 | 37 | for l,r in zip([left, right], [left1, right1]): 38 | if l in edges_dict: 39 | edges_dict[l] += [r] 40 | else: 41 | edges_dict[l] = [r] 42 | 43 | total_t = {} 44 | 45 | for j in range(n): 46 | visited_nodes = {} 47 | total_t_j = expected_time(j, t) 48 | total_t[j] = total_t_j 49 | 50 | ret_key = min(total_t, key=total_t.get) 51 | 52 | return ret_key 53 | 54 | -------------------------------------------------------------------------------- /MinesweeperGame/minesweeper.py: -------------------------------------------------------------------------------- 1 | def get_adjacent_cells(i, j, m, n): 2 | 3 | coords = [] 4 | if i >= 1: 5 | if j >= 1: 6 | coords += [[i-1, j-1]] 7 | coords += [[i-1, j]] 8 | 9 | if j < n - 1: 10 | coords += [[i-1, j+1]] 11 | 12 | if i < m - 1: 13 | if j >= 1: 14 | coords += [[i+1, j-1]] 15 | coords += [[i+1, j]] 16 | 17 | if j < n -1: 18 | coords += [[i+1, j+1]] 19 | 20 | if j >= 1: 21 | coords += [[i, j-1]] 22 | 23 | if j < n - 1: 24 | coords += [[i, j+1]] 25 | 26 | return coords 27 | 28 | 29 | def minesweeper(matrix): 30 | 31 | m = len(matrix) 32 | n = len(matrix[0]) 33 | 34 | num_matrix = [ [0] * n for _ in range(m)] 35 | 36 | for i in range(m): 37 | for j in range(n): 38 | if matrix[i][j]: 39 | matrix[i][j] = 1 40 | else: 41 | matrix[i][j] = 0 42 | 43 | for i in range(m): 44 | for j in range(n): 45 | 46 | coords = get_adjacent_cells(i, j, m, n) 47 | cur_sum = sum([ matrix[x][y] for (x,y) in coords ]) 48 | num_matrix[i][j] = cur_sum 49 | 50 | return num_matrix -------------------------------------------------------------------------------- /findPathInMatrix/findPathInMatrix.py: -------------------------------------------------------------------------------- 1 | def findAdjacentCells(i,j, n, m): 2 | l = [] 3 | 4 | if i > 0: 5 | l += [(i-1, j)] 6 | 7 | if i < (n-1): 8 | l += [(i+1, j)] 9 | 10 | if j > 0: 11 | l += [(i, j-1)] 12 | 13 | if j < m - 1: 14 | l += [(i, j+1)] 15 | 16 | return l 17 | 18 | def findPath(matrix): 19 | 20 | starti = -1 21 | startj = -1 22 | 23 | found = False 24 | for i in range(len(matrix)): 25 | if found: 26 | break 27 | for j in range(len(matrix[0])): 28 | if matrix[i][j] == 1: 29 | starti, startj = i, j 30 | found = True 31 | break 32 | 33 | valid = True 34 | 35 | n = len(matrix) 36 | m = len(matrix[0]) 37 | 38 | 39 | for i in range(1, n*m): 40 | l = findAdjacentCells(starti, startj, n, m) 41 | print(l) 42 | 43 | found_next = False 44 | for x, y in l: 45 | if matrix[x][y] == i+1: 46 | found_next = True 47 | starti, startj = x, y 48 | break 49 | 50 | if not found_next: 51 | valid = False 52 | break 53 | 54 | return valid 55 | 56 | -------------------------------------------------------------------------------- /SortedBinaryTreeLeaves/solver.py: -------------------------------------------------------------------------------- 1 | def find(s, ch): 2 | return [i for i, letter in enumerate(s) if letter == ch] 3 | 4 | def treeBottom(tree): 5 | 6 | left_par_indexes = find(tree, '(') 7 | d = {} 8 | nums = {} 9 | sorted_nums = [] 10 | 11 | cnt = 0 12 | for j in left_par_indexes: 13 | r = find(tree[j:], ' ') 14 | if r != []: 15 | r = r[0] 16 | else: 17 | continue 18 | 19 | num = tree[j: j+r] 20 | num = num[1:] 21 | if not num.isdigit(): 22 | continue 23 | 24 | nums[j] = int(num) 25 | sorted_nums += [int(num)] 26 | cnt += 1 27 | 28 | par_cnt_arr = [] 29 | left_par_cnt = 0 30 | for j in range(len(tree)): 31 | c = tree[j] 32 | if c == '(': 33 | left_par_cnt += 1 34 | if c == ')': 35 | left_par_cnt -= 1 36 | par_cnt_arr.append(left_par_cnt) 37 | 38 | cnt = 1 39 | for k in nums: 40 | if nums[k] not in d: 41 | d[nums[k]] = par_cnt_arr[k] 42 | else: 43 | d[str(nums[k])+'_'+str(cnt)] = par_cnt_arr[k] 44 | cnt += 1 45 | 46 | max_depth = max(d.values()) 47 | out = [] 48 | for (k,v) in d.items(): 49 | if v == max_depth: 50 | k = int(str(k).split('_')[0]) 51 | out += [k] 52 | 53 | mm = [] 54 | for i in sorted_nums: 55 | for j in range(len(out)): 56 | if i == out[j]: 57 | mm += [out[j]] 58 | del out[j] 59 | break 60 | 61 | return mm 62 | -------------------------------------------------------------------------------- /IsTreeSymmetric/solver.py: -------------------------------------------------------------------------------- 1 | # Definition for binary tree: 2 | # class Tree(object): 3 | # def __init__(self, x): 4 | # self.value = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | def inOrderTraversal(t, list=[]): 9 | 10 | if t == None: 11 | return [] 12 | 13 | if t.left is not None: 14 | inOrderTraversal(t.left,list) 15 | list += [t.value] 16 | if t.right is not None: 17 | inOrderTraversal(t.right,list) 18 | 19 | return list 20 | 21 | def reversedInOrderTraversal(t, rlist=[]): 22 | 23 | if t == None: 24 | return [] 25 | 26 | if t.right is not None: 27 | reversedInOrderTraversal(t.right) 28 | rlist += [t.value] 29 | if t.left is not None: 30 | reversedInOrderTraversal(t.left) 31 | 32 | return rlist 33 | 34 | def isTreeSymmetric(t): 35 | 36 | if t == None: 37 | return 1 38 | 39 | left_branch = None 40 | right_branch = None 41 | 42 | # branch for in order traversal 43 | if t.left is not None: 44 | left_branch = t.left 45 | 46 | # branch for 'in order traversal' 47 | left_list = inOrderTraversal(left_branch) 48 | print(left_list) 49 | 50 | # ---- 51 | 52 | # branch for reversed in order traversal 53 | if t.right is not None: 54 | right_branch = t.right 55 | 56 | # branch for 'symmetrical/reversed in order traversal' 57 | right_list = reversedInOrderTraversal(right_branch) 58 | print(right_list) 59 | 60 | if left_list == right_list: 61 | return 1 62 | else: 63 | return 0 -------------------------------------------------------------------------------- /IsTreeSymmetric/README.md: -------------------------------------------------------------------------------- 1 | Given a binary tree `t`, determine whether it is symmetric around its center, i.e. each side mirrors the other. 2 | 3 | **Example** 4 | 5 | - For 6 | 7 | ``` 8 | t = { 9 | "value": 1, 10 | "left": { 11 | "value": 2, 12 | "left": { 13 | "value": 3, 14 | "left": null, 15 | "right": null 16 | }, 17 | "right": { 18 | "value": 4, 19 | "left": null, 20 | "right": null 21 | } 22 | }, 23 | "right": { 24 | "value": 2, 25 | "left": { 26 | "value": 4, 27 | "left": null, 28 | "right": null 29 | }, 30 | "right": { 31 | "value": 3, 32 | "left": null, 33 | "right": null 34 | } 35 | } 36 | } 37 | ``` 38 | the output should be `isTreeSymmetric(t) = true`. 39 | 40 | Here's what the tree in this example looks like: 41 | ``` 42 | 1 43 | / \ 44 | 2 2 45 | / \ / \ 46 | 3 4 4 3 47 | ``` 48 | 49 | As you can see, it is symmetric. 50 | 51 | - For 52 | ``` 53 | t = { 54 | "value": 1, 55 | "left": { 56 | "value": 2, 57 | "left": null, 58 | "right": { 59 | "value": 3, 60 | "left": null, 61 | "right": null 62 | } 63 | }, 64 | "right": { 65 | "value": 2, 66 | "left": null, 67 | "right": { 68 | "value": 3, 69 | "left": null, 70 | "right": null 71 | } 72 | } 73 | } 74 | ``` 75 | the output should be `isTreeSymmetric(t) = false`. 76 | 77 | Here's what the tree in this example looks like: 78 | ``` 79 | 1 80 | / \ 81 | 2 2 82 | \ \ 83 | 3 3 84 | ``` 85 | 86 | As you can see, it is not symmetric. -------------------------------------------------------------------------------- /IsCryptarithmSolution/README.md: -------------------------------------------------------------------------------- 1 | A cryptarithm is a mathematical puzzle for which the goal is to find the correspondence between letters and digits, such that the given arithmetic equation consisting of letters holds true when the letters are converted to digits. 2 | 3 | You have an array of strings `crypt`, the cryptarithm, and an an array containing the mapping of letters and digits, `solution`. The array `crypt` will contain three non-empty strings that follow the structure: `[word1, word2, word3]`, which should be interpreted as the `word1 + word2 = word3` cryptarithm. 4 | 5 | If `crypt`, when it is decoded by replacing all of the letters in the cryptarithm with digits using the mapping in `solution`, becomes a valid arithmetic equation containing no numbers with leading zeroes, the answer is `true`. If it does not become a valid arithmetic solution, the answer is `false`. 6 | 7 | **Example** 8 | 9 | For `crypt = ["SEND", "MORE", "MONEY"]` and 10 | 11 | ``` 12 | solution = [['O', '0'], 13 | ['M', '1'], 14 | ['Y', '2'], 15 | ['E', '5'], 16 | ['N', '6'], 17 | ['D', '7'], 18 | ['R', '8'], 19 | ['S', '9']] 20 | ``` 21 | 22 | the output should be 23 | `isCryptSolution(crypt, solution) = true`. 24 | 25 | When you decrypt `"SEND"`, `"MORE"`, and `"MONEY"` using the mapping given in `crypt`, you get `9567 + 1085 = 10652` which is correct and a valid arithmetic equation. 26 | 27 | For `crypt = ["TEN", "TWO", "ONE"]` and 28 | 29 | ``` 30 | solution = [['O', '1'], 31 | ['T', '0'], 32 | ['W', '9'], 33 | ['E', '5'], 34 | ['N', '4']] 35 | ``` 36 | 37 | the output should be 38 | `isCryptSolution(crypt, solution) = false`. 39 | 40 | Even though `054 + 091 = 145`, `054` and `091` both contain leading zeroes, meaning that this is not a valid solution. -------------------------------------------------------------------------------- /Quora-Bot-1/solver.py: -------------------------------------------------------------------------------- 1 | import operator 2 | 3 | def mostViewedWriters(topicIds, answerIds, views): 4 | 5 | final_dict = {} 6 | 7 | uniq_topic_ids = set([topicIds[i][j] for i in range(len(topicIds)) for j in range(len(topicIds[i])) ]) 8 | 9 | for u in uniq_topic_ids: 10 | 11 | u_indexes = [x for x in range(len(topicIds)) if u in topicIds[x] ] 12 | 13 | tmp = [answerIds[x] for x in u_indexes] 14 | cur_answer_ids = [tmp[i][j] for i in range(len(tmp)) for j in range(len(tmp[i])) ] 15 | 16 | cur_user_id = [views[x][1] for x in range(len(views)) if views[x][0] in cur_answer_ids] 17 | cur_views = [views[x][2] for x in range(len(views)) if views[x][0] in cur_answer_ids] 18 | 19 | 20 | for (user, view) in zip(cur_user_id, cur_views): 21 | if u not in final_dict: 22 | final_dict[u] = [ [user, view] ] 23 | else: 24 | id_to_add_views = [x for x in range(len(final_dict[u])) if final_dict[u][x][0] == user] 25 | if not id_to_add_views: 26 | final_dict[u].append([user, view]) 27 | else: 28 | idx = id_to_add_views[0] 29 | final_dict[u][idx][1] += view 30 | 31 | final_arr = [] 32 | 33 | for k in sorted(uniq_topic_ids): 34 | if k not in final_dict: 35 | final_arr.append([]) 36 | else: 37 | sublist = final_dict[k] 38 | sorted_sublist1 = sorted(sublist, key=operator.itemgetter(0)) 39 | sorted_sublist = sorted(sorted_sublist1, key=operator.itemgetter(1), reverse=True) 40 | 41 | if len(sorted_sublist) > 10: 42 | sorted_sublist = sorted_sublist[:10] 43 | final_arr.append(sorted_sublist) 44 | 45 | return(final_arr) 46 | 47 | -------------------------------------------------------------------------------- /Sudoku2/sudoku2.py: -------------------------------------------------------------------------------- 1 | def line_is_valid(row): 2 | 3 | tmp_dict = {} 4 | valid = True 5 | 6 | if len(row) > 0: 7 | #print(row) 8 | for r in row: 9 | if r in tmp_dict: 10 | tmp_dict[r] += 1 11 | else: 12 | tmp_dict[r] = 1 13 | 14 | if tmp_dict[max(tmp_dict, key=tmp_dict.get)] > 1: 15 | valid = False 16 | 17 | return valid 18 | 19 | 20 | def grid_is_valid(grid): 21 | 22 | valid = True 23 | 24 | for i in range(len(grid)): 25 | row = [int(x) for x in grid[i] if x != '.'] 26 | #print(row) 27 | valid = line_is_valid(row) 28 | if not valid: 29 | break 30 | 31 | return valid 32 | 33 | def sudoku2(grid): 34 | 35 | result = False 36 | 37 | # check rows: 38 | rows_valid = grid_is_valid(grid) 39 | 40 | # check columns: 41 | col_valid = grid_is_valid(list(zip(*grid))) 42 | 43 | # check 3x3 grids: 44 | grid3x3_valid = True 45 | for i in range(0,len(grid), 3): 46 | 47 | if not grid3x3_valid: 48 | break 49 | 50 | sub_mat = grid[i:i+3] 51 | 52 | for j in range(0,len(grid[0]),3): 53 | 54 | tmp_list = [x[j:j+3] for x in sub_mat] 55 | #print(tmp_list) 56 | tmp_list = [tmp_list[k][l] for k in range(len(tmp_list)) for l in range(len(tmp_list[k]))] 57 | 58 | row = [int(x) for x in tmp_list if x != '.'] 59 | grid3x3_valid = line_is_valid(row) 60 | #print(grid3x3_valid) 61 | 62 | if not grid3x3_valid: 63 | break 64 | 65 | 66 | if rows_valid and col_valid and grid3x3_valid: 67 | result = True 68 | 69 | return result -------------------------------------------------------------------------------- /groupingDishes/README.md: -------------------------------------------------------------------------------- 1 | You have a list of `dishes`. Each dish is associated with a list of ingredients used to prepare it. You want to group the dishes by ingredients, so that for each ingredient you'll be able to find all the dishes that contain it (if there are at least `2` such dishes). 2 | 3 | Return an array where each element is a list with the first element equal to the name of the ingredient and all of the other elements equal to the names of dishes that contain this ingredient. The dishes inside each list should be sorted *lexicographically*. The result array should be sorted *lexicographically* by the names of the ingredients in its elements. 4 | 5 | **Example** 6 | 7 | - For 8 | ``` 9 | dishes = [["Salad", "Tomato", "Cucumber", "Salad", "Sauce"], 10 | ["Pizza", "Tomato", "Sausage", "Sauce", "Dough"], 11 | ["Quesadilla", "Chicken", "Cheese", "Sauce"], 12 | ["Sandwich", "Salad", "Bread", "Tomato", "Cheese"]] 13 | ``` 14 | the output should be 15 | ``` 16 | groupingDishes(dishes) = [["Cheese", "Quesadilla", "Sandwich"], 17 | ["Salad", "Salad", "Sandwich"], 18 | ["Sauce", "Pizza", "Quesadilla", "Salad"], 19 | ["Tomato", "Pizza", "Salad", "Sandwich"]] 20 | ``` 21 | 22 | - For 23 | ``` 24 | dishes = [["Pasta", "Tomato Sauce", "Onions", "Garlic"], 25 | ["Chicken Curry", "Chicken", "Curry Sauce"], 26 | ["Fried Rice", "Rice", "Onions", "Nuts"], 27 | ["Salad", "Spinach", "Nuts"], 28 | ["Sandwich", "Cheese", "Bread"], 29 | ["Quesadilla", "Chicken", "Cheese"]] 30 | ``` 31 | the output should be 32 | ``` 33 | groupingDishes(dishes) = [["Cheese", "Quesadilla", "Sandwich"], 34 | ["Chicken", "Chicken Curry", "Quesadilla"], 35 | ["Nuts", "Fried Rice", "Salad"], 36 | ["Onions", "Fried Rice", "Pasta"]] 37 | ``` -------------------------------------------------------------------------------- /Sudoku2/README.md: -------------------------------------------------------------------------------- 1 | Sudoku is a number-placement puzzle. The objective is to fill a `9 × 9` grid with numbers in such a way that each column, each row, and each of the nine `3 × 3` sub-grids that compose the grid all contain all of the numbers from `1` to `9` one time. 2 | 3 | Implement an algorithm that will check whether the given `grid` of numbers represents a valid Sudoku puzzle according to the layout rules described above. Note that the puzzle represented by `grid` does not have to be solvable. 4 | 5 | **Example** 6 | 7 | * For 8 | 9 | ``` 10 | 11 | grid = [['.', '.', '.', '1', '4', '.', '.', '2', '.'], 12 | ['.', '.', '6', '.', '.', '.', '.', '.', '.'], 13 | ['.', '.', '.', '.', '.', '.', '.', '.', '.'], 14 | ['.', '.', '1', '.', '.', '.', '.', '.', '.'], 15 | ['.', '6', '7', '.', '.', '.', '.', '.', '9'], 16 | ['.', '.', '.', '.', '.', '.', '8', '1', '.'], 17 | ['.', '3', '.', '.', '.', '.', '.', '.', '6'], 18 | ['.', '.', '.', '.', '.', '7', '.', '.', '.'], 19 | ['.', '.', '.', '5', '.', '.', '.', '7', '.']] 20 | 21 | ``` 22 | 23 | the output should be 24 | `sudoku2(grid) = true` 25 | 26 | * For 27 | 28 | ``` 29 | 30 | grid = [['.', '.', '.', '.', '2', '.', '.', '9', '.'], 31 | ['.', '.', '.', '.', '6', '.', '.', '.', '.'], 32 | ['7', '1', '.', '.', '7', '5', '.', '.', '.'], 33 | ['.', '7', '.', '.', '.', '.', '.', '.', '.'], 34 | ['.', '.', '.', '.', '8', '3', '.', '.', '.'], 35 | ['.', '.', '8', '.', '.', '7', '.', '6', '.'], 36 | ['.', '.', '.', '.', '.', '2', '.', '.', '.'], 37 | ['.', '1', '.', '2', '.', '.', '.', '.', '.'], 38 | ['.', '2', '.', '.', '3', '.', '.', '.', '.']] 39 | 40 | ``` 41 | 42 | the output should be 43 | `sudoku2(grid) = false`. 44 | 45 | The given `grid` is not correct because there are two `1`s in the second column. Each column, each row, and each `3 × 3` subgrid can only contain the numbers `1` through `9` one time. 46 | -------------------------------------------------------------------------------- /Quora-Bot-3_Knapsack_with_Dynamic_Programming/solver.py: -------------------------------------------------------------------------------- 1 | def find_best_combination(stories, h): 2 | 3 | #print('*************') 4 | #print(h, stories) 5 | # find optimal combination of stories with score: max and sum(size) <= h 6 | 7 | vals = [0] 8 | weights = [0] 9 | keys = [] 10 | 11 | # init values and weights 12 | for s in sorted(stories): 13 | l = stories[s] 14 | #print(l) 15 | vals += [l[1]] 16 | weights += [l[2]] 17 | keys += [s] 18 | 19 | n = len(stories) 20 | #print('n:', n) 21 | #print(stories) 22 | m = [ [0] * (h+1) for _ in range(n+1)] 23 | 24 | for j in range(h+1): 25 | m[0][j] = 0 26 | 27 | for i in range(1,n+1): 28 | for j in range(h+1): 29 | if weights[i] > j: 30 | m[i][j] = m[i-1][j] 31 | else: 32 | m[i][j] = max(m[i-1][j], m[i-1][j - weights[i]] + vals[i]) 33 | 34 | path = [] 35 | 36 | j = h 37 | for i in range(n, 0, -1): 38 | #print(i) 39 | if m[i][j] != m[i-1][j]: 40 | path.append(i-1) 41 | 42 | j -= weights[i] 43 | 44 | path.reverse() 45 | 46 | final_path = [] 47 | for p in path: 48 | final_path += [keys[p]] 49 | 50 | final_path = [m[n][h]] + final_path 51 | #print(keys) 52 | return final_path 53 | 54 | 55 | 56 | def feedOptimizer(span, h, events): 57 | 58 | result = [] 59 | 60 | stories = {} 61 | story_timestamps = {} 62 | 63 | start_time = 0 64 | i = 0 65 | for e in events: 66 | 67 | # new story event 68 | if len(e) == 3: 69 | #print('\n----- Story -----') 70 | if i == 0: # 1st timestamp 71 | start_time = e[0] 72 | 73 | i += 1 74 | stories[i] = e 75 | story_timestamps[i] = e[0] 76 | #print('story_timestamps:', story_timestamps) 77 | 78 | else: # calc feed output 79 | cur_time = e[0] 80 | #print('\n----- reload -----') 81 | #print('cur_time:', cur_time) 82 | #elapsed_time = cur_time - start_time 83 | 84 | ids_to_del = [x for x in story_timestamps if story_timestamps[x] < cur_time - span] 85 | 86 | for k in ids_to_del: 87 | #print('delete dict elems') 88 | #print(k) 89 | del story_timestamps[k] 90 | del stories[k] 91 | #print(stories) 92 | 93 | if len(stories): 94 | cur_res = find_best_combination(stories, h) 95 | 96 | result += [cur_res] 97 | else: 98 | result += [[0]] 99 | 100 | return result 101 | 102 | 103 | -------------------------------------------------------------------------------- /HasPathWithGivenSum/README.md: -------------------------------------------------------------------------------- 1 | Given a binary tree `t` and an integer `s`, determine whether there is a root to leaf path in `t` such that the sum of vertex values equals `s`. 2 | 3 | **Example** 4 | 5 | - For 6 | 7 | ``` 8 | t = { 9 | "value": 4, 10 | "left": { 11 | "value": 1, 12 | "left": { 13 | "value": -2, 14 | "left": null, 15 | "right": { 16 | "value": 3, 17 | "left": null, 18 | "right": null 19 | } 20 | }, 21 | "right": null 22 | }, 23 | "right": { 24 | "value": 3, 25 | "left": { 26 | "value": 1, 27 | "left": null, 28 | "right": null 29 | }, 30 | "right": { 31 | "value": 2, 32 | "left": { 33 | "value": -2, 34 | "left": null, 35 | "right": null 36 | }, 37 | "right": { 38 | "value": -3, 39 | "left": null, 40 | "right": null 41 | } 42 | } 43 | } 44 | } 45 | ``` 46 | 47 | and 48 | `s = 7`, 49 | the output should be `hasPathWithGivenSum(t, s) = true`. 50 | 51 | This is what this tree looks like: 52 | 53 | ``` 54 | 4 55 | / \ 56 | 1 3 57 | / / \ 58 | -2 1 2 59 | \ / \ 60 | 3 -2 -3 61 | ``` 62 | 63 | Path `4 -> 3 -> 2 -> -2` gives us `7`, the required sum. 64 | 65 | - For 66 | 67 | ``` 68 | t = { 69 | "value": 4, 70 | "left": { 71 | "value": 1, 72 | "left": { 73 | "value": -2, 74 | "left": null, 75 | "right": { 76 | "value": 3, 77 | "left": null, 78 | "right": null 79 | } 80 | }, 81 | "right": null 82 | }, 83 | "right": { 84 | "value": 3, 85 | "left": { 86 | "value": 1, 87 | "left": null, 88 | "right": null 89 | }, 90 | "right": { 91 | "value": 2, 92 | "left": { 93 | "value": -4, 94 | "left": null, 95 | "right": null 96 | }, 97 | "right": { 98 | "value": -3, 99 | "left": null, 100 | "right": null 101 | } 102 | } 103 | } 104 | } 105 | ``` 106 | and 107 | `s = 7`, 108 | the output should be `hasPathWithGivenSum(t, s) = false`. 109 | 110 | This is what this tree looks like: 111 | 112 | ``` 113 | 4 114 | / \ 115 | 1 3 116 | / / \ 117 | -2 1 2 118 | \ / \ 119 | 3 -4 -3 120 | ``` 121 | 122 | There is no path from root to leaf with the given sum `7`. -------------------------------------------------------------------------------- /Quora-Bot-2/README.md: -------------------------------------------------------------------------------- 1 | For the purposes of this problem, suppose that Quora has `n` questions, and question `i` takes `ti` time to read. Some questions are related to each other. If we connect related questions by edges, we get an undirected graph such that there exists exactly one path from any question to another. In other words, the graph of related questions is a tree. 2 | 3 | Every time Steve reads a question, he will see a list of questions that are directly related to it and will navigate at random to one that he hasn't read yet (all related questions have an equal chance of being viewed). Steve will stop reading once there are no unread related questions left. 4 | 5 | Given the number of related questions `n`, an array that contains the estimated reading time for each question `t`, and an array containing the pairs of related questions `edges`, which question should we show to Steve first so that we minimize his total expected reading time? It is guaranteed that there is one unique question that is optimal. 6 | 7 | Here's how the total expected time for question `i` with `q` related questions is calculated: 8 | 9 | * Take the time `ti` that it will take Steve to read this question; 10 | * Recursively calculate the `expected_timej` for each related question `j` without considering the `ith` question; 11 | * Add to `ti` the sum of `expected_timej` for each `j`, divided by `q`, i.e. the answer will be equal to `ti + sum(expected_timej) / q`. 12 | 13 | **Example** 14 | 15 | For `n = 5`, `t = [2, 2, 1, 2, 2]` and `edges = [[0, 1], [1, 2], [2, 3], [3, 4]]`, the output should be 16 | `relatedQuestions(n, t, edges) = 2`. 17 | 18 | For this example, the tree can be visualized as: 19 | 20 | ![example](example.png) 21 | 22 | Let's calculate the answers for each of the `5` vertices: 23 | 24 | * If Steve starts reading from question `0`, then the expected reading time equals `t0 + expected_time1 / 1 = t0 + (t1 + expected_time2 / 1) / 1 = ... = t0 + (t1 + (t2 + (t3 + (t4 + 0 / 1) / 1) / 1) / 1) / 1 = t0 + t1 + t2 + t3 + t4 = 2 + 2 + 1 + 2 + 2 = 9`. 25 | * If Steve starts reading from question `1`, then the expected reading time equals `t1 + (expected_time0 + expected_time2) / 2 = t1 + ((t0 + 0 / 1) + (t2 + expected_time3 / 1)) / 2 = t1 + (t0 + t2 + (t3 + (t4 + 0 / 1) / 1) / 1) / 2 = t1 + (t0 + t2 + t3 + t4) / 2 = 2 + (2 + 1 + 2 + 2) / 2 = 5.5`. 26 | * If Steve starts reading from question `2`, then the expected reading time equals `t2 + (expected_time1 + expected_time3) / 2 = t2 + ((t1 + expected_time0 / 1) + (t3 + expected_time4 / 1)) / 2 = t2 + ((t1 + t0) + (t3 + t4)) / 2 = t2 + (t1 + t0 + t3 + t4) / 2 = 1 + (2 + 2 + 2 + 2) / 2 = 5`. 27 | * The expected reading time for vertex `3` is equal to the expected reading time for vertex `1`, because they are symmetric in the tree. The same works for vertices `4` and `0`. 28 | 29 | So, as we can see, the optimal vertex to start with is vertex `2`, since that gives us the smallest expected reading time. -------------------------------------------------------------------------------- /Quora-Bot-3_Knapsack_with_Dynamic_Programming/README.md: -------------------------------------------------------------------------------- 1 | Quora shows a customized feed of recent stories on a user's home page. Stories in Quora refer to activities that happen on the site, such as when a user adds a question or upvotes an answer. Every story has a score, which represents the value that the story brings to the user. The goal is to quickly generate a feed of the best and most recent stories for the user every time they reload their Quora home page. 2 | 3 | Your task is to design the algorithm that picks the stories that are displayed in this feed. 4 | 5 | You are given a list of stories that, for each story, contains: the time the story was published, the story's score, and the height in pixels that it takes to display the story. Given the total number of pixels h that are available for displaying the story feed in the browser, you want to maximize the sum of the scores for the stories that you can display in the feed every time the user reloads their home page. You can only consider recent stories, so a story can be displayed at any given moment only if it was posted no longer than span units of time before that moment. You do not have to use up all the pixels available in the browser. 6 | 7 | For each reload event, return an array where the first element is the best available sum of scores, and the other elements are the set of story IDs that correspond to that score sum. The IDs should be returned in ascending order. The answer arrays should be ordered by their corresponding reload event times. 8 | 9 | If two sets of stories have the same score, choose the set that contains fewer stories. If there is still a tie, choose the set which has the lexicographically smaller set of IDs. 10 | 11 | **Example** 12 | 13 | For `span = 10`, `h = 100` and 14 | 15 | ``` 16 | events = [[11, 50, 30], 17 | [12], 18 | [13, 40, 20], 19 | [14, 45, 40], 20 | [15], 21 | [16], 22 | [18, 45, 20], 23 | [21], 24 | [22]] 25 | ``` 26 | 27 | the output should be 28 | 29 | ``` 30 | feedOptimizer(span, h, events) = [[50, 1], 31 | [135, 1, 2, 3], 32 | [135, 1, 2, 3], 33 | [140, 1, 3, 4], 34 | [130, 2, 3, 4]] 35 | ``` 36 | 37 | 38 | There are 4 stories (with IDs 1 to 4) and 5 reload events. 39 | 40 | * At the first reload, there is only one story (ID = 1) with score of 50 available for display; 41 | * After the next two reloads, there are 3 stories that take up 90 of the 100 pixels available, for a total score of 135; 42 | * After reloading at time 21, there are 4 stories available to choose from, but only 3 will fit into the browser height. The best set is `[1, 3, 4]` for a total score of 140; 43 | * At the last reload event, you can no longer consider story 1 when choosing stories because it is more than 10 time units old. 44 | 45 | The best set of scores is thus `[2, 3, 4]`. 46 | 47 | For a good visualization of this, check out the image below: 48 | 49 | ![example](example.png) -------------------------------------------------------------------------------- /Quora-Bot-1/README.md: -------------------------------------------------------------------------------- 1 | On Quora, a question can have a variety of user-submitted answers. These questions are assigned topic tags to improve discoverability, and views are tracked at the answer level to identify the top answers and surface them in the the feed and search results. 2 | 3 | More specifically: 4 | 5 | * A user can write an answer to a question; 6 | * A question can have multiple answers; 7 | * A question can be assigned multiple topics; 8 | * For example, the question "How many software engineers work at Google as of 2017?" is tagged with the topics "Silicon Valley", "Google", and "Software Engineering". 9 | * An answer can get views. 10 | 11 | The Most-Viewed Writers for a given topic are the top 10 Quora users whose answers to questions tagged with that topic are viewed the most. (When fewer than 10 users have submitted answers to questions tagged with a particular topic, the Most-Viewed Writers for that topic would include all the users who have contributed answers, regardless of whether or not their answers have any views.) An answer must belong to a question that is tagged with a given topic to be considered to be within that topic. 12 | 13 | Given this system, compute the Most Viewed Writers for each topic, ordered from the smallest `topic_id` to the largest one. If two users have the same number of views, the user with the smaller user_id should come first. 14 | 15 | For a specific `topic_id`, the set of Most-Viewed Writers should be returned in the following format: 16 | 17 | * 18 | * 19 | * ... 20 | * 21 | 22 | where: 23 | 24 | * `user_id_i` is the ID of the `ith` user in the set; 25 | * `views_i` is the total number of views the user gets across all their answers in that topic; 26 | * Note that `views_i` may be equal to `0`. If a user posted an answer that didn't get any views, they can still be included in the Most Viewed Writers list if there are fewer than `10` users who have contributed answers for that topic; 27 | * `N` is the number of Most Viewed Writers for the topic `topic_id`. 28 | 29 | **Example** 30 | 31 | For `topicIds = [[1, 2, 3], [2, 3, 4], [1, 4], [2, 3]]`, 32 | 33 | `answerIds = [[6, 4], [1, 2], [5], [3]]` and 34 | 35 | `views = [[2, 1, 2], [6, 3, 5], [3, 3, 0], [5, 1, 1], [4, 2, 3], [1, 4, 2]]`, the output should be: 36 | 37 | ``` 38 | 39 | mostViewedWriters(topicIds, answerIds, views) = [ 40 | [[3, 5], [2, 3], [1, 1]], 41 | [[3, 5], [2, 3], [1, 2], [4, 2]], 42 | [[3, 5], [2, 3], [1, 2], [4, 2]], 43 | [[1, 3], [4, 2]] 44 | ] 45 | 46 | ``` 47 | 48 | In this example, we have `4` different topic IDs: `1`, `2`, `3`, and `4`. Let's find the Most Viewed Writers for each of them. 49 | 50 | * **For `topic_id = 1`**: 51 | * As we can see in the `topicIds` array, topic `1` is tagged to questions `0` and `2`. 52 | * We can see in the `answerIds` array that the answers corresponding to this topic are `6`, `4`, and `5`. 53 | * Now let's look at the `views` array and find all such `views[i]` that `views[i][0]` is one of the answer IDs from the last line: 54 | `views[1][0] = 6`, so we add `views[1][2] = 5` views to the user with ID `views[1][1] = 3`; 55 | `views[3][0] = 5`, so we add `views[3][2] = 1` views to the user with ID `views[3][1] = 1`; 56 | `views[4][0] = 4`, so we add `views[4][2] = 3` views to the user with ID `views[4][1] = 2`. 57 | * To recap, for `topic_id = 1` we have `3` Most Viewed Writers: the user with ID `3` has `5` views, the user with ID `2` has `3` views, and the user with ID `1` has `1` view. 58 | 59 | * **For `topic_id = 2`**: 60 | * As we can see in the topicIds array, topic `2` is tagged to questions `0`, `1`, and `3`. 61 | * We can see in the answerIds array that the answers corresponding to this topic are `6`, `4`, `1`, `2`, and `3`. 62 | * Now let's look at the `views` array and find all such `views[i]` that `views[i][0]` is one of our answer IDs: 63 | `views[1][0] = 6`, so we add `views[1][2] = 5` views to the user with ID `views[1][1] = 3`; 64 | `views[4][0] = 4`, so we add `views[4][2] = 3` views to the user with ID `views[4][1] = 2`; 65 | `views[5][0] = 1`, so we add `views[5][2] = 2` views to the user with ID `views[5][1] = 4`; 66 | `views[0][0] = 2`, so we add `views[0][2] = 2` views to the user with ID `views[4][1] = 1`; 67 | `views[2][0] = 3`, so we add `views[3][2] = 0` views to the user with ID `views[3][1] = 3`. 68 | 69 | * To recap, for `topic_id = 2` we have `4` Most Viewed Writers: the user with ID `3` has `5` views, the user with ID `2` has `3` views, the user with ID `1` has `2` views, and the user with ID `4` has `2` views. The last two users are ordered as they are because the user with the smaller ID comes first. 70 | 71 | * **For `topic_id = 3`**: 72 | * This topic is tagged to the same questions as `topic_id = 2` is, so its Most Viewed Writers is also the same. 73 | 74 | * **For `topic_id = 4`**: 75 | * As we can see in the `topicId` array, this topic is tagged to questions `1` and `2`. 76 | * We can see in the `answerId` array that the answers corresponding to this topic are `1`, `2`, and `5`. 77 | * Now let's look at the `views` array and find all such `views[i]` that `views[i][0]` is one of our above answer IDs: 78 | `views[5][0] = 1`, so we add `views[5][2] = 2` views to the user with ID `views[5][1] = 4`; 79 | `views[0][0] = 2`, so we add `views[0][2] = 2` views to the user with ID `views[0][1] = 1`; 80 | `views[3][0] = 5`, so we add `views[3][2] = 1` views to the user with ID `views[3][1] = 1`. 81 | * To recap, for `topic_id = 4` we have `2` Most Viewed Writers: the user with ID `1` has `3` views, and the user with ID `4` has `2` views. 82 | --------------------------------------------------------------------------------