├── find-the-difference.py ├── divar ├── 1.py ├── 2.py ├── 3.py ├── 4.py └── 5.py ├── merge-strings-alternately.py ├── non-overlapping-intervals.py ├── subsets.py ├── 3sum.py ├── climbing-stairs.py ├── longest-substring-without-repeating-characters.py ├── valid-parentheses.py ├── daily-temperatures.py ├── zigzag-conversion.py ├── find-the-index-of-the-first-occurrence-in-a-string.py ├── container-with-most-water.py ├── subarray-sum-equals-k.py ├── merge-intervals.py ├── maximum-depth-of-binary-tree.py ├── symmetric-tree.py ├── two-sum.py ├── binary-tree-level-order-traversal.py ├── number-of-islands.py ├── binary-tree-zigzag-level-order-traversal.py ├── minimum-window-substring.py ├── word-ladder.py ├── longest-palindrome.py ├── house-robber.py ├── network-delay-time.py ├── word-search.py ├── low-level-design └── elevator.py └── word-ladder-ii.py /find-the-difference.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findTheDifference(self, s: str, t: str) -> str: 3 | t_list = list(t) 4 | for letter in s: 5 | t_list.remove(letter) 6 | 7 | return t_list[0] 8 | -------------------------------------------------------------------------------- /divar/1.py: -------------------------------------------------------------------------------- 1 | n, x = list(map(int, input().split())) 2 | A = list(map(int, input().split())) 3 | A_set = set(A) 4 | is_awesome = False 5 | 6 | for num in A: 7 | desired_num = x - num 8 | if desired_num in A_set: 9 | if desired_num == num and A.count(num) == 1: 10 | continue 11 | is_awesome = True 12 | break 13 | 14 | if is_awesome: 15 | print("YES") 16 | else: 17 | print("NO") 18 | -------------------------------------------------------------------------------- /divar/2.py: -------------------------------------------------------------------------------- 1 | def count_sms(message): 2 | s_count = 0 3 | sm_count = 0 4 | sms_count = 0 5 | 6 | for letter in message: 7 | if letter == "s": 8 | s_count += 1 9 | sms_count += sm_count 10 | elif letter == "m": 11 | sm_count += s_count 12 | 13 | return sms_count 14 | 15 | 16 | for _ in range(int(input())): 17 | message = input() 18 | result = count_sms(message) 19 | print(result) 20 | -------------------------------------------------------------------------------- /merge-strings-alternately.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def mergeAlternately(self, word1: str, word2: str) -> str: 3 | output = str() 4 | longer_length = len(word1) 5 | if longer_length < len(word2): 6 | longer_length = len(word2) 7 | 8 | for i in range(longer_length): 9 | if i < len(word1): 10 | output += word1[i] 11 | if i < len(word2): 12 | output += word2[i] 13 | 14 | return output 15 | -------------------------------------------------------------------------------- /non-overlapping-intervals.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def eraseOverlapIntervals(self, intervals): 3 | intervals.sort(key=lambda x: x[1]) 4 | 5 | prev_end = intervals[0][1] 6 | remove_count = 0 7 | for interval in intervals[1:]: 8 | start, end = interval 9 | 10 | if prev_end > start: 11 | remove_count += 1 12 | 13 | else: 14 | prev_end = end 15 | 16 | return remove_count -------------------------------------------------------------------------------- /subsets.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Solution: 5 | def subsets(self, nums: List[int]) -> List[List[int]]: 6 | results = list() 7 | 8 | def find_subset(num_index, result): 9 | results.append(result) 10 | for new_num_index in range(num_index, len(nums)): 11 | find_subset(new_num_index + 1, result + [nums[new_num_index]]) 12 | 13 | find_subset(0, []) 14 | return results 15 | 16 | 17 | Solution().subsets([1, 2, 3]) 18 | -------------------------------------------------------------------------------- /3sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def threeSum(self, nums): 3 | answers = set() 4 | for num1_index in range(len(nums)): 5 | for num2_index in range(len(nums)): 6 | if num1_index == num2_index: 7 | continue 8 | num1 = nums[num1_index] 9 | num2 = nums[num2_index] 10 | if (-(num1 + num2)) in set(nums[num2_index + 1 :]): 11 | answers.add(tuple(sorted([num1, num2, -(num1 + num2)]))) 12 | return list(answers) 13 | -------------------------------------------------------------------------------- /climbing-stairs.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def climbStairs(self, n: int) -> int: 3 | memo = {} 4 | def climb(n): 5 | if n in memo: 6 | return memo[n] 7 | 8 | if n == 1: 9 | return 1 10 | if n == 2: 11 | return 2 12 | 13 | answer = climb(n - 1) + climb(n - 2) 14 | memo[n] = answer 15 | 16 | return answer 17 | 18 | return climb(n) 19 | 20 | print(Solution().climbStairs(3)) -------------------------------------------------------------------------------- /longest-substring-without-repeating-characters.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lengthOfLongestSubstring(self, s: str) -> int: 3 | char_set = set() 4 | left = 0 5 | longest_string_found = 0 6 | 7 | for right in range(len(s)): 8 | while s[right] in char_set: 9 | char_set.remove(s[left]) 10 | left += 1 11 | char_set.add(s[right]) 12 | longest_string_found = max(longest_string_found, right - left + 1) 13 | 14 | return longest_string_found 15 | -------------------------------------------------------------------------------- /valid-parentheses.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isValid(self, s: str) -> bool: 3 | stack = list() 4 | mapping = { 5 | ")": "(", 6 | "}": "{", 7 | "]": "[", 8 | } 9 | for letter in s: 10 | needed_letter = mapping.get(letter, None) 11 | if needed_letter and stack and stack[-1] == needed_letter: 12 | stack.pop() 13 | else: 14 | stack.append(letter) 15 | if stack: 16 | return False 17 | return True -------------------------------------------------------------------------------- /daily-temperatures.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def dailyTemperatures(self, temperatures): 3 | days = [0] * len(temperatures) 4 | stack = list() 5 | for i in range(len(temperatures)): 6 | temperature = temperatures[i] 7 | 8 | while stack and temperatures[stack[-1]] < temperature: 9 | popped_index = stack.pop() 10 | days[popped_index] = i - popped_index 11 | stack.append(i) 12 | return days 13 | 14 | 15 | print(Solution().dailyTemperatures([73, 74, 75, 71, 69, 72, 76, 73])) 16 | -------------------------------------------------------------------------------- /zigzag-conversion.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def convert(self, s: str, numRows: int) -> str: 3 | rows = ["" for i in range(numRows)] 4 | if numRows == 1: 5 | cycle = 1 6 | else: 7 | cycle = numRows * 2 - 2 8 | for i in range(len(s)): 9 | i_ = i % cycle 10 | if (i_) < numRows: 11 | rows[i_] += s[i] 12 | else: 13 | rows[2 * (numRows - 1) - (i_)] += s[i] 14 | 15 | output = str() 16 | for row in rows: 17 | output += "".join(row) 18 | return output 19 | 20 | print(Solution().convert("PAYPALISHIRING", 4)) -------------------------------------------------------------------------------- /find-the-index-of-the-first-occurrence-in-a-string.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def strStr(self, haystack: str, needle: str) -> int: 3 | return haystack.find(needle) 4 | 5 | # if needle in haystack: 6 | # for i_haystack in range(len(haystack)): 7 | # output = i_haystack 8 | # if haystack[i_haystack] == needle[0]: 9 | # for i_needle in range(1, len(needle)): 10 | # if haystack[i_haystack + i_needle] != needle[i_needle]: 11 | # break 12 | # else: 13 | # return output 14 | # return -1 15 | -------------------------------------------------------------------------------- /container-with-most-water.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxArea(self, height) -> int: 3 | p1 = 0 4 | p2 = len(height) - 1 5 | max_water = 0 6 | 7 | while (p1 < p2): 8 | current_water = (p2 - p1) * min(height[p1], height[p2]) 9 | max_water = max(max_water, current_water) 10 | 11 | if height[p1] == height[p2]: 12 | p1 += 1 13 | p2 -= 1 14 | elif height[p1] > height[p2]: 15 | p2 -= 1 16 | else: 17 | p1 += 1 18 | return max_water 19 | 20 | print(Solution().maxArea([1,8,6,2,5,4,8,3,7])) -------------------------------------------------------------------------------- /subarray-sum-equals-k.py: -------------------------------------------------------------------------------- 1 | nums = [-1,-1,1] 2 | t = 1 3 | 4 | 5 | # p1 = 0 6 | # current_sum = float("-inf") 7 | # count = 0 8 | 9 | # for p2 in range(len(nums)): 10 | # current_sum += nums[p2] 11 | # while current_sum >= t and p1 <= p2: 12 | # if current_sum == t: 13 | # count += 1 14 | # current_sum -= nums[p1] 15 | # p1 += 1 16 | 17 | # print(count) 18 | 19 | 20 | prefix_sum = 0 21 | tracker = {0: 1} 22 | count = 0 23 | 24 | for num in nums: 25 | prefix_sum += num 26 | need = prefix_sum - t 27 | count += tracker.get(need, 0) 28 | tracker[prefix_sum] = tracker.get(prefix_sum, 0) + 1 29 | 30 | print(count) -------------------------------------------------------------------------------- /merge-intervals.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, intervals): 3 | intervals.sort(key=lambda x: x[0]) 4 | if len(intervals) <= 1: 5 | return intervals 6 | start = intervals[0][0] 7 | output_intervals = list() 8 | end = intervals[0][1] 9 | for interval in intervals[1:]: 10 | if interval[0] > end: 11 | output_intervals.append([start, end]) 12 | start = interval[0] 13 | end = max(end, interval[1]) 14 | if [start, end] not in output_intervals: 15 | output_intervals.append([start, end]) 16 | return output_intervals 17 | 18 | print(Solution().merge([[1,4],[2,3]])) -------------------------------------------------------------------------------- /maximum-depth-of-binary-tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def maxDepth(self, root: Optional[TreeNode]) -> int: 9 | 10 | if not root: 11 | return 0 12 | 13 | def search(node, depth): 14 | if not node: 15 | return depth 16 | 17 | if not node.left and not node.right: 18 | return depth 19 | 20 | depth += 1 21 | 22 | return max(search(node.right, depth), search(node.left, depth)) 23 | 24 | return search(root, 1) 25 | -------------------------------------------------------------------------------- /symmetric-tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | 8 | 9 | class Solution: 10 | def isSymmetric(self, root: Optional[TreeNode]) -> bool: 11 | if root is None: 12 | return True 13 | 14 | def is_mirror(left, right): 15 | if not left and not right: 16 | return True 17 | if not left or not right: 18 | return False 19 | if left.val != right.val: 20 | return False 21 | 22 | return is_mirror(left.left, right.right) and is_mirror( 23 | right.left, left.right 24 | ) 25 | 26 | return is_mirror(root.left, root.right) 27 | -------------------------------------------------------------------------------- /two-sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, nums, target: int): 3 | nums_count = dict() 4 | for num in nums: 5 | nums_count[num] = nums_count.get(num, 0) + 1 6 | 7 | for num in nums_count: 8 | desired_num = target - num 9 | desired_num_count = nums_count.get(desired_num, 0) 10 | if (desired_num == num and desired_num_count >= 2): 11 | first_index = nums.index(num) 12 | second_infex = nums[first_index + 1:].index(desired_num) + first_index + 1 13 | return [first_index, second_infex] 14 | 15 | if (desired_num != num and desired_num_count >= 1): 16 | first_index = nums.index(num) 17 | second_infex = nums.index(desired_num) 18 | return [first_index, second_infex] 19 | print(Solution().twoSum([3,3], 6)) -------------------------------------------------------------------------------- /binary-tree-level-order-traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def levelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: 9 | if root is None: 10 | return [] 11 | 12 | def level_order_traversal(nodes, output): 13 | new_nodes = [] 14 | values = [] 15 | for node in nodes: 16 | if node: 17 | values.append(node.val) 18 | new_nodes.append(node.left) 19 | new_nodes.append(node.right) 20 | if not new_nodes: 21 | return output 22 | output.append(values) 23 | return level_order_traversal(new_nodes, output) 24 | 25 | return level_order_traversal([root], []) 26 | -------------------------------------------------------------------------------- /number-of-islands.py: -------------------------------------------------------------------------------- 1 | grid = [["1","0","1","1","0","1","1"]] 2 | 3 | class Solution: 4 | def numIslands(self, grid) -> int: 5 | def dfs(grid, location): 6 | grid[location[0]][location[1]] = "0" 7 | 8 | directions = [(0, 1), (0, -1), (1, 0), (-1, 0)] 9 | for direction in directions: 10 | new_location = (location[0] + direction[0], location[1] + direction[1]) 11 | try: 12 | if new_location[0] >= 0 and new_location[1] >= 0 and grid[new_location[0]][new_location[1]] == "1": 13 | dfs(grid, new_location) 14 | except: 15 | pass 16 | 17 | counter = 0 18 | for i in range(len(grid)): 19 | for j in range(len(grid[0])): 20 | if grid[i][j] == "1": 21 | dfs(grid, (i, j)) 22 | counter += 1 23 | return counter 24 | 25 | print(Solution().numIslands(grid)) -------------------------------------------------------------------------------- /binary-tree-zigzag-level-order-traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def zigzagLevelOrder(self, root: Optional[TreeNode]) -> List[List[int]]: 9 | if root is None: 10 | return [] 11 | 12 | def level_order_traversal_zigzag(nodes, is_reversed, output): 13 | new_nodes = [] 14 | values = [] 15 | for node in nodes: 16 | if node: 17 | values.append(node.val) 18 | new_nodes.append(node.left) 19 | new_nodes.append(node.right) 20 | if not new_nodes: 21 | return output 22 | 23 | if is_reversed: 24 | values = values[::-1] 25 | output.append(values) 26 | 27 | return level_order_traversal_zigzag(new_nodes, not is_reversed, output) 28 | 29 | return level_order_traversal_zigzag([root], False, []) 30 | -------------------------------------------------------------------------------- /minimum-window-substring.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minWindow(self, s: str, t: str) -> str: 3 | p1 = 0 4 | p2 = 0 5 | min_window = "" 6 | current_slide = {} 7 | essential_slide = dict() 8 | 9 | def is_t_in(): 10 | for essential_letter in essential_slide: 11 | if current_slide.get(essential_letter, 0) < essential_slide[essential_letter]: 12 | return False 13 | return True 14 | 15 | for letter in t: 16 | essential_slide[letter] = essential_slide.get(letter, 0) + 1 17 | while p2 < len(s) or is_t_in() is True: 18 | if is_t_in() is True: 19 | if ((min_window != "" and ((p2 - p1) < len(min_window))) or min_window == ""): 20 | min_window = s[p1: p2] 21 | current_slide[s[p1]] -= 1 22 | p1 += 1 23 | else: 24 | current_slide[s[p2]] = current_slide.get(s[p2], 0) + 1 25 | p2 += 1 26 | 27 | return min_window 28 | 29 | print(Solution().minWindow(s = "ADOBECODEBANC", t = "ABC")) -------------------------------------------------------------------------------- /word-ladder.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from collections import deque, defaultdict 3 | 4 | 5 | class Solution: 6 | def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: 7 | if endWord not in wordList: 8 | return 0 9 | 10 | neighbors = defaultdict(list) 11 | for word in wordList: 12 | for i in range(len(word)): 13 | pattern = word[:i] + "*" + word[i + 1 :] 14 | neighbors[pattern].append(word) 15 | 16 | visited = set() 17 | queue = deque([beginWord]) 18 | 19 | steps = 1 20 | visited.add(beginWord) 21 | 22 | while queue: 23 | for i in range(len(queue)): 24 | word = queue.popleft() 25 | 26 | if word == endWord: 27 | return steps 28 | 29 | for j in range(len(word)): 30 | pattern = word[:j] + "*" + word[j + 1 :] 31 | for new_word in neighbors[pattern]: 32 | if new_word not in visited: 33 | visited.add(new_word) 34 | queue.append(new_word) 35 | steps += 1 36 | return 0 37 | -------------------------------------------------------------------------------- /longest-palindrome.py: -------------------------------------------------------------------------------- 1 | # class Solution: 2 | # def longestPalindrome(self, s: str) -> int: 3 | # letter_count = dict() 4 | # longest_palindrome = 0 5 | # the_odd_one = False 6 | # for letter in s: 7 | # letter_count[letter] = letter_count.get(letter, 0) + 1 8 | 9 | # for letter in letter_count: 10 | # if letter_count[letter] % 2 == 1 and the_odd_one is False: 11 | # longest_palindrome += letter_count[letter] 12 | # the_odd_one = True 13 | # elif letter_count[letter] % 2 == 1: 14 | # longest_palindrome += letter_count[letter] - 1 15 | # else: 16 | # longest_palindrome += letter_count[letter] 17 | 18 | # return longest_palindrome 19 | 20 | 21 | class Solution: 22 | def longestPalindrome(self, s: str) -> int: 23 | longest_palindrome = 0 24 | history = set() 25 | for letter in s: 26 | if letter in history: 27 | history.remove(letter) 28 | longest_palindrome += 2 29 | else: 30 | history.add(letter) 31 | if history != set(): 32 | longest_palindrome += 1 33 | return longest_palindrome -------------------------------------------------------------------------------- /house-robber.py: -------------------------------------------------------------------------------- 1 | # class Solution: 2 | # def rob(self, nums): 3 | # memo = {} 4 | # def rob_one_house(houses, amount): 5 | # max_amount = amount 6 | # tuple_houses = tuple(houses) 7 | # if len(houses) == 1: 8 | # return amount + houses[0] 9 | # if len(houses) == 0: 10 | # return amount 11 | # if tuple_houses in memo: 12 | # return memo[tuple_houses] 13 | # for house_index in range(len(houses)): 14 | # houses_without_adjacents = houses.copy() 15 | # if house_index != (len(houses) - 1): 16 | # houses_without_adjacents.pop(house_index + 1) 17 | # houses_without_adjacents.pop(house_index) 18 | # if house_index != 0: 19 | # houses_without_adjacents.pop(house_index - 1) 20 | # max_amount = max(rob_one_house(houses_without_adjacents, amount + houses[house_index]), max_amount) 21 | # memo[tuple_houses] = max_amount 22 | # return max_amount 23 | # return rob_one_house(nums, 0) 24 | 25 | class Solution: 26 | def rob(self, nums): 27 | memo = dict() 28 | def dp(i): 29 | if i >= len(nums): 30 | return 0 31 | if i in memo: 32 | return memo[i] 33 | 34 | robbed_amount = nums[i] + dp(i + 2) 35 | skipped_amount = dp(i + 1) 36 | 37 | max_amount = max(robbed_amount, skipped_amount) 38 | memo[i] = max_amount 39 | 40 | return max_amount 41 | return dp(0) 42 | 43 | 44 | print(Solution().rob([2,7,9,3,1])) -------------------------------------------------------------------------------- /network-delay-time.py: -------------------------------------------------------------------------------- 1 | from collections import deque, defaultdict 2 | from heapq import heappop, heappush 3 | from typing import List 4 | 5 | 6 | class Solution: 7 | def networkDelayTime(self, times: List[List[int]], n: int, k: int) -> int: 8 | adjacency = defaultdict(list) 9 | closest = {} 10 | 11 | for source, target, w in times: 12 | adjacency[source].append((target, w)) 13 | 14 | min_heap = [(0, k)] 15 | while min_heap: 16 | current_w, source = heappop(min_heap) 17 | 18 | if source in closest: 19 | continue 20 | 21 | closest[source] = current_w 22 | 23 | if len(closest) == n: 24 | break 25 | 26 | for target, w in adjacency[source]: 27 | if target not in closest: 28 | heappush(min_heap, (current_w + w, target)) 29 | 30 | if len(closest) != n: 31 | return -1 32 | else: 33 | return max(closest.values()) 34 | 35 | 36 | print( 37 | Solution().networkDelayTime( 38 | times=[ 39 | [4, 2, 76], 40 | [1, 3, 79], 41 | [3, 1, 81], 42 | [4, 3, 30], 43 | [2, 1, 47], 44 | [1, 5, 61], 45 | [1, 4, 99], 46 | [3, 4, 68], 47 | [3, 5, 46], 48 | [4, 1, 6], 49 | [5, 4, 7], 50 | [5, 3, 44], 51 | [4, 5, 19], 52 | [2, 3, 13], 53 | [3, 2, 18], 54 | [1, 2, 0], 55 | [5, 1, 25], 56 | [2, 5, 58], 57 | [2, 4, 77], 58 | [5, 2, 74], 59 | ], 60 | n=5, 61 | k=3, 62 | ) 63 | ) 64 | -------------------------------------------------------------------------------- /word-search.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from collections import deque, defaultdict 3 | 4 | 5 | class Solution: 6 | def exist(self, board: List[List[str]], word: str) -> bool: 7 | total_rows, total_cols = len(board), len(board[0]) 8 | 9 | def search(row_index, col_index, char_index): 10 | if char_index == len(word): 11 | return True 12 | 13 | if ( 14 | row_index < 0 15 | or row_index >= total_rows 16 | or col_index < 0 17 | or col_index >= total_cols 18 | or board[row_index][col_index] != word[char_index] 19 | ): 20 | return False 21 | 22 | saved_char = word[char_index] 23 | board[row_index][col_index] = "#" 24 | 25 | result = ( 26 | search(row_index + 1, col_index, char_index + 1) 27 | or search(row_index - 1, col_index, char_index + 1) 28 | or search(row_index, col_index + 1, char_index + 1) 29 | or search(row_index, col_index - 1, char_index + 1) 30 | ) 31 | board[row_index][col_index] = saved_char 32 | return result 33 | 34 | for row_index in range(total_rows): 35 | for col_index in range(total_cols): 36 | if board[row_index][col_index] == word[0]: 37 | if search(row_index, col_index, 0): 38 | return True 39 | return False 40 | 41 | 42 | print( 43 | Solution().exist( 44 | board=[ 45 | ["A", "A", "A", "A", "A", "A"], 46 | ["A", "A", "A", "B", "A", "A"], 47 | ["A", "A", "A", "A", "A", "A"], 48 | ["A", "A", "A", "A", "A", "A"], 49 | ["A", "A", "A", "A", "A", "A"], 50 | ["A", "A", "A", "A", "A", "A"], 51 | ], 52 | word="AB", 53 | ) 54 | ) 55 | -------------------------------------------------------------------------------- /divar/3.py: -------------------------------------------------------------------------------- 1 | class Desk: 2 | def __init__(self, floor_number, desk_number): 3 | self.id = f"{floor_number}-{desk_number}" 4 | self.floor_number = floor_number 5 | self.desk_number = desk_number 6 | self.assigned_to = None 7 | self.end_time = 0 8 | 9 | def is_available(self, time): 10 | if self.assigned_to is None: 11 | return True 12 | 13 | return self.end_time <= time 14 | 15 | def assign(self, time, duration, assigned_to): 16 | self.assigned_to = assigned_to 17 | self.end_time = time + duration 18 | 19 | def __str__(self): 20 | return self.id 21 | 22 | 23 | class Floor: 24 | def __init__(self, floor_number, desks_count): 25 | self.floor_number = floor_number 26 | self.desks = [ 27 | Desk(floor_number, desk_number) for desk_number in range(1, desks_count + 1) 28 | ] 29 | 30 | def get_available_desk(self, time): 31 | for desk in self.desks: 32 | if desk.is_available(time): 33 | return desk 34 | 35 | return None 36 | 37 | def __str__(self): 38 | return f"Floor {self.floor_number}" 39 | 40 | 41 | class WorkingSpace: 42 | def __init__(self, floor_desks_count): 43 | self.floors = [ 44 | Floor(floor_number, floor_desks_count[floor_number]) 45 | for floor_number in floor_desks_count 46 | ] 47 | 48 | def request_desk(self, username, timestap, duration): 49 | for floor in self.floors: 50 | available_desk = floor.get_available_desk(timestap) 51 | if available_desk: 52 | available_desk.assign(timestap, duration, username) 53 | return f"{username} got desk {available_desk}" 54 | return "no desk available" 55 | 56 | 57 | floors_count = int(input()) 58 | floor_desks_count = dict() 59 | for floor_number in range(1, floors_count + 1): 60 | desks_count = int(input()) 61 | floor_desks_count[floor_number] = desks_count 62 | 63 | working_space = WorkingSpace(floor_desks_count) 64 | 65 | while True: 66 | command = input() 67 | if command == "end": 68 | break 69 | 70 | timestamp, action, username, duration = command.split(" ") 71 | timestamp = int(timestamp) 72 | duration = int(duration) 73 | 74 | if action == "request_desk": 75 | result = working_space.request_desk(username, timestamp, duration) 76 | print(result) 77 | -------------------------------------------------------------------------------- /divar/4.py: -------------------------------------------------------------------------------- 1 | class Desk: 2 | def __init__(self, floor_number, desk_number): 3 | self.id = f"{floor_number}-{desk_number}" 4 | self.floor_number = floor_number 5 | self.desk_number = desk_number 6 | self.assigned_to = None 7 | self.end_time = 0 8 | 9 | def is_available(self, time): 10 | if self.assigned_to is None: 11 | return True 12 | 13 | return self.end_time <= time 14 | 15 | def assign(self, time, duration, assigned_to): 16 | self.assigned_to = assigned_to 17 | self.end_time = time + duration 18 | 19 | def __str__(self): 20 | return self.id 21 | 22 | 23 | class Floor: 24 | def __init__(self, floor_number, desks_count, floor_type): 25 | self.floor_number = floor_number 26 | self.desks = [ 27 | Desk(floor_number, desk_number) for desk_number in range(1, desks_count + 1) 28 | ] 29 | self.floor_type = floor_type 30 | 31 | def get_available_desk(self, time): 32 | for desk in self.desks: 33 | if desk.is_available(time): 34 | return desk 35 | 36 | return None 37 | 38 | def __str__(self): 39 | return f"Floor {self.floor_number}" 40 | 41 | 42 | class WorkingSpace: 43 | def __init__(self, floor_desks_count, special_floor_fee): 44 | self.floors = [ 45 | Floor( 46 | floor_number=floor_number, 47 | desks_count=floor_desks_count[floor_number]["count"], 48 | floor_type=floor_desks_count[floor_number]["type"], 49 | ) 50 | for floor_number in floor_desks_count 51 | ] 52 | self.special_floor_fee = special_floor_fee 53 | 54 | def request_desk(self, username, timestap, duration, floor_type): 55 | for floor in self.floors: 56 | if floor.floor_type != floor_type: 57 | continue 58 | available_desk = floor.get_available_desk(timestap) 59 | if available_desk: 60 | available_desk.assign(timestap, duration, username) 61 | if floor.floor_type == "special": 62 | return f"{username} got desk {available_desk} for {self.special_floor_fee}" 63 | return f"{username} got desk {available_desk}" 64 | return "no desk available" 65 | 66 | 67 | floors_count, special_floor_fee = input().split(" ") 68 | floors_count = int(floors_count) 69 | floor_desks_count = dict() 70 | for floor_number in range(1, floors_count + 1): 71 | desks_count, floor_type = input().split() 72 | desks_count = int(desks_count) 73 | floor_desks_count[floor_number] = {"type": floor_type, "count": desks_count} 74 | 75 | working_space = WorkingSpace(floor_desks_count, special_floor_fee) 76 | 77 | while True: 78 | command = input() 79 | if command == "end": 80 | break 81 | 82 | timestamp, action, username, floor_type, duration = command.split(" ") 83 | timestamp = int(timestamp) 84 | duration = int(duration) 85 | 86 | if action == "request_desk": 87 | result = working_space.request_desk(username, timestamp, duration, floor_type) 88 | print(result) 89 | -------------------------------------------------------------------------------- /divar/5.py: -------------------------------------------------------------------------------- 1 | class Reservation: 2 | def __init__(self, username, start_time, duration): 3 | self.username = username 4 | self.start_time = start_time 5 | self.end_time = start_time + duration 6 | 7 | 8 | class Desk: 9 | def __init__(self, floor_number, desk_number): 10 | self.id = f"{floor_number}-{desk_number}" 11 | self.floor_number = floor_number 12 | self.desk_number = desk_number 13 | self.reservations = [] 14 | 15 | def is_available(self, from_time, duration): 16 | end_time = from_time + duration 17 | for reservation in self.reservations: 18 | if not ( 19 | end_time <= reservation.start_time or from_time >= reservation.end_time 20 | ): 21 | return False 22 | return True 23 | 24 | def assign(self, time, duration, username): 25 | new_reservation = Reservation(username, time, duration) 26 | self.reservations.append(new_reservation) 27 | 28 | def __str__(self): 29 | return self.id 30 | 31 | 32 | class Floor: 33 | def __init__(self, floor_number, desks_count, floor_type): 34 | self.floor_number = floor_number 35 | self.desks = [ 36 | Desk(floor_number, desk_number) for desk_number in range(1, desks_count + 1) 37 | ] 38 | self.floor_type = floor_type 39 | 40 | def get_available_desk(self, from_time, duration): 41 | for desk in self.desks: 42 | if desk.is_available(from_time, duration): 43 | return desk 44 | 45 | return None 46 | 47 | def __str__(self): 48 | return f"Floor {self.floor_number}" 49 | 50 | 51 | class WorkingSpace: 52 | def __init__(self, floor_desks_count, special_floor_fee): 53 | self.floors = [ 54 | Floor( 55 | floor_number=floor_number, 56 | desks_count=floor_desks_count[floor_number]["count"], 57 | floor_type=floor_desks_count[floor_number]["type"], 58 | ) 59 | for floor_number in floor_desks_count 60 | ] 61 | self.special_floor_fee = special_floor_fee 62 | 63 | def request_desk(self, username, timestap, duration, floor_type): 64 | for floor in self.floors: 65 | if floor.floor_type != floor_type: 66 | continue 67 | available_desk = floor.get_available_desk(timestap, duration) 68 | if available_desk: 69 | available_desk.assign(timestap, duration, username) 70 | if floor.floor_type == "special": 71 | return f"{username} got desk {available_desk} for {self.special_floor_fee}" 72 | return f"{username} got desk {available_desk}" 73 | return "no desk available" 74 | 75 | def reserve_desk(self, username, timestamp, from_time, duration): 76 | for floor in self.floors: 77 | if floor.floor_type != "special": 78 | continue 79 | available_desk = floor.get_available_desk(from_time, duration) 80 | if available_desk: 81 | available_desk.assign(from_time, duration, username) 82 | return f"{username} reserved desk {available_desk} for {self.special_floor_fee}" 83 | return "no desk available" 84 | 85 | 86 | floors_count, special_floor_fee = input().split(" ") 87 | floors_count = int(floors_count) 88 | floor_desks_count = dict() 89 | for floor_number in range(1, floors_count + 1): 90 | desks_count, floor_type = input().split() 91 | desks_count = int(desks_count) 92 | floor_desks_count[floor_number] = {"type": floor_type, "count": desks_count} 93 | 94 | working_space = WorkingSpace(floor_desks_count, special_floor_fee) 95 | 96 | while True: 97 | command = input() 98 | if command == "end": 99 | break 100 | 101 | parts = command.split(" ") 102 | timestamp = int(parts[0]) 103 | action = parts[1] 104 | username = parts[2] 105 | 106 | if action == "request_desk": 107 | floor_type = parts[3] 108 | duration = int(parts[4]) 109 | result = working_space.request_desk(username, timestamp, duration, floor_type) 110 | print(result) 111 | 112 | elif action == "reserve_desk": 113 | from_time = int(parts[3]) 114 | duration = int(parts[4]) 115 | result = working_space.reserve_desk(username, timestamp, from_time, duration) 116 | print(result) 117 | -------------------------------------------------------------------------------- /low-level-design/elevator.py: -------------------------------------------------------------------------------- 1 | 2 | from enum import Enum 3 | 4 | class Direction(Enum): 5 | DOWN = -1 6 | IDLE = 0 7 | UP = 1 8 | 9 | class Request: 10 | def __init__(self, pick_up_floor): 11 | self.pick_up_floor = pick_up_floor 12 | 13 | class ElevatorDisplay: 14 | @staticmethod 15 | def open_doors(floor): 16 | print(f"Opening doors at floor: {floor}") 17 | def close_doors(floor): 18 | print(f"Closing doors at floor: {floor}") 19 | def enter_destination(floor): 20 | print(f"Level {floor}: Get in passengers") 21 | destination = int(input("Please enter your destination: ")) 22 | return destination 23 | 24 | class Elevator: 25 | def __init__(self, id, current_floor = 0): 26 | self.id = id 27 | self.pick_up_floors = list() 28 | self.destination_floors = list() 29 | self.direction = Direction.IDLE 30 | self.current_floor = current_floor 31 | 32 | def step(self): 33 | if self.destination_floors == list() and self.pick_up_floors == list(): 34 | self.direction = Direction.IDLE 35 | return 36 | 37 | if self.current_floor in self.destination_floors + self.pick_up_floors: 38 | ElevatorDisplay.open_doors(self.current_floor) 39 | while self.current_floor in self.destination_floors: 40 | self.destination_floors.remove(self.current_floor) 41 | 42 | if self.current_floor in self.pick_up_floors: 43 | self.new_destination(ElevatorDisplay.enter_destination(self.current_floor)) 44 | while self.current_floor in self.pick_up_floors: 45 | self.pick_up_floors.remove(self.current_floor) 46 | ElevatorDisplay.close_doors(self.current_floor) 47 | return 48 | 49 | if self.direction != Direction.DOWN: 50 | if self.get_highest_floor_to_go() > self.current_floor: 51 | self.direction = Direction.UP 52 | self.current_floor += 1 53 | else: 54 | self.direction == Direction.DOWN 55 | self.current_floor -= 1 56 | return 57 | 58 | if self.direction != Direction.UP: 59 | if self.get_lowest_floor_to_go() < self.current_floor: 60 | self.direction = Direction.DOWN 61 | self.current_floor -= 1 62 | else: 63 | self.direction == Direction.UP 64 | self.current_floor += 1 65 | return 66 | 67 | def new_pick_up(self, floor): 68 | self.pick_up_floors.append(floor) 69 | self.pick_up_floors.sort() 70 | 71 | def new_destination(self, floor): 72 | self.destination_floors.append(floor) 73 | self.destination_floors.sort() 74 | 75 | def get_lowest_floor_to_go(self): 76 | go_to_floors = list() 77 | if self.destination_floors: 78 | go_to_floors.append(self.destination_floors[0]) 79 | if self.pick_up_floors: 80 | go_to_floors.append(self.pick_up_floors[0]) 81 | return min(go_to_floors) 82 | 83 | 84 | def get_highest_floor_to_go(self): 85 | go_to_floors = list() 86 | if self.destination_floors: 87 | go_to_floors.append(self.destination_floors[-1]) 88 | if self.pick_up_floors: 89 | go_to_floors.append(self.pick_up_floors[-1]) 90 | return max(go_to_floors) 91 | 92 | def __str__(self): 93 | return f"Elevator {self.id} At {self.current_floor}, Direction: {self.direction}" 94 | 95 | class ElevatorManger: 96 | def __init__(self, elevators): 97 | self.elevators = elevators 98 | 99 | def find_elevator_score(self, elevator: Elevator, request: Request): 100 | if elevator.current_floor == request.pick_up_floor: 101 | return float("inf") 102 | if elevator.current_floor > request.pick_up_floor: 103 | if elevator.direction != Direction.UP: 104 | return -1 * (elevator.current_floor - request.pick_up_floor) 105 | else: 106 | return -1 * ((max(elevator.destination_floors[-1], elevator.pick_up_floors[-1]) - elevator.current_floor) + (elevator.current_floor - request.pick_up_floor)) 107 | else: 108 | if elevator.direction != Direction.DOWN: 109 | return -1 * (request.pick_up_floor - elevator.current_floor) 110 | else: 111 | return -1 * ((elevator.current_floor - min(elevator.destination_floors[0], elevator.pick_up_floors[0])) + (request.pick_up_floor - elevator.current_floor)) 112 | 113 | def find_best_elevator(self, request: Request): 114 | best_score = float("-inf") 115 | best_elevator = None 116 | for elevator in self.elevators: 117 | current_score = self.find_elevator_score(elevator, request) 118 | print(current_score) 119 | if best_score < current_score: 120 | best_score = current_score 121 | best_elevator = elevator 122 | return best_elevator 123 | 124 | def request_elevator(self, request: Request): 125 | chosen_elevator = self.find_best_elevator(request) 126 | chosen_elevator.new_pick_up(request.pick_up_floor) 127 | 128 | def process(self, steps): 129 | for i in range(steps): 130 | print("-" * 56) 131 | for elevator in elevators: 132 | elevator.step() 133 | print(elevator) 134 | 135 | elevators = [ 136 | Elevator("A", 0), 137 | Elevator("B", 0), 138 | ] 139 | manager = ElevatorManger(elevators) 140 | manager.process(2) 141 | manager.request_elevator(Request(5)) 142 | manager.process(2) 143 | manager.request_elevator(Request(4)) 144 | manager.process(10) 145 | 146 | -------------------------------------------------------------------------------- /word-ladder-ii.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from collections import deque, defaultdict 3 | 4 | 5 | class Solution: 6 | def findLadders(self, beginWord: str, endWord: str, wordList: List[str]): 7 | if endWord not in wordList: 8 | return [] 9 | 10 | wordList = set(wordList) 11 | patterns = defaultdict(list) 12 | for word in wordList: 13 | for i in range(len(word)): 14 | pattern = word[:i] + "*" + word[i + 1 :] 15 | patterns[pattern].append(word) 16 | 17 | queue = deque([(beginWord, 0)]) 18 | visited = {beginWord: 0} 19 | backtracking = defaultdict(list) 20 | 21 | while queue: 22 | for _ in range(len(queue)): 23 | word, level = queue.popleft() 24 | 25 | if word == endWord: 26 | return self.find_ways(backtracking, beginWord, endWord) 27 | 28 | for i in range(len(word)): 29 | pattern = word[:i] + "*" + word[i + 1 :] 30 | for new_word in patterns[pattern]: 31 | if new_word not in visited or visited[new_word] == level + 1: 32 | backtracking[new_word].append(word) 33 | if new_word not in visited: 34 | visited[new_word] = level + 1 35 | queue.append((new_word, level + 1)) 36 | return [] 37 | 38 | def find_ways(self, backtracking, begin_word, end_word): 39 | results = [] 40 | 41 | def find_way(path): 42 | target = path[-1] 43 | if target == begin_word: 44 | results.append(path[::-1]) 45 | else: 46 | for next_word in backtracking[target]: 47 | find_way(path + [next_word]) 48 | 49 | find_way([end_word]) 50 | 51 | return results 52 | 53 | 54 | print( 55 | Solution().findLadders( 56 | "aaaaa", 57 | "ggggg", 58 | [ 59 | "aaaaa", 60 | "caaaa", 61 | "cbaaa", 62 | "daaaa", 63 | "dbaaa", 64 | "eaaaa", 65 | "ebaaa", 66 | "faaaa", 67 | "fbaaa", 68 | "gaaaa", 69 | "gbaaa", 70 | "haaaa", 71 | "hbaaa", 72 | "iaaaa", 73 | "ibaaa", 74 | "jaaaa", 75 | "jbaaa", 76 | "kaaaa", 77 | "kbaaa", 78 | "laaaa", 79 | "lbaaa", 80 | "maaaa", 81 | "mbaaa", 82 | "naaaa", 83 | "nbaaa", 84 | "oaaaa", 85 | "obaaa", 86 | "paaaa", 87 | "pbaaa", 88 | "bbaaa", 89 | "bbcaa", 90 | "bbcba", 91 | "bbdaa", 92 | "bbdba", 93 | "bbeaa", 94 | "bbeba", 95 | "bbfaa", 96 | "bbfba", 97 | "bbgaa", 98 | "bbgba", 99 | "bbhaa", 100 | "bbhba", 101 | "bbiaa", 102 | "bbiba", 103 | "bbjaa", 104 | "bbjba", 105 | "bbkaa", 106 | "bbkba", 107 | "bblaa", 108 | "bblba", 109 | "bbmaa", 110 | "bbmba", 111 | "bbnaa", 112 | "bbnba", 113 | "bboaa", 114 | "bboba", 115 | "bbpaa", 116 | "bbpba", 117 | "bbbba", 118 | "abbba", 119 | "acbba", 120 | "dbbba", 121 | "dcbba", 122 | "ebbba", 123 | "ecbba", 124 | "fbbba", 125 | "fcbba", 126 | "gbbba", 127 | "gcbba", 128 | "hbbba", 129 | "hcbba", 130 | "ibbba", 131 | "icbba", 132 | "jbbba", 133 | "jcbba", 134 | "kbbba", 135 | "kcbba", 136 | "lbbba", 137 | "lcbba", 138 | "mbbba", 139 | "mcbba", 140 | "nbbba", 141 | "ncbba", 142 | "obbba", 143 | "ocbba", 144 | "pbbba", 145 | "pcbba", 146 | "ccbba", 147 | "ccaba", 148 | "ccaca", 149 | "ccdba", 150 | "ccdca", 151 | "cceba", 152 | "cceca", 153 | "ccfba", 154 | "ccfca", 155 | "ccgba", 156 | "ccgca", 157 | "cchba", 158 | "cchca", 159 | "cciba", 160 | "ccica", 161 | "ccjba", 162 | "ccjca", 163 | "cckba", 164 | "cckca", 165 | "cclba", 166 | "cclca", 167 | "ccmba", 168 | "ccmca", 169 | "ccnba", 170 | "ccnca", 171 | "ccoba", 172 | "ccoca", 173 | "ccpba", 174 | "ccpca", 175 | "cccca", 176 | "accca", 177 | "adcca", 178 | "bccca", 179 | "bdcca", 180 | "eccca", 181 | "edcca", 182 | "fccca", 183 | "fdcca", 184 | "gccca", 185 | "gdcca", 186 | "hccca", 187 | "hdcca", 188 | "iccca", 189 | "idcca", 190 | "jccca", 191 | "jdcca", 192 | "kccca", 193 | "kdcca", 194 | "lccca", 195 | "ldcca", 196 | "mccca", 197 | "mdcca", 198 | "nccca", 199 | "ndcca", 200 | "occca", 201 | "odcca", 202 | "pccca", 203 | "pdcca", 204 | "ddcca", 205 | "ddaca", 206 | "ddada", 207 | "ddbca", 208 | "ddbda", 209 | "ddeca", 210 | "ddeda", 211 | "ddfca", 212 | "ddfda", 213 | "ddgca", 214 | "ddgda", 215 | "ddhca", 216 | "ddhda", 217 | "ddica", 218 | "ddida", 219 | "ddjca", 220 | "ddjda", 221 | "ddkca", 222 | "ddkda", 223 | "ddlca", 224 | "ddlda", 225 | "ddmca", 226 | "ddmda", 227 | "ddnca", 228 | "ddnda", 229 | "ddoca", 230 | "ddoda", 231 | "ddpca", 232 | "ddpda", 233 | "dddda", 234 | "addda", 235 | "aedda", 236 | "bddda", 237 | "bedda", 238 | "cddda", 239 | "cedda", 240 | "fddda", 241 | "fedda", 242 | "gddda", 243 | "gedda", 244 | "hddda", 245 | "hedda", 246 | "iddda", 247 | "iedda", 248 | "jddda", 249 | "jedda", 250 | "kddda", 251 | "kedda", 252 | "lddda", 253 | "ledda", 254 | "mddda", 255 | "medda", 256 | "nddda", 257 | "nedda", 258 | "oddda", 259 | "oedda", 260 | "pddda", 261 | "pedda", 262 | "eedda", 263 | "eeada", 264 | "eeaea", 265 | "eebda", 266 | "eebea", 267 | "eecda", 268 | "eecea", 269 | "eefda", 270 | "eefea", 271 | "eegda", 272 | "eegea", 273 | "eehda", 274 | "eehea", 275 | "eeida", 276 | "eeiea", 277 | "eejda", 278 | "eejea", 279 | "eekda", 280 | "eekea", 281 | "eelda", 282 | "eelea", 283 | "eemda", 284 | "eemea", 285 | "eenda", 286 | "eenea", 287 | "eeoda", 288 | "eeoea", 289 | "eepda", 290 | "eepea", 291 | "eeeea", 292 | "ggggg", 293 | "agggg", 294 | "ahggg", 295 | "bgggg", 296 | "bhggg", 297 | "cgggg", 298 | "chggg", 299 | "dgggg", 300 | "dhggg", 301 | "egggg", 302 | "ehggg", 303 | "fgggg", 304 | "fhggg", 305 | "igggg", 306 | "ihggg", 307 | "jgggg", 308 | "jhggg", 309 | "kgggg", 310 | "khggg", 311 | "lgggg", 312 | "lhggg", 313 | "mgggg", 314 | "mhggg", 315 | "ngggg", 316 | "nhggg", 317 | "ogggg", 318 | "ohggg", 319 | "pgggg", 320 | "phggg", 321 | "hhggg", 322 | "hhagg", 323 | "hhahg", 324 | "hhbgg", 325 | "hhbhg", 326 | "hhcgg", 327 | "hhchg", 328 | "hhdgg", 329 | "hhdhg", 330 | "hhegg", 331 | "hhehg", 332 | "hhfgg", 333 | "hhfhg", 334 | "hhigg", 335 | "hhihg", 336 | "hhjgg", 337 | "hhjhg", 338 | "hhkgg", 339 | "hhkhg", 340 | "hhlgg", 341 | "hhlhg", 342 | "hhmgg", 343 | "hhmhg", 344 | "hhngg", 345 | "hhnhg", 346 | "hhogg", 347 | "hhohg", 348 | "hhpgg", 349 | "hhphg", 350 | "hhhhg", 351 | "ahhhg", 352 | "aihhg", 353 | "bhhhg", 354 | "bihhg", 355 | "chhhg", 356 | "cihhg", 357 | "dhhhg", 358 | "dihhg", 359 | "ehhhg", 360 | "eihhg", 361 | "fhhhg", 362 | "fihhg", 363 | "ghhhg", 364 | "gihhg", 365 | "jhhhg", 366 | "jihhg", 367 | "khhhg", 368 | "kihhg", 369 | "lhhhg", 370 | "lihhg", 371 | "mhhhg", 372 | "mihhg", 373 | "nhhhg", 374 | "nihhg", 375 | "ohhhg", 376 | "oihhg", 377 | "phhhg", 378 | "pihhg", 379 | "iihhg", 380 | "iiahg", 381 | "iiaig", 382 | "iibhg", 383 | "iibig", 384 | "iichg", 385 | "iicig", 386 | "iidhg", 387 | "iidig", 388 | "iiehg", 389 | "iieig", 390 | "iifhg", 391 | "iifig", 392 | "iighg", 393 | "iigig", 394 | "iijhg", 395 | "iijig", 396 | "iikhg", 397 | "iikig", 398 | "iilhg", 399 | "iilig", 400 | "iimhg", 401 | "iimig", 402 | "iinhg", 403 | "iinig", 404 | "iiohg", 405 | "iioig", 406 | "iiphg", 407 | "iipig", 408 | "iiiig", 409 | "aiiig", 410 | "ajiig", 411 | "biiig", 412 | "bjiig", 413 | "ciiig", 414 | "cjiig", 415 | "diiig", 416 | "djiig", 417 | "eiiig", 418 | "ejiig", 419 | "fiiig", 420 | "fjiig", 421 | "giiig", 422 | "gjiig", 423 | "hiiig", 424 | "hjiig", 425 | "kiiig", 426 | "kjiig", 427 | "liiig", 428 | "ljiig", 429 | "miiig", 430 | "mjiig", 431 | "niiig", 432 | "njiig", 433 | "oiiig", 434 | "ojiig", 435 | "piiig", 436 | "pjiig", 437 | "jjiig", 438 | "jjaig", 439 | "jjajg", 440 | "jjbig", 441 | "jjbjg", 442 | "jjcig", 443 | "jjcjg", 444 | "jjdig", 445 | "jjdjg", 446 | "jjeig", 447 | "jjejg", 448 | "jjfig", 449 | "jjfjg", 450 | "jjgig", 451 | "jjgjg", 452 | "jjhig", 453 | "jjhjg", 454 | "jjkig", 455 | "jjkjg", 456 | "jjlig", 457 | "jjljg", 458 | "jjmig", 459 | "jjmjg", 460 | "jjnig", 461 | "jjnjg", 462 | "jjoig", 463 | "jjojg", 464 | "jjpig", 465 | "jjpjg", 466 | "jjjjg", 467 | "ajjjg", 468 | "akjjg", 469 | "bjjjg", 470 | "bkjjg", 471 | "cjjjg", 472 | "ckjjg", 473 | "djjjg", 474 | "dkjjg", 475 | "ejjjg", 476 | "ekjjg", 477 | "fjjjg", 478 | "fkjjg", 479 | "gjjjg", 480 | "gkjjg", 481 | "hjjjg", 482 | "hkjjg", 483 | "ijjjg", 484 | "ikjjg", 485 | "ljjjg", 486 | "lkjjg", 487 | "mjjjg", 488 | "mkjjg", 489 | "njjjg", 490 | "nkjjg", 491 | "ojjjg", 492 | "okjjg", 493 | "pjjjg", 494 | "pkjjg", 495 | "kkjjg", 496 | "kkajg", 497 | "kkakg", 498 | "kkbjg", 499 | "kkbkg", 500 | "kkcjg", 501 | "kkckg", 502 | "kkdjg", 503 | "kkdkg", 504 | "kkejg", 505 | "kkekg", 506 | "kkfjg", 507 | "kkfkg", 508 | "kkgjg", 509 | "kkgkg", 510 | "kkhjg", 511 | "kkhkg", 512 | "kkijg", 513 | "kkikg", 514 | "kkljg", 515 | "kklkg", 516 | "kkmjg", 517 | "kkmkg", 518 | "kknjg", 519 | "kknkg", 520 | "kkojg", 521 | "kkokg", 522 | "kkpjg", 523 | "kkpkg", 524 | "kkkkg", 525 | "ggggx", 526 | "gggxx", 527 | "ggxxx", 528 | "gxxxx", 529 | "xxxxx", 530 | "xxxxy", 531 | "xxxyy", 532 | "xxyyy", 533 | "xyyyy", 534 | "yyyyy", 535 | "yyyyw", 536 | "yyyww", 537 | "yywww", 538 | "ywwww", 539 | "wwwww", 540 | "wwvww", 541 | "wvvww", 542 | "vvvww", 543 | "vvvwz", 544 | "avvwz", 545 | "aavwz", 546 | "aaawz", 547 | "aaaaz", 548 | ], 549 | ) 550 | ) 551 | --------------------------------------------------------------------------------