Add coding exercises for Facebook interviews
Add attempts at solving coding problems to Briefcase.
This commit is contained in:
		
							parent
							
								
									d2d772e43e
								
							
						
					
					
						commit
						aa66d9b83d
					
				
					 66 changed files with 2994 additions and 0 deletions
				
			
		
							
								
								
									
										71
									
								
								scratch/facebook/anglocize-int.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								scratch/facebook/anglocize-int.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | ||||||
|  | THOUSAND = int(1e3) | ||||||
|  | MILLION = int(1e6) | ||||||
|  | BILLION = int(1e9) | ||||||
|  | TRILLION = int(1e12) | ||||||
|  | 
 | ||||||
|  | facts = { | ||||||
|  |     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: "Thirteen", | ||||||
|  |     14: "Fourteen", | ||||||
|  |     15: "Fifteen", | ||||||
|  |     16: "Sixteen", | ||||||
|  |     17: "Seventeen", | ||||||
|  |     18: "Eighteen", | ||||||
|  |     19: "Nineteen", | ||||||
|  |     20: "Twenty", | ||||||
|  |     30: "Thirty", | ||||||
|  |     40: "Forty", | ||||||
|  |     50: "Fifty", | ||||||
|  |     60: "Sixty", | ||||||
|  |     70: "Seventy", | ||||||
|  |     80: "Eighty", | ||||||
|  |     90: "Ninety", | ||||||
|  |     100: "Hundred", | ||||||
|  |     THOUSAND: "Thousand", | ||||||
|  |     MILLION: "Million", | ||||||
|  |     BILLION: "Billion", | ||||||
|  |     TRILLION: "Trillion", | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | def anglocize(x): | ||||||
|  |     # ones | ||||||
|  |     if x >= 0 and x < 10: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     # tens | ||||||
|  |     elif x < 100: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     # hundreds | ||||||
|  |     elif x < THOUSAND: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     # thousands | ||||||
|  |     elif x < MILLION: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     # millions | ||||||
|  |     elif x < BILLION: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     # billion | ||||||
|  |     elif x < TRILLION: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  |     # trillion | ||||||
|  |     else: | ||||||
|  |         pass | ||||||
|  | 
 | ||||||
|  | x = 1234 | ||||||
|  | assert anglocize(x) == "One Thousand, Two Hundred Thirty Four" | ||||||
							
								
								
									
										70
									
								
								scratch/facebook/balanced-binary-tree.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								scratch/facebook/balanced-binary-tree.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | ||||||
|  | from collections import deque | ||||||
|  | 
 | ||||||
|  | class Node(object): | ||||||
|  |     # __init__ :: T(A) | ||||||
|  |     def __init__(self, value=None, left=None, right=None): | ||||||
|  |         self.value = value | ||||||
|  |         self.left = left | ||||||
|  |         self.right = right | ||||||
|  | 
 | ||||||
|  |     # insert_left :: T(A) -> A -> T(A) | ||||||
|  |     def insert_left(self, value): | ||||||
|  |         self.left = Node(value) | ||||||
|  |         return self.left | ||||||
|  | 
 | ||||||
|  |     # insert_right :: T(A) -> A -> T(A) | ||||||
|  |     def insert_right(self, value): | ||||||
|  |         self.right = Node(value) | ||||||
|  |         return self.right | ||||||
|  | 
 | ||||||
|  |     # is_superbalanced :: T(A) -> Bool | ||||||
|  |     def is_superbalanced(self): | ||||||
|  |         xs = deque() | ||||||
|  |         min_depth, max_depth = float('inf'), float('-inf') | ||||||
|  |         xs.append((self, 0)) | ||||||
|  |         while xs: | ||||||
|  |             x, d = xs.popleft() | ||||||
|  |             # Only redefine the depths at leaf nodes | ||||||
|  |             if not x.left and not x.right: | ||||||
|  |                 min_depth, max_depth = min(min_depth, d), max(max_depth, d) | ||||||
|  |             if x.left: | ||||||
|  |                 xs.append((x.left, d + 1)) | ||||||
|  |             if x.right: | ||||||
|  |                 xs.append((x.right, d + 1)) | ||||||
|  |         return max_depth - min_depth <= 1 | ||||||
|  | 
 | ||||||
|  |     # __repr__ :: T(A) -> String | ||||||
|  |     def __repr__(self): | ||||||
|  |         result = '' | ||||||
|  |         xs = deque() | ||||||
|  |         xs.append((self, 0)) | ||||||
|  |         while xs: | ||||||
|  |             node, indent = xs.popleft() | ||||||
|  |             result += '{i}{x}\n'.format(i=' ' * indent, x=node.value) | ||||||
|  |             if node.left: | ||||||
|  |                 xs.append((node.left, indent + 2)) | ||||||
|  |             if node.right: | ||||||
|  |                 xs.append((node.right, indent + 2)) | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  | # from_array :: List(A) -> T(A) | ||||||
|  | def from_array(values): | ||||||
|  |     xs = deque() | ||||||
|  |     root = Node() | ||||||
|  |     xs.append(root) | ||||||
|  |     for value in values: | ||||||
|  |         node = xs.popleft() | ||||||
|  |         node.value = value | ||||||
|  |         node.left = Node() | ||||||
|  |         xs.append(node.left) | ||||||
|  |         node.right = Node() | ||||||
|  |         xs.append(node.right) | ||||||
|  |     return root | ||||||
|  | 
 | ||||||
|  | x = from_array([1, 1, 1, 1, 1, 1, 1]) | ||||||
|  | print(x) | ||||||
|  | print(x.is_superbalanced()) | ||||||
|  | 
 | ||||||
|  | x = Node(1, Node(2), Node(3)) | ||||||
|  | print(x) | ||||||
|  | print(x.is_superbalanced()) | ||||||
							
								
								
									
										112
									
								
								scratch/facebook/breakfast-generator.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								scratch/facebook/breakfast-generator.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | ||||||
|  | # After being inspired by... | ||||||
|  | # craftinginterpreters.com/representing-code.html | ||||||
|  | # ...I'm implementing the breakfast generator that the author describes | ||||||
|  | # therein. | ||||||
|  | 
 | ||||||
|  | import random | ||||||
|  | import string | ||||||
|  | 
 | ||||||
|  | # Breakfast | ||||||
|  | 
 | ||||||
|  | def breakfast(): | ||||||
|  |     fn = random.choice([ | ||||||
|  |         lambda: " ".join([protein(), "with", breakfast(), "on the side"]), | ||||||
|  |         lambda: protein(), | ||||||
|  |         lambda: bread(), | ||||||
|  |     ]) | ||||||
|  |     return fn() | ||||||
|  | 
 | ||||||
|  | def protein(): | ||||||
|  |     fn = random.choice([ | ||||||
|  |         lambda: " ".join([qualifier(), "crispy", "bacon"]), | ||||||
|  |         lambda: "sausage", | ||||||
|  |         lambda: " ".join([cooking_method(), "sausage"]), | ||||||
|  |     ]) | ||||||
|  |     return fn() | ||||||
|  | 
 | ||||||
|  | def qualifier(): | ||||||
|  |     fn = random.choice([ | ||||||
|  |         lambda: "really", | ||||||
|  |         lambda: "super", | ||||||
|  |         lambda: " ".join(["really", qualifier()]), | ||||||
|  |     ]) | ||||||
|  |     return fn() | ||||||
|  | 
 | ||||||
|  | def cooking_method(): | ||||||
|  |     return random.choice([ | ||||||
|  |         "scrambled", | ||||||
|  |         "poached", | ||||||
|  |         "fried", | ||||||
|  |     ]) | ||||||
|  | 
 | ||||||
|  | def bread(): | ||||||
|  |     return random.choice([ | ||||||
|  |         "toast", | ||||||
|  |         "biscuits", | ||||||
|  |         "English muffin", | ||||||
|  |     ]) | ||||||
|  | 
 | ||||||
|  | print(breakfast()) | ||||||
|  | 
 | ||||||
|  | # Expression Language | ||||||
|  | 
 | ||||||
|  | # Because Python is a strictly evaluated language any functions that are | ||||||
|  | # mutually recursive won't terminate and will overflow our stack. Therefore, any | ||||||
|  | # non-terminals expressed in an alternative are wrapped in lambdas as thunks. | ||||||
|  | 
 | ||||||
|  | def expression(): | ||||||
|  |     fn = random.choice([ | ||||||
|  |         lambda: literal(), | ||||||
|  |         lambda: binary(), | ||||||
|  |     ]) | ||||||
|  |     return fn() | ||||||
|  | 
 | ||||||
|  | def literal(): | ||||||
|  |     return str(random.randint(0, 100)) | ||||||
|  | 
 | ||||||
|  | def binary(): | ||||||
|  |     return " ".join([expression(), operator(), expression()]) | ||||||
|  | 
 | ||||||
|  | def operator(): | ||||||
|  |     return random.choice(["+", "*"]) | ||||||
|  | 
 | ||||||
|  | print(expression()) | ||||||
|  | 
 | ||||||
|  | # Lox | ||||||
|  | 
 | ||||||
|  | def lox_expression(): | ||||||
|  |     fn = random.choice([ | ||||||
|  |         lambda: lox_literal(), | ||||||
|  |         lambda: lox_unary(), | ||||||
|  |         lambda: lox_binary(), | ||||||
|  |         lambda: lox_grouping(), | ||||||
|  |     ]) | ||||||
|  |     return fn() | ||||||
|  | 
 | ||||||
|  | def lox_literal(): | ||||||
|  |     fn = random.choice([ | ||||||
|  |         lambda: str(random.randint(0, 100)), | ||||||
|  |         lambda: lox_string(), | ||||||
|  |         lambda: random.choice(["true", "false"]), | ||||||
|  |         lambda: "nil", | ||||||
|  |     ]) | ||||||
|  |     return fn() | ||||||
|  | 
 | ||||||
|  | def lox_string(): | ||||||
|  |     return "\"{}\"".format( | ||||||
|  |         "".join(random.choice(string.ascii_lowercase) | ||||||
|  |                 for _ in range(random.randint(0, 25)))) | ||||||
|  | 
 | ||||||
|  | def lox_grouping(): | ||||||
|  |     return "(" + lox_expression() + ")" | ||||||
|  | 
 | ||||||
|  | def lox_unary(): | ||||||
|  |     return random.choice(["-", "!"]) + lox_expression() | ||||||
|  | 
 | ||||||
|  | def lox_binary(): | ||||||
|  |     return lox_expression() + lox_operator() + lox_expression() | ||||||
|  | 
 | ||||||
|  | def lox_operator(): | ||||||
|  |     return random.choice(["==", "!=", "<", "<=", ">", ">=", "+", "-", "*", "/"]) | ||||||
|  | 
 | ||||||
|  | print(lox_expression()) | ||||||
							
								
								
									
										79
									
								
								scratch/facebook/bst-checker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								scratch/facebook/bst-checker.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,79 @@ | ||||||
|  | from collections import deque | ||||||
|  | 
 | ||||||
|  | class Node(object): | ||||||
|  |     def __init__(self, value, left=None, right=None): | ||||||
|  |         self.value = value | ||||||
|  |         self.left = left | ||||||
|  |         self.right = right | ||||||
|  | 
 | ||||||
|  |     def insert_left(self, value): | ||||||
|  |         self.left = Node(value) | ||||||
|  |         return self.left | ||||||
|  | 
 | ||||||
|  |     def insert_right(self, value): | ||||||
|  |         self.right = Node(value) | ||||||
|  |         return self.right | ||||||
|  | 
 | ||||||
|  |     def min(self): | ||||||
|  |         xs = deque() | ||||||
|  |         result = float('inf') | ||||||
|  |         xs.append(self) | ||||||
|  |         while xs: | ||||||
|  |             node = xs.popleft() | ||||||
|  |             result = min(result, node.value) | ||||||
|  |             if node.left: | ||||||
|  |                 xs.append(node.left) | ||||||
|  |             if node.right: | ||||||
|  |                 xs.append(node.right) | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  |     def max(self): | ||||||
|  |         xs = deque() | ||||||
|  |         result = float('-inf') | ||||||
|  |         xs.append(self) | ||||||
|  |         while xs: | ||||||
|  |             node = xs.popleft() | ||||||
|  |             result = max(result, node.value) | ||||||
|  |             if node.left: | ||||||
|  |                 xs.append(node.left) | ||||||
|  |             if node.right: | ||||||
|  |                 xs.append(node.right) | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  |     def is_bst(self): | ||||||
|  |         result = True | ||||||
|  |         if self.left: | ||||||
|  |             result = result and self.left.max() < self.value | ||||||
|  |         if self.right: | ||||||
|  |             result = result and self.right.min() > self.value | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | x = Node( | ||||||
|  |     50, | ||||||
|  |     Node( | ||||||
|  |         17, | ||||||
|  |         Node( | ||||||
|  |             12, | ||||||
|  |             Node(9), | ||||||
|  |             Node(14), | ||||||
|  |         ), | ||||||
|  |         Node( | ||||||
|  |             23, | ||||||
|  |             Node(19), | ||||||
|  |         ), | ||||||
|  |     ), | ||||||
|  |     Node( | ||||||
|  |         72, | ||||||
|  |         Node( | ||||||
|  |             54, | ||||||
|  |             None, | ||||||
|  |             Node(67) | ||||||
|  |         ), | ||||||
|  |         Node(76), | ||||||
|  |     ), | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | assert x.is_bst() | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										19
									
								
								scratch/facebook/cafe-order-checker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scratch/facebook/cafe-order-checker.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | def orders_are_sorted(take_out, dine_in, audit): | ||||||
|  |     if len(take_out) + len(dine_in) != len(audit): | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  |     i, j = 0, 0 | ||||||
|  |     for x in audit: | ||||||
|  |         if i < len(take_out) and take_out[i] == x: | ||||||
|  |             i += 1 | ||||||
|  |         elif j < len(dine_in) and dine_in[j] == x: | ||||||
|  |             j += 1 | ||||||
|  |         else: | ||||||
|  |             return False | ||||||
|  |     return True | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | assert orders_are_sorted([1,3,5], [2,4,6], [1,2,4,3,6,5]) | ||||||
|  | assert not orders_are_sorted([1,3,5], [2,4,6], [1,2,4,5,6,3]) | ||||||
|  | assert orders_are_sorted([], [2,4,6], [2,4,6]) | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										61
									
								
								scratch/facebook/cake_thief.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								scratch/facebook/cake_thief.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | from math import floor | ||||||
|  | 
 | ||||||
|  | def print_table(table): | ||||||
|  |     print('\n-- TABLE --') | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         x = '' | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             x += ' ' + str(table[row][col]) | ||||||
|  |         print(x) | ||||||
|  | 
 | ||||||
|  | def leftover(capacity, kg): | ||||||
|  |     n = floor(capacity / kg) | ||||||
|  |     return n, capacity - (n * kg) | ||||||
|  | 
 | ||||||
|  | def init_table(num_rows, num_cols): | ||||||
|  |     table = [] | ||||||
|  |     for _ in range(num_rows): | ||||||
|  |         row = [] | ||||||
|  |         for _ in range(num_cols): | ||||||
|  |             row.append(0) | ||||||
|  |         table.append(row) | ||||||
|  |     return table | ||||||
|  | 
 | ||||||
|  | def get(table, row, col): | ||||||
|  |     if row < 0 or col < 0: | ||||||
|  |         return 0 | ||||||
|  |     return table[row][col] | ||||||
|  | 
 | ||||||
|  | def max_haul(items, capacity): | ||||||
|  |     table = init_table(len(items), capacity) | ||||||
|  | 
 | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             curr_capacity = col + 1 | ||||||
|  |             kg, val = items[row] | ||||||
|  |             # A | ||||||
|  |             a = get(table, row - 1, col) | ||||||
|  |             # B | ||||||
|  |             n, lo = leftover(curr_capacity, kg) | ||||||
|  |             b = (val * n) + get(table, row - 1, lo - 1) | ||||||
|  |             # commit | ||||||
|  |             if kg > curr_capacity: | ||||||
|  |                 table[row][col] = a | ||||||
|  |             else: | ||||||
|  |                 print(n, lo) | ||||||
|  |                 table[row][col] = max([a, b]) | ||||||
|  |             print_table(table) | ||||||
|  |     return table[-1][-1] | ||||||
|  | 
 | ||||||
|  | # There are multiple variants of this problem: | ||||||
|  | #   1. We're allowed to take multiple of each item. | ||||||
|  | #   2. We can only take one of each item. | ||||||
|  | #   3. We can only take a fixed amount of each item. | ||||||
|  | 
 | ||||||
|  | items = [(7,160), (3,90), (2,15)] | ||||||
|  | capacity = 20 | ||||||
|  | result = max_haul(items, capacity) | ||||||
|  | expected = None | ||||||
|  | print("Result: {} == Expected: {}".format(result, expected)) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										46
									
								
								scratch/facebook/camping-knapsack.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								scratch/facebook/camping-knapsack.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | from utils import get, init_table, print_table | ||||||
|  | 
 | ||||||
|  | def max_haul(capacity, items, names): | ||||||
|  |     table = init_table(rows=len(items), cols=capacity, default=0) | ||||||
|  |     items_table = init_table(rows=len(items), cols=capacity, default=[]) | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             kg, value = items[row] | ||||||
|  |             curr_capacity = col + 1 | ||||||
|  | 
 | ||||||
|  |             if kg > curr_capacity: | ||||||
|  |                 a = 0 | ||||||
|  |             else: | ||||||
|  |                 a = value + get(table, row - 1, curr_capacity - kg - 1) | ||||||
|  |             b = get(table, row - 1, col) | ||||||
|  | 
 | ||||||
|  |             if a > b: | ||||||
|  |                 rest = get(items_table, row - 1, curr_capacity - kg - 1) | ||||||
|  |                 knapsack = [names.get(items[row])] | ||||||
|  |                 if rest: | ||||||
|  |                     knapsack += rest | ||||||
|  |             else: | ||||||
|  |                 knapsack = get(items_table, row - 1, col) | ||||||
|  | 
 | ||||||
|  |             table[row][col] = max([a, b]) | ||||||
|  |             items_table[row][col] = knapsack | ||||||
|  |         print_table(table) | ||||||
|  |     return items_table[-1][-1] | ||||||
|  | 
 | ||||||
|  | water = (3, 10) | ||||||
|  | book = (1, 3) | ||||||
|  | food = (2, 9) | ||||||
|  | jacket = (2, 5) | ||||||
|  | camera = (1, 6) | ||||||
|  | items = [water, book, food, jacket, camera] | ||||||
|  | result = max_haul(6, items, { | ||||||
|  |     water: 'water', | ||||||
|  |     book: 'book', | ||||||
|  |     food: 'food', | ||||||
|  |     jacket: 'jacket', | ||||||
|  |     camera: 'camera', | ||||||
|  | }) | ||||||
|  | expected = ['camera', 'food', 'water'] | ||||||
|  | print(result, expected) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										50
									
								
								scratch/facebook/coin.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								scratch/facebook/coin.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | def init_table(rows=0, cols=0, default=None): | ||||||
|  |     table = [] | ||||||
|  |     for _ in range(rows): | ||||||
|  |         row = [] | ||||||
|  |         for _ in range(cols): | ||||||
|  |             row.append(default) | ||||||
|  |         table.append(row) | ||||||
|  |     return table | ||||||
|  | 
 | ||||||
|  | def print_table(table): | ||||||
|  |     result = '' | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         x = '' | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             x += str(table[row][col]) + ' ' | ||||||
|  |         result += x + '\n' | ||||||
|  |     print(result) | ||||||
|  | 
 | ||||||
|  | def get(table, row, col): | ||||||
|  |     if row < 0 or col < 0: | ||||||
|  |         return 0 | ||||||
|  |     else: | ||||||
|  |         return table[row][col] | ||||||
|  | 
 | ||||||
|  | def make_change(coins, amt): | ||||||
|  |     table = init_table(rows=len(coins), cols=amt, default=0) | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             coin = coins[row] | ||||||
|  |             curr_amt = col + 1 | ||||||
|  |             pull_down = get(table, row - 1, col) | ||||||
|  | 
 | ||||||
|  |             if curr_amt < coin: | ||||||
|  |                 table[row][col] = pull_down | ||||||
|  |             elif curr_amt == coin: | ||||||
|  |                 table[row][col] = pull_down + 1 | ||||||
|  |             else: | ||||||
|  |                 leftover = get(table, row, curr_amt - coin - 1) | ||||||
|  |                 table[row][col] = pull_down + leftover | ||||||
|  | 
 | ||||||
|  |     print_table(table) | ||||||
|  |     return table[-1][-1] | ||||||
|  | 
 | ||||||
|  | #   1 2 3 4 | ||||||
|  | # 1 1 1 1 1 | ||||||
|  | # 2 1 1 2 2 | ||||||
|  | # 3 1 1 3 4 | ||||||
|  | 
 | ||||||
|  | result = make_change([3,2,1], 4) | ||||||
|  | print(result) | ||||||
							
								
								
									
										19
									
								
								scratch/facebook/delete-node.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scratch/facebook/delete-node.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | from linked_list import Node, from_list | ||||||
|  | 
 | ||||||
|  | def delete(node): | ||||||
|  |     if not node.next: | ||||||
|  |         node.value = None | ||||||
|  |     else: | ||||||
|  |         node.value = node.next.value | ||||||
|  |         node.next = node.next.next | ||||||
|  | 
 | ||||||
|  | one = Node(1) | ||||||
|  | two = Node(2) | ||||||
|  | three = Node(3) | ||||||
|  | 
 | ||||||
|  | one.next = two | ||||||
|  | two.next = three | ||||||
|  | 
 | ||||||
|  | print(one) | ||||||
|  | delete(two) | ||||||
|  | print(one) | ||||||
							
								
								
									
										38
									
								
								scratch/facebook/dijkstras.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								scratch/facebook/dijkstras.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | from heapq import heappush, heappop | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | # Dijkstra's algorithm will traverse a directed graph with weighted edges. If | ||||||
|  | # the edges aren't weighted, we can pretend that each edges weighs 1. The | ||||||
|  | # algorithm will find the shortest path between points A and B. | ||||||
|  | 
 | ||||||
|  | def dijkstra(a, b, graph): | ||||||
|  |     h = [] | ||||||
|  |     seen = set() | ||||||
|  |     heappush(h, (0, a, [a], [])) | ||||||
|  |     while h: | ||||||
|  |         km, x, path, steps = heappop(h) | ||||||
|  | 
 | ||||||
|  |         if x == b: | ||||||
|  |             for a, b, d in steps: | ||||||
|  |                 print("{} -> {} => {}".format(a, b, d)) | ||||||
|  |             return path, km | ||||||
|  | 
 | ||||||
|  |         seen.add(x) | ||||||
|  |         for c, dist in graph[x]: | ||||||
|  |             if c not in seen: | ||||||
|  |                 heappush(h, (km + dist, c, path + [c], steps + [(x, c, dist)])) | ||||||
|  |     return [], float('inf') | ||||||
|  | 
 | ||||||
|  | graph = { | ||||||
|  |     1: [(3, 9), (2, 7), (6, 14)], | ||||||
|  |     2: [(1, 7), (3, 10), (4, 15)], | ||||||
|  |     3: [(1, 9), (6, 2), (4, 11), (2, 10)], | ||||||
|  |     4: [(5, 6), (2, 15), (3, 11)], | ||||||
|  |     5: [(4, 6), (6, 9)], | ||||||
|  |     6: [(5, 9), (3, 2), (1, 14)], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | beg = random.choice(list(graph.keys())) | ||||||
|  | end = random.choice(list(graph.keys())) | ||||||
|  | print("Searching for the shortest path from {} -> {}".format(beg, end)) | ||||||
|  | print(dijkstra(beg, end, graph)) | ||||||
							
								
								
									
										39
									
								
								scratch/facebook/evaluator.hs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								scratch/facebook/evaluator.hs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | ||||||
|  | module Evaluator where | ||||||
|  | 
 | ||||||
|  | data Token | ||||||
|  |   = TokenInt Integer | ||||||
|  |   | TokenAdd | ||||||
|  |   | TokenMultiply | ||||||
|  |   deriving (Eq, Show) | ||||||
|  | 
 | ||||||
|  | newtype AST = AST [Token] | ||||||
|  |   deriving (Eq, Show) | ||||||
|  | 
 | ||||||
|  | tokens :: [Token] | ||||||
|  | tokens = | ||||||
|  |   [ TokenInt 13 | ||||||
|  |   , TokenAdd | ||||||
|  |   , TokenInt 2 | ||||||
|  |   , TokenMultiply | ||||||
|  |   , TokenInt 4 | ||||||
|  |   , TokenAdd | ||||||
|  |   , TokenInt 7 | ||||||
|  |   , TokenAdd | ||||||
|  |   , TokenInt 3 | ||||||
|  |   , TokenMultiply | ||||||
|  |   , TokenInt 8 | ||||||
|  |   ] | ||||||
|  | 
 | ||||||
|  | -- expression     -> addition ; | ||||||
|  | -- addition       -> multiplication ( "+" multiplication )* ; | ||||||
|  | -- multiplication -> terminal ( "*" terminal )* ; | ||||||
|  | -- terminal       -> NUMBER ; | ||||||
|  | 
 | ||||||
|  | parseExpression :: [Token] -> ([Token], AST) | ||||||
|  | parseExpression tokens = do | ||||||
|  |   lhs, rest = parseMultiplication tokens | ||||||
|  | 
 | ||||||
|  | parseMulitplication :: [Token] -> ([Token], AST) | ||||||
|  | 
 | ||||||
|  | main :: IO () | ||||||
|  | main = print $ parse tokens | ||||||
							
								
								
									
										234
									
								
								scratch/facebook/evaluator.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								scratch/facebook/evaluator.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,234 @@ | ||||||
|  | # After stumbling through my first technical screen, I'm going to drill | ||||||
|  | # algorithms for implementing evaluators for a toy expression language: | ||||||
|  | # e.g. 2 + 13 * 3 + 5 * 2 | ||||||
|  | # | ||||||
|  | # As of now, I'm aware of a few algorithms for solving this: | ||||||
|  | #   - DONE: Convert infix expression to Polish notation and evaluate the Polish | ||||||
|  | #     notation. | ||||||
|  | #   - DONE: Evaluate the tokens using two stacks and avoid converting it. | ||||||
|  | #   - DONE: Create a tree of depth two to encode the operator precedence and | ||||||
|  | #     evaluate that AST. | ||||||
|  | #   - TODO: Convert the infix expression to a prefix expression | ||||||
|  | #   - TODO: Write a recursive descent parser and evaluate the AST. | ||||||
|  | 
 | ||||||
|  | operators = { | ||||||
|  |     '*': 1, | ||||||
|  |     '+': 0, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     result = [] | ||||||
|  |     i = 0 | ||||||
|  |     while i < len(xs): | ||||||
|  |         current = xs[i] | ||||||
|  |         if current == ' ': | ||||||
|  |             i += 1 | ||||||
|  |             continue | ||||||
|  |         elif current in operators.keys(): | ||||||
|  |             result.append(current) | ||||||
|  |             i += 1 | ||||||
|  |         else: | ||||||
|  |             i += 1 | ||||||
|  |             while i < len(xs) and xs[i] in {str(n) for n in range(10)}: | ||||||
|  |                 current += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             result.append(int(current)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # Convert infix to postfix; evaluate postfix | ||||||
|  | # I believe this is known as the Shunting-Yards algorithm | ||||||
|  | def postfix(tokens): | ||||||
|  |     result = [] | ||||||
|  |     s = [] | ||||||
|  |     for token in tokens: | ||||||
|  |         if type(token) == int: | ||||||
|  |             result.append(token) | ||||||
|  |         else: | ||||||
|  |             while s and operators[token] < operators[s[-1]]: | ||||||
|  |                 result.append(s.pop()) | ||||||
|  |             s.append(token) | ||||||
|  |     while s: | ||||||
|  |         result.append(s.pop()) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def do_evaluate_with_polish_notation(tokens): | ||||||
|  |     s = [] | ||||||
|  |     for token in tokens: | ||||||
|  |         if token == '*': | ||||||
|  |             s.append(s.pop() * s.pop()) | ||||||
|  |         elif token == '+': | ||||||
|  |             s.append(s.pop() + s.pop()) | ||||||
|  |         else: | ||||||
|  |             s.append(token) | ||||||
|  |     return s[-1] | ||||||
|  | 
 | ||||||
|  | def evaluate_with_polish_notation(expr): | ||||||
|  |     tokens = tokenize(expr) | ||||||
|  |     print("Tokens:  {}".format(tokens)) | ||||||
|  |     pn = postfix(tokens) | ||||||
|  |     print("Postfix: {}".format(pn)) | ||||||
|  |     result = do_evaluate_with_polish_notation(pn) | ||||||
|  |     print("Result:  {}".format(result)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # Evaluate Tokens | ||||||
|  | 
 | ||||||
|  | def apply_operator(op, a, b): | ||||||
|  |     if op == '*': | ||||||
|  |         return a * b | ||||||
|  |     elif op == '+': | ||||||
|  |         return a + b | ||||||
|  | 
 | ||||||
|  | def do_evaluate_tokens(tokens): | ||||||
|  |     vals = [] | ||||||
|  |     ops = [] | ||||||
|  |     for token in tokens: | ||||||
|  |         if type(token) == int: | ||||||
|  |             vals.append(token) | ||||||
|  |         elif token == '*': | ||||||
|  |             ops.append(token) | ||||||
|  |         elif token == '+': | ||||||
|  |             while ops and operators[token] < operators[ops[-1]]: | ||||||
|  |                 vals.append(apply_operator(ops.pop(), vals.pop(), vals.pop())) | ||||||
|  |             ops.append(token) | ||||||
|  |         else: | ||||||
|  |             raise Exception("Unexpected token: {}".format(token)) | ||||||
|  |     while ops: | ||||||
|  |         vals.append(apply_operator(ops.pop(), vals.pop(), vals.pop())) | ||||||
|  |     return vals[-1] | ||||||
|  | 
 | ||||||
|  | def evaluate_tokens(expr): | ||||||
|  |     tokens = tokenize(expr) | ||||||
|  |     print("Tokens:  {}".format(tokens)) | ||||||
|  |     result = do_evaluate_tokens(tokens) | ||||||
|  |     print("Result:  {}".format(result)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # Ad Hoc Tree | ||||||
|  | 
 | ||||||
|  | def parse(tokens): | ||||||
|  |     result = [] | ||||||
|  |     series = [] | ||||||
|  |     for token in tokens: | ||||||
|  |         if type(token) == int: | ||||||
|  |             series.append(token) | ||||||
|  |         elif token == '*': | ||||||
|  |             continue | ||||||
|  |         elif token == '+': | ||||||
|  |             result.append(series) | ||||||
|  |             series = [] | ||||||
|  |         else: | ||||||
|  |             raise Exception("Unexpected token: {}".format(token)) | ||||||
|  |     result.append(series) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def product(xs): | ||||||
|  |     result = 1 | ||||||
|  |     for x in xs: | ||||||
|  |         result *= x | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def do_evaluate_ad_hoc_tree(ast): | ||||||
|  |     return sum([product(xs) for xs in ast]) | ||||||
|  | 
 | ||||||
|  | def evaluate_ad_hoc_tree(expr): | ||||||
|  |     tokens = tokenize(expr) | ||||||
|  |     print("Tokens:  {}".format(tokens)) | ||||||
|  |     ast = parse(tokens) | ||||||
|  |     print("AST:     {}".format(ast)) | ||||||
|  |     result = do_evaluate_ad_hoc_tree(ast) | ||||||
|  |     print("Result:  {}".format(result)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # Recursive Descent Parser | ||||||
|  | 
 | ||||||
|  | # expression     -> addition ; | ||||||
|  | # addition       -> multiplication ( "+" multiplication )* ; | ||||||
|  | # multiplication -> terminal ( "*" terminal )* ; | ||||||
|  | # terminal       -> NUMBER ; | ||||||
|  | 
 | ||||||
|  | class Parser(object): | ||||||
|  |     def __init__(self, tokens): | ||||||
|  |         self.tokens = tokens | ||||||
|  |         self.i = 0 | ||||||
|  | 
 | ||||||
|  |     # mutations | ||||||
|  |     def advance(self): | ||||||
|  |         self.i += 1 | ||||||
|  | 
 | ||||||
|  |     def consume(self): | ||||||
|  |         result = self.curr() | ||||||
|  |         self.advance() | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  |     # predicates | ||||||
|  |     def match(self, x): | ||||||
|  |         if self.curr() == x: | ||||||
|  |             self.advance() | ||||||
|  |             return True | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  |     def tokens_available(self): | ||||||
|  |         return self.i < len(self.tokens) | ||||||
|  | 
 | ||||||
|  |     # getters | ||||||
|  |     def prev(self): | ||||||
|  |         return self.tokens[self.i - 1] | ||||||
|  | 
 | ||||||
|  |     def curr(self): | ||||||
|  |         return self.tokens[self.i] if self.tokens_available() else None | ||||||
|  | 
 | ||||||
|  |     def next(self): | ||||||
|  |         return self.tokens[self.i + 1] | ||||||
|  | 
 | ||||||
|  | def parse_expression(tokens): | ||||||
|  |     parser = Parser(tokens) | ||||||
|  |     return parse_addition(parser) | ||||||
|  | 
 | ||||||
|  | def parse_addition(parser): | ||||||
|  |     result = parse_multiplication(parser) | ||||||
|  |     while parser.match("+"): | ||||||
|  |         op = parser.prev() | ||||||
|  |         rhs = parse_multiplication(parser) | ||||||
|  |         result = ["+", result, rhs] | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def parse_multiplication(parser): | ||||||
|  |     result = parse_terminal(parser) | ||||||
|  |     while parser.match("*"): | ||||||
|  |         op = parser.prev() | ||||||
|  |         rhs = parse_terminal(parser) | ||||||
|  |         result = ["*", result, rhs] | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def parse_terminal(parser): | ||||||
|  |     # If we reach here, the current token *must* be a number. | ||||||
|  |     return parser.consume() | ||||||
|  | 
 | ||||||
|  | def evaluate_ast(ast): | ||||||
|  |     if type(ast) == int: | ||||||
|  |         return ast | ||||||
|  |     else: | ||||||
|  |         op, lhs, rhs = ast[0], ast[1], ast[2] | ||||||
|  |         return apply_operator(op, evaluate_ast(lhs), evaluate_ast(rhs)) | ||||||
|  | 
 | ||||||
|  | def evaluate_recursive_descent(expr): | ||||||
|  |     tokens = tokenize(expr) | ||||||
|  |     print("Tokens:  {}".format(tokens)) | ||||||
|  |     ast = parse_expression(tokens) | ||||||
|  |     print("AST:     {}".format(ast)) | ||||||
|  |     result = evaluate_ast(ast) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | methods = { | ||||||
|  |     'Polish Notation': evaluate_with_polish_notation, | ||||||
|  |     'Evaluate Tokens': evaluate_tokens, | ||||||
|  |     'Ad Hoc Tree': evaluate_ad_hoc_tree, | ||||||
|  |     'Recursive Descent': evaluate_recursive_descent, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | for name, fn in methods.items(): | ||||||
|  |     expr = "13 + 2 * 4 + 7 + 3 * 8" | ||||||
|  |     print("Evaluating \"{}\" using the \"{}\" method...".format(expr, name)) | ||||||
|  |     assert fn(expr) == eval(expr) | ||||||
|  |     print("Success!") | ||||||
							
								
								
									
										22
									
								
								scratch/facebook/find-duplicate-optimize-for-space.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								scratch/facebook/find-duplicate-optimize-for-space.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | def find_duplicate(xs): | ||||||
|  |     print(xs) | ||||||
|  |     # entry point in our cycle is the duplicate | ||||||
|  |     i = xs[0] | ||||||
|  |     j = xs[xs[0]] | ||||||
|  |     while i != j: | ||||||
|  |         print(i, xs[i], j, xs[j]) | ||||||
|  |         i = xs[i] | ||||||
|  |         j = xs[xs[j]] | ||||||
|  |     # detect cycle | ||||||
|  |     j = 0 | ||||||
|  |     while i != j: | ||||||
|  |         i = xs[i] | ||||||
|  |         j = xs[j] | ||||||
|  |     return xs[i] | ||||||
|  | 
 | ||||||
|  | n = random.randint(5, 10) | ||||||
|  | xs = [random.randint(0, n - 1) for _ in range(n)] | ||||||
|  | result = find_duplicate(xs) | ||||||
|  | print(xs, result) | ||||||
							
								
								
									
										47
									
								
								scratch/facebook/find-rotation-point.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								scratch/facebook/find-rotation-point.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | from math import floor | ||||||
|  | 
 | ||||||
|  | def find_rotation(xs): | ||||||
|  |     if xs[0] < xs[-1]: | ||||||
|  |         return xs[0] | ||||||
|  |     beg, end = 0, len(xs) - 1 | ||||||
|  |     found = False | ||||||
|  |     count = 10 | ||||||
|  |     while not found and count >= 0: | ||||||
|  |         i = beg + floor((end - beg) / 2) | ||||||
|  |         if xs[beg] < xs[i]: | ||||||
|  |             beg = i | ||||||
|  |             i = beg + floor((end - beg) / 2) | ||||||
|  |         elif xs[beg] > xs[i]: | ||||||
|  |             end = i | ||||||
|  |         found = xs[i - 1] > xs[i] | ||||||
|  |         count -= 1 | ||||||
|  |     return xs[i] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | xs = [(['ptolemaic', | ||||||
|  |         'retrograde', | ||||||
|  |         'supplant', | ||||||
|  |         'undulate', | ||||||
|  |         'xenoepist', | ||||||
|  |         'zebra', | ||||||
|  |         'asymptote', | ||||||
|  |         'babka', | ||||||
|  |         'banoffee', | ||||||
|  |         'engender', | ||||||
|  |         'karpatka', | ||||||
|  |         'othellolagkage', | ||||||
|  |         ], "asymptote"), | ||||||
|  |       (['asymptote', | ||||||
|  |         'babka', | ||||||
|  |         'banoffee', | ||||||
|  |         'engender', | ||||||
|  |         'karpatka', | ||||||
|  |         'othellolagkage', | ||||||
|  |         ], "asymptote"), | ||||||
|  |       ] | ||||||
|  | 
 | ||||||
|  | for x, expected in xs: | ||||||
|  |     result = find_rotation(x) | ||||||
|  |     print(x, result) | ||||||
|  |     assert result == expected | ||||||
|  |     print("Success!") | ||||||
							
								
								
									
										17
									
								
								scratch/facebook/find-unique-int-among-duplicates.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								scratch/facebook/find-unique-int-among-duplicates.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | def find_duplicate(xs): | ||||||
|  |     mini, maxi, acc = xs[0], xs[0], xs[0] | ||||||
|  |     for i in range(1, len(xs)): | ||||||
|  |         mini = min(mini, xs[i]) | ||||||
|  |         maxi = max(maxi, xs[i]) | ||||||
|  |         acc = acc ^ xs[i] | ||||||
|  |     mask = mini | ||||||
|  |     for i in range(mini + 1, maxi + 1): | ||||||
|  |         mask = mask ^ i | ||||||
|  |     return mask ^ acc | ||||||
|  | 
 | ||||||
|  | xs = [5, 3, 4, 1, 5, 2] | ||||||
|  | print(xs) | ||||||
|  | result = find_duplicate(xs) | ||||||
|  | print(result) | ||||||
							
								
								
									
										60
									
								
								scratch/facebook/graph-coloring.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								scratch/facebook/graph-coloring.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | ||||||
|  | from collections import deque | ||||||
|  | 
 | ||||||
|  | class Palette(object): | ||||||
|  |     def __init__(self, n): | ||||||
|  |         self.i = 0 | ||||||
|  |         self.colors = list(range(n)) | ||||||
|  | 
 | ||||||
|  |     def get(self): | ||||||
|  |         return self.colors[self.i] | ||||||
|  | 
 | ||||||
|  |     def advance(self): | ||||||
|  |         self.i += 1 % len(self.colors) | ||||||
|  | 
 | ||||||
|  | class GraphNode(object): | ||||||
|  |     def __init__(self, label): | ||||||
|  |         self.label = label | ||||||
|  |         self.neighbors = set() | ||||||
|  |         self.color = None | ||||||
|  | 
 | ||||||
|  |     def __repr__(self): | ||||||
|  |         result = [] | ||||||
|  |         xs = deque() | ||||||
|  |         xs.append(self) | ||||||
|  |         seen = set() | ||||||
|  |         while xs: | ||||||
|  |             node = xs.popleft() | ||||||
|  |             result.append('{} ({})'.format(node.label, str(node.color))) | ||||||
|  |             seen.add(node.label) | ||||||
|  |             for c in node.neighbors: | ||||||
|  |                 if c.label not in seen: | ||||||
|  |                     xs.append(c) | ||||||
|  |         return ', '.join(result) | ||||||
|  | 
 | ||||||
|  | def color_graph(graph, d): | ||||||
|  |     seen = set() | ||||||
|  |     start = graph | ||||||
|  |     xs = deque() | ||||||
|  |     palette = Palette(d + 1) | ||||||
|  |     xs.append((start, palette.get())) | ||||||
|  |     while xs: | ||||||
|  |         x, color = xs.popleft() | ||||||
|  |         x.color = color | ||||||
|  |         seen.add(x.label) | ||||||
|  |         for c in x.neighbors: | ||||||
|  |             if c.label not in seen: | ||||||
|  |                 palette.advance() | ||||||
|  |                 xs.append((c, palette.get())) | ||||||
|  | 
 | ||||||
|  | a = GraphNode('a') | ||||||
|  | b = GraphNode('b') | ||||||
|  | c = GraphNode('c') | ||||||
|  | 
 | ||||||
|  | a.neighbors.add(b) | ||||||
|  | b.neighbors.add(a) | ||||||
|  | b.neighbors.add(c) | ||||||
|  | c.neighbors.add(b) | ||||||
|  | 
 | ||||||
|  | print(a) | ||||||
|  | color_graph(a, 3) | ||||||
|  | print(a) | ||||||
							
								
								
									
										20
									
								
								scratch/facebook/highest-product-of-3.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								scratch/facebook/highest-product-of-3.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | def hi_product(xs): | ||||||
|  |     lowest_one, highest_one = min(xs[0], xs[1]), max(xs[0], xs[1]) | ||||||
|  |     lowest_two, highest_two = xs[0] * xs[1], xs[0] * xs[1] | ||||||
|  |     highest = float('-inf') | ||||||
|  |     for x in xs[2:]: | ||||||
|  |         highest = max(highest, highest_two * x, lowest_two * x) | ||||||
|  |         lowest_one = min(lowest_one, x) | ||||||
|  |         highest_one = max(highest_one, x) | ||||||
|  |         lowest_two = min(lowest_two, highest_one * x, lowest_one * x) | ||||||
|  |         highest_two = max(highest_two, highest_one * x, lowest_one * x) | ||||||
|  |     return highest | ||||||
|  | 
 | ||||||
|  | xs = [([-10,-10,1,3,2], 300), | ||||||
|  |       ([1,10,-5,1,-100], 5000)] | ||||||
|  | 
 | ||||||
|  | for x, expected in xs: | ||||||
|  |     result = hi_product(x) | ||||||
|  |     print(x, result) | ||||||
|  |     assert result == expected | ||||||
|  |     print("Success!") | ||||||
							
								
								
									
										51
									
								
								scratch/facebook/infix-to-postfix.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								scratch/facebook/infix-to-postfix.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | ||||||
|  | operators = { | ||||||
|  |     '*': 1, | ||||||
|  |     '+': 0, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     result = [] | ||||||
|  |     i = 0 | ||||||
|  |     while i < len(xs): | ||||||
|  |         current = xs[i] | ||||||
|  |         if current in operators.keys(): | ||||||
|  |             result.append(current) | ||||||
|  |             i += 1 | ||||||
|  |             continue | ||||||
|  |         else: | ||||||
|  |             i += 1 | ||||||
|  |             while i < len(xs) and xs[i] in {str(n) for n in range(10)}: | ||||||
|  |                 current += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             result.append(int(current)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def postfix(xs): | ||||||
|  |     result = [] | ||||||
|  |     s = [] | ||||||
|  |     for x in xs: | ||||||
|  |         if x in operators.keys(): | ||||||
|  |             while s and operators[s[-1]] >= operators[x]: | ||||||
|  |                 result.append(s.pop()) | ||||||
|  |             s.append(x) | ||||||
|  |         else: | ||||||
|  |             result.append(x) | ||||||
|  |     while s: | ||||||
|  |         result.append(s.pop()) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def evaluate(xs): | ||||||
|  |     s = [] | ||||||
|  |     for x in xs: | ||||||
|  |         print(s, x) | ||||||
|  |         if x == '*': | ||||||
|  |             s.append(s.pop() * s.pop()) | ||||||
|  |         elif x == '+': | ||||||
|  |             s.append(s.pop() + s.pop()) | ||||||
|  |         else: | ||||||
|  |             s.append(x) | ||||||
|  |         print(s) | ||||||
|  |     return s[-1] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | print(evaluate(postfix(tokenize("12+3*10")))) | ||||||
							
								
								
									
										29
									
								
								scratch/facebook/inflight-entertainment.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								scratch/facebook/inflight-entertainment.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | from random import choice | ||||||
|  | from utils import init_table | ||||||
|  | 
 | ||||||
|  | def get(movie, seeking): | ||||||
|  |     return any([movie in xs for xs in seeking.values()]) | ||||||
|  | 
 | ||||||
|  | def set_complement(movie, seeking): | ||||||
|  |     for duration, xs in seeking.items(): | ||||||
|  |         seeking[duration].add(duration - movie) | ||||||
|  | 
 | ||||||
|  | def choose_movies(tolerance, duration, movies): | ||||||
|  |     seeking = {duration + i: set() for i in range(-1 * tolerance, tolerance + 1)} | ||||||
|  |     for movie in movies: | ||||||
|  |         if get(movie, seeking): | ||||||
|  |             return movie, duration - movie | ||||||
|  |         else: | ||||||
|  |             set_complement(movie, seeking) | ||||||
|  |     return None | ||||||
|  | 
 | ||||||
|  | tolerance = 20 | ||||||
|  | duration = choice([1, 2, 3]) * choice([1, 2]) * choice([15, 30, 45]) | ||||||
|  | movies = [choice([1, 2, 3]) * choice([15, 30, 45]) for _ in range(10)] | ||||||
|  | print("Seeking two movies for a duration of [{}, {}] minutes".format(duration - tolerance, duration + tolerance)) | ||||||
|  | print(movies) | ||||||
|  | result = choose_movies(tolerance, duration, movies) | ||||||
|  | if result: | ||||||
|  |     print("{} + {} = {}".format(result[0], result[1], duration)) | ||||||
|  | else: | ||||||
|  |     print(":( We're sad because we couldn't find two movies for a {} minute flight".format(duration)) | ||||||
							
								
								
									
										42
									
								
								scratch/facebook/knapsack-faq.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								scratch/facebook/knapsack-faq.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | from utils import get, init_table, print_table | ||||||
|  | 
 | ||||||
|  | # This problem has a few variants: | ||||||
|  | #   - limited supply of each item | ||||||
|  | #   - unlimited supply of each item | ||||||
|  | #   - fractional amounts of each item (e.g. rice) | ||||||
|  | 
 | ||||||
|  | def max_haul(capacity, items): | ||||||
|  |     min_kg = min([kg for _, kg in items]) | ||||||
|  |     max_kg = max([kg for _, kg in items]) | ||||||
|  | 
 | ||||||
|  |     cols = int(max_kg / min_kg) | ||||||
|  |     fr_col_index = lambda index: min_kg * index + min_kg | ||||||
|  |     to_col_index = lambda capacity: int((capacity - min_kg) * cols / max_kg) | ||||||
|  | 
 | ||||||
|  |     table = init_table(rows=len(items), cols=cols, default=0) | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             curr_capacity = fr_col_index(col) | ||||||
|  |             value, kg = items[row] | ||||||
|  | 
 | ||||||
|  |             if kg > curr_capacity: | ||||||
|  |                 a = 0 | ||||||
|  |             else: | ||||||
|  |                 a = value + get(table, row - 1, to_col_index(curr_capacity - kg)) | ||||||
|  | 
 | ||||||
|  |             b = get(table, row - 1, col) | ||||||
|  |             table[row][col] = max([a, b]) | ||||||
|  |         print_table(table) | ||||||
|  |     return table[-1][-1] | ||||||
|  | 
 | ||||||
|  | guitar = (1500, 1) | ||||||
|  | stereo = (3000, 4) | ||||||
|  | laptop = (2000, 3) | ||||||
|  | necklace = (2000, 0.5) | ||||||
|  | items = [necklace, guitar, stereo, laptop] | ||||||
|  | capacity = 4 | ||||||
|  | result = max_haul(capacity, items) | ||||||
|  | expected = 4000 | ||||||
|  | print(result, expected) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										26
									
								
								scratch/facebook/kth-to-last-node-in-singly-linked-list.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								scratch/facebook/kth-to-last-node-in-singly-linked-list.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | from linked_list import Node, from_list | ||||||
|  | 
 | ||||||
|  | def kth_to_last_node(k, node): | ||||||
|  |     one = node | ||||||
|  |     two = node | ||||||
|  |     for _ in range(k - 1): | ||||||
|  |         if not one: | ||||||
|  |             return None | ||||||
|  |         one = one.next | ||||||
|  |     while one.next: | ||||||
|  |         one = one.next | ||||||
|  |         two = two.next | ||||||
|  |     return two.value | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | xs = from_list(["Angel Food", "Bundt", "Cheese", "Devil's Food", "Eccles"]) | ||||||
|  | result = kth_to_last_node(2, xs) | ||||||
|  | print(result) | ||||||
|  | assert result == "Devil's Food" | ||||||
|  | print("Success!") | ||||||
|  | 
 | ||||||
|  | xs = from_list(["Angel Food", "Bundt"]) | ||||||
|  | result = kth_to_last_node(30, xs) | ||||||
|  | print(result) | ||||||
|  | assert result is None | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										70
									
								
								scratch/facebook/language.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								scratch/facebook/language.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | # Write an evaluator for a small language: | ||||||
|  | #   - operators: '+', '*' | ||||||
|  | #   - operands:  Integers | ||||||
|  | # | ||||||
|  | # E.g. evaluate("2+14*90+5*16") | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     result = [] | ||||||
|  |     i = 0 | ||||||
|  |     while i < len(xs): | ||||||
|  |         current = xs[i] | ||||||
|  |         if current in {'*', '+'}: | ||||||
|  |             result.append(current) | ||||||
|  |             i += 1 | ||||||
|  |             continue | ||||||
|  |         elif current == ' ': | ||||||
|  |             i += 1 | ||||||
|  |             continue | ||||||
|  |         else: | ||||||
|  |             i += 1 | ||||||
|  |             while i < len(xs) and xs[i] in {str(x) for x in range(10)}: | ||||||
|  |                 current += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             result.append(int(current)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def ast(tokens): | ||||||
|  |     result = [] | ||||||
|  |     series = [] | ||||||
|  |     for token in tokens: | ||||||
|  |         if token == '+': | ||||||
|  |             result.append(series) | ||||||
|  |             series = [] | ||||||
|  |         elif token == '*': | ||||||
|  |             continue | ||||||
|  |         else: | ||||||
|  |             series.append(token) | ||||||
|  |     if series: | ||||||
|  |         result.append(series) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def product(xs): | ||||||
|  |     result = 1 | ||||||
|  |     for x in xs: | ||||||
|  |         result *= x | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def evaluate(x): | ||||||
|  |     tokens = tokenize(x) | ||||||
|  |     tree = ast(tokens) | ||||||
|  |     return sum([product(xs) for xs in tree]) | ||||||
|  | 
 | ||||||
|  | n = 7 | ||||||
|  | operands = [random.randint(0, 100) for _ in range(n)] | ||||||
|  | operators = [random.choice(['+','*']) for _ in range(n - 1)] | ||||||
|  | expr = [] | ||||||
|  | for i in range(n - 1): | ||||||
|  |     expr.append(operands[i]) | ||||||
|  |     expr.append(operators[i]) | ||||||
|  | expr.append(operands[-1]) | ||||||
|  | 
 | ||||||
|  | expr = ' '.join([str(x) for x in expr]) | ||||||
|  | print("Expression: {}".format(expr)) | ||||||
|  | print("Tokens: {}".format(tokenize(expr))) | ||||||
|  | print("AST: {}".format(ast(tokenize(expr)))) | ||||||
|  | print("Answer: {}".format(evaluate(expr))) | ||||||
|  | assert evaluate(expr) == eval(expr) | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										50
									
								
								scratch/facebook/language2.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								scratch/facebook/language2.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     result = [] | ||||||
|  |     i = 0 | ||||||
|  |     while i < len(xs): | ||||||
|  |         curr = xs[i] | ||||||
|  |         if curr in {'*','+'}: | ||||||
|  |             result.append(curr) | ||||||
|  |             i += 1 | ||||||
|  |             continue | ||||||
|  |         i += 1 | ||||||
|  |         while i < len(xs) and xs[i] in {str(x) for x in range(10)}: | ||||||
|  |             curr += xs[i] | ||||||
|  |             i += 1 | ||||||
|  |         result.append(int(curr)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def parse(tokens): | ||||||
|  |     result = [] | ||||||
|  |     series = [] | ||||||
|  |     for token in tokens: | ||||||
|  |         if token == '*': | ||||||
|  |             continue | ||||||
|  |         elif token == '+': | ||||||
|  |             result.append(series) | ||||||
|  |             series = [] | ||||||
|  |         else: | ||||||
|  |             series.append(token) | ||||||
|  |     if series: | ||||||
|  |         result.append(series) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def product(xs): | ||||||
|  |     result = 1 | ||||||
|  |     for x in xs: | ||||||
|  |         result *= x | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def evaluate(tree): | ||||||
|  |     return sum([product(xs) for xs in tree]) | ||||||
|  | 
 | ||||||
|  | print(evaluate(parse(tokenize("2+30*8*9+10")))) | ||||||
							
								
								
									
										15
									
								
								scratch/facebook/largest-contiguous-sum.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								scratch/facebook/largest-contiguous-sum.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | def find_sum(xs): | ||||||
|  |     result = float('-inf') | ||||||
|  |     streak = 0 | ||||||
|  |     for x in xs: | ||||||
|  |         result = max(result, streak, x) | ||||||
|  |         if streak + x <= 0: | ||||||
|  |             streak = x | ||||||
|  |         else: | ||||||
|  |             streak += x | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | x = [2,-8,3,-2,4,-10] | ||||||
|  | assert find_sum(x) == 5 | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										49
									
								
								scratch/facebook/largest-stack.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								scratch/facebook/largest-stack.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,49 @@ | ||||||
|  | from stack import Stack, from_list | ||||||
|  | from heapq import heapify, heappush, heappop | ||||||
|  | from random import shuffle | ||||||
|  | 
 | ||||||
|  | class MaxStack(Stack): | ||||||
|  |     def __init__(self): | ||||||
|  |         self.max = Stack() | ||||||
|  |         super().__init__() | ||||||
|  | 
 | ||||||
|  |     def __repr__(self): | ||||||
|  |         return super().__repr__() | ||||||
|  | 
 | ||||||
|  |     def push(self, x): | ||||||
|  |         super().push(x) | ||||||
|  |         max = self.get_max() | ||||||
|  |         if not max: | ||||||
|  |             self.max.push(x) | ||||||
|  |         else: | ||||||
|  |             self.max.push(max if x < max else x) | ||||||
|  | 
 | ||||||
|  |     def pop(self): | ||||||
|  |         self.max.pop() | ||||||
|  |         return super().pop() | ||||||
|  | 
 | ||||||
|  |     def get_max(self): | ||||||
|  |         return self.max.peek() | ||||||
|  | 
 | ||||||
|  | xs = list(range(1, 11)) | ||||||
|  | shuffle(xs) | ||||||
|  | stack = MaxStack() | ||||||
|  | for x in xs: | ||||||
|  |     stack.push(x) | ||||||
|  | 
 | ||||||
|  | print(stack) | ||||||
|  | result = stack.get_max() | ||||||
|  | print(result) | ||||||
|  | assert result == 10 | ||||||
|  | 
 | ||||||
|  | popped = stack.pop() | ||||||
|  | print("Popped: {}".format(popped)) | ||||||
|  | print(stack) | ||||||
|  | while popped != 10: | ||||||
|  |     assert stack.get_max() == 10 | ||||||
|  |     popped = stack.pop() | ||||||
|  |     print("Popped: {}".format(popped)) | ||||||
|  |     print(stack) | ||||||
|  | 
 | ||||||
|  | assert stack.get_max() != 10 | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										26
									
								
								scratch/facebook/linked-list-cycles.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								scratch/facebook/linked-list-cycles.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | from linked_list import Node | ||||||
|  | 
 | ||||||
|  | def contains_cycle(node): | ||||||
|  |     one = node | ||||||
|  |     two = node | ||||||
|  |     while two.next and two.next.next: | ||||||
|  |         one = one.next | ||||||
|  |         two = two.next.next | ||||||
|  |         if one == two: | ||||||
|  |             return True | ||||||
|  |     return False | ||||||
|  | 
 | ||||||
|  | xs = Node(1, Node(2, Node(3))) | ||||||
|  | assert not contains_cycle(xs) | ||||||
|  | print("Success!") | ||||||
|  | 
 | ||||||
|  | a = Node(1) | ||||||
|  | b = Node(2) | ||||||
|  | c = Node(3) | ||||||
|  | a.next = b | ||||||
|  | b.next = c | ||||||
|  | c.next = random.choice([a, b, c]) | ||||||
|  | assert contains_cycle(a) | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										22
									
								
								scratch/facebook/linked_list.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								scratch/facebook/linked_list.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | class Node(object): | ||||||
|  |     def __init__(self, value=None, next=None): | ||||||
|  |         self.value = value | ||||||
|  |         self.next = next | ||||||
|  | 
 | ||||||
|  |     def __repr__(self): | ||||||
|  |         result = [] | ||||||
|  |         node = self | ||||||
|  |         while node: | ||||||
|  |             result.append(str(node.value)) | ||||||
|  |             node = node.next | ||||||
|  |         return 'LinkedList({xs})'.format(xs=', '.join(result)) | ||||||
|  | 
 | ||||||
|  | def from_list(xs): | ||||||
|  |     head = Node(xs[0]) | ||||||
|  |     node = head | ||||||
|  |     for x in xs[1:]: | ||||||
|  |         node.next = Node(x) | ||||||
|  |         node = node.next | ||||||
|  |     return head | ||||||
|  | 
 | ||||||
|  | list = from_list(['A', 'B', 'C']) | ||||||
							
								
								
									
										42
									
								
								scratch/facebook/london-knapsack.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								scratch/facebook/london-knapsack.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | from utils import get, init_table, print_table | ||||||
|  | 
 | ||||||
|  | def optimal_itinerary(duration, items): | ||||||
|  |     min_duration = min([duration for duration, _ in items]) | ||||||
|  |     max_duration = max([duration for duration, _ in items]) | ||||||
|  |     table = init_table(rows=len(items), cols=int(max_duration / min_duration), default=0) | ||||||
|  |     to_index = lambda duration: int(duration / min_duration) - 1 | ||||||
|  |     to_duration = lambda i: i * min_duration + min_duration | ||||||
|  | 
 | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             curr_duration = to_duration(col) | ||||||
|  |             duration, value = items[row] | ||||||
|  |             if duration > curr_duration: | ||||||
|  |                 a = 0 | ||||||
|  |             else: | ||||||
|  |                 a = value + get(table, row - 1, to_index(curr_duration - duration)) | ||||||
|  |             b = get(table, row - 1, col) | ||||||
|  |             table[row][col] = max([a, b]) | ||||||
|  | 
 | ||||||
|  |         print_table(table) | ||||||
|  |     return table[-1][-1] | ||||||
|  | 
 | ||||||
|  | # You're in London for two days, and you'd like to see the following | ||||||
|  | # attractions. How can you maximize your time spent in London? | ||||||
|  | westminster = (0.5, 7) | ||||||
|  | globe_theater = (0.5, 6) | ||||||
|  | national_gallery = (1, 9) | ||||||
|  | british_museum = (2, 9) | ||||||
|  | st_pauls_cathedral = (0.5, 8) | ||||||
|  | items = [ | ||||||
|  |     westminster, | ||||||
|  |     globe_theater, | ||||||
|  |     national_gallery, | ||||||
|  |     british_museum, | ||||||
|  |     st_pauls_cathedral, | ||||||
|  | ] | ||||||
|  | result = optimal_itinerary(2, items) | ||||||
|  | expected = 24 | ||||||
|  | print(result, expected) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										20
									
								
								scratch/facebook/longest-common-substring.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								scratch/facebook/longest-common-substring.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | from utils import get, init_table, print_table | ||||||
|  | 
 | ||||||
|  | def longest_common_substring(a, b): | ||||||
|  |     """ | ||||||
|  |     Computes the length of the longest string that's present in both `a` and | ||||||
|  |     `b`. | ||||||
|  |     """ | ||||||
|  |     table = init_table(rows=len(b), cols=len(a), default=0) | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             if b[row] == a[col]: | ||||||
|  |                 table[row][col] = 1 + get(table, row - 1, col - 1) | ||||||
|  |     return max([max(row) for row in table]) | ||||||
|  | 
 | ||||||
|  | dictionary = ["fish", "vista"] | ||||||
|  | result = [longest_common_substring("hish", x) for x in dictionary] | ||||||
|  | expected = [3, 2] | ||||||
|  | print(result, expected) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										44
									
								
								scratch/facebook/merge-sorted-arrays.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								scratch/facebook/merge-sorted-arrays.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | def merge_sorted(xs, ys): | ||||||
|  |     result = [] | ||||||
|  |     i, j = 0, 0 | ||||||
|  | 
 | ||||||
|  |     while i < len(xs) and j < len(ys): | ||||||
|  |         if xs[i] <= ys[j]: | ||||||
|  |             result.append(xs[i]) | ||||||
|  |             i += 1 | ||||||
|  |         else: | ||||||
|  |             result.append(ys[j]) | ||||||
|  |             j += 1 | ||||||
|  | 
 | ||||||
|  |     while i < len(xs): | ||||||
|  |         result.append(xs[i]) | ||||||
|  |         i += 1 | ||||||
|  | 
 | ||||||
|  |     while j < len(ys): | ||||||
|  |         result.append(ys[j]) | ||||||
|  |         j += 1 | ||||||
|  | 
 | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # A | ||||||
|  | result = merge_sorted([3, 4, 6, 10, 11, 15], [1, 5, 8, 12, 14, 19]) | ||||||
|  | print(result) | ||||||
|  | assert result == [1, 3, 4, 5, 6, 8, 10, 11, 12, 14, 15, 19] | ||||||
|  | 
 | ||||||
|  | # B | ||||||
|  | result = merge_sorted([], [1,2,3]) | ||||||
|  | print(result) | ||||||
|  | assert result == [1,2,3] | ||||||
|  | 
 | ||||||
|  | # C | ||||||
|  | result = merge_sorted([1,2,3], []) | ||||||
|  | print(result) | ||||||
|  | assert result == [1,2,3] | ||||||
|  | 
 | ||||||
|  | # D | ||||||
|  | result = merge_sorted([], []) | ||||||
|  | print(result) | ||||||
|  | assert result == [] | ||||||
|  | 
 | ||||||
|  | # Wahoo! | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										23
									
								
								scratch/facebook/merging-ranges.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								scratch/facebook/merging-ranges.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,23 @@ | ||||||
|  | 
 | ||||||
|  | def merge(xs): | ||||||
|  |     xs.sort() | ||||||
|  |     result = xs[0:1] | ||||||
|  |     for a, b in xs[1:]: | ||||||
|  |         y, z = result[-1] | ||||||
|  |         if a <= z: | ||||||
|  |             result[-1] = (y, max(b, z)) | ||||||
|  |         else: | ||||||
|  |             result.append((a, b)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | inputs = [([(0,1),(3,5),(4,8),(10,12),(9,10)], [(0,1),(3,8),(9,12)]), | ||||||
|  |           ([(1,2),(2,3)], [(1,3)]), | ||||||
|  |           ([(1,5),(2,3)], [(1,5)]), | ||||||
|  |           ([(1,10),(2,6),(3,5),(7,9)], [(1,10)]), | ||||||
|  |           ] | ||||||
|  | for x, expected in inputs: | ||||||
|  |     result = merge(x) | ||||||
|  |     print(x) | ||||||
|  |     print(result) | ||||||
|  |     assert result == expected | ||||||
|  |     print("Success!") | ||||||
							
								
								
									
										40
									
								
								scratch/facebook/mesh-message.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								scratch/facebook/mesh-message.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,40 @@ | ||||||
|  | from heapq import heappush, heappop | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | def shortest_path(a, b, graph): | ||||||
|  |     seen = set() | ||||||
|  |     h = [] | ||||||
|  |     heappush(h, (0, a, [a])) | ||||||
|  |     while h: | ||||||
|  |         km, x, path = heappop(h) | ||||||
|  |         if x == b: | ||||||
|  |             return path | ||||||
|  |         for c in graph[x]: | ||||||
|  |             if c not in seen: | ||||||
|  |                 heappush(h, (km + 1, c, path + [c])) | ||||||
|  |     raise Exception("We were unable to find a path from {} to {}".format(a, b)) | ||||||
|  | 
 | ||||||
|  | graph = { | ||||||
|  |     'Min'     : ['William', 'Jayden', 'Omar'], | ||||||
|  |     'William' : ['Min', 'Noam'], | ||||||
|  |     'Jayden'  : ['Min', 'Amelia', 'Ren', 'Noam'], | ||||||
|  |     'Ren'     : ['Jayden', 'Omar'], | ||||||
|  |     'Amelia'  : ['Jayden', 'Adam', 'Miguel'], | ||||||
|  |     'Adam'    : ['Amelia', 'Miguel', 'Sofia', 'Lucas'], | ||||||
|  |     'Miguel'  : ['Amelia', 'Adam', 'Liam', 'Nathan'], | ||||||
|  |     'Noam'    : ['Nathan', 'Jayden', 'William'], | ||||||
|  |     'Omar'    : ['Ren', 'Min', 'Scott'], | ||||||
|  |     'Liam'    : ['Ren'], | ||||||
|  |     'Nathan'  : ['Noam'], | ||||||
|  |     'Scott'   : [], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | result = shortest_path('Jayden', 'Adam', graph) | ||||||
|  | print(result) | ||||||
|  | assert result == ['Jayden', 'Amelia', 'Adam'] | ||||||
|  | print('Success!') | ||||||
|  | 
 | ||||||
|  | beg = random.choice(list(graph.keys())) | ||||||
|  | end = random.choice(list(graph.keys())) | ||||||
|  | print("Attempting to find the shortest path between {} and {}".format(beg, end)) | ||||||
|  | print(shortest_path(beg, end, graph)) | ||||||
							
								
								
									
										71
									
								
								scratch/facebook/mst.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								scratch/facebook/mst.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | ||||||
|  | from heapq import heappush, heappop | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | def to_vertex_list(graph): | ||||||
|  |     result = {} | ||||||
|  |     for a, b, kg in graph: | ||||||
|  |         if a in result: | ||||||
|  |             result[a].append((b, kg)) | ||||||
|  |         else: | ||||||
|  |             result[a] = [(b, kg)] | ||||||
|  |         if b in result: | ||||||
|  |             result[b].append((a, kg)) | ||||||
|  |         else: | ||||||
|  |             result[b] = [(a, kg)] | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def mst(graph): | ||||||
|  |     graph = to_vertex_list(graph) | ||||||
|  |     beg = random.choice(list(graph.keys())) | ||||||
|  |     h = [] | ||||||
|  |     result = [] | ||||||
|  |     seen = set() | ||||||
|  |     for c, kg in graph[beg]: | ||||||
|  |         heappush(h, (kg, beg, c)) | ||||||
|  |     while h: | ||||||
|  |         kg, beg, end = heappop(h) | ||||||
|  |         # detect cycles | ||||||
|  |         if end in seen: | ||||||
|  |             continue | ||||||
|  |         # use the edge | ||||||
|  |         seen.add(beg) | ||||||
|  |         seen.add(end) | ||||||
|  |         result.append((beg, end)) | ||||||
|  |         for c, kg in graph[end]: | ||||||
|  |             heappush(h, (kg, end, c)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | graphs = [ | ||||||
|  |     [ | ||||||
|  |         ('A', 'B', 7), | ||||||
|  |         ('A', 'D', 5), | ||||||
|  |         ('B', 'D', 9), | ||||||
|  |         ('E', 'D', 15), | ||||||
|  |         ('F', 'D', 6), | ||||||
|  |         ('F', 'G', 11), | ||||||
|  |         ('F', 'E', 8), | ||||||
|  |         ('G', 'E', 9), | ||||||
|  |         ('C', 'E', 5), | ||||||
|  |         ('B', 'E', 7), | ||||||
|  |         ('B', 'C', 8), | ||||||
|  |     ], | ||||||
|  |     [ | ||||||
|  |         ('A', 'B', 4), | ||||||
|  |         ('A', 'C', 8), | ||||||
|  |         ('B', 'C', 11), | ||||||
|  |         ('B', 'E', 8), | ||||||
|  |         ('C', 'D', 7), | ||||||
|  |         ('C', 'F', 1), | ||||||
|  |         ('D', 'E', 2), | ||||||
|  |         ('D', 'F', 6), | ||||||
|  |         ('E', 'G', 7), | ||||||
|  |         ('E', 'H', 4), | ||||||
|  |         ('F', 'H', 2), | ||||||
|  |         ('G', 'H', 14), | ||||||
|  |         ('G', 'I', 9), | ||||||
|  |         ('H', 'I', 10), | ||||||
|  |     ], | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | for graph in graphs: | ||||||
|  |     print(mst(graph)) | ||||||
							
								
								
									
										38
									
								
								scratch/facebook/node.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								scratch/facebook/node.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | class Node(object): | ||||||
|  |     def __init__(self, value, left=None, right=None): | ||||||
|  |         self.value = value | ||||||
|  |         self.left = left | ||||||
|  |         self.right = right | ||||||
|  | 
 | ||||||
|  |     def insert_left(self, value): | ||||||
|  |         self.left = Node(value) | ||||||
|  |         return self.left | ||||||
|  | 
 | ||||||
|  |     def insert_right(self, value): | ||||||
|  |         self.right = Node(value) | ||||||
|  |         return self.right | ||||||
|  | 
 | ||||||
|  | tree = Node( | ||||||
|  |     50, | ||||||
|  |     Node( | ||||||
|  |         17, | ||||||
|  |         Node( | ||||||
|  |             12, | ||||||
|  |             Node(9), | ||||||
|  |             Node(14), | ||||||
|  |         ), | ||||||
|  |         Node( | ||||||
|  |             23, | ||||||
|  |             Node(19), | ||||||
|  |         ), | ||||||
|  |     ), | ||||||
|  |     Node( | ||||||
|  |         72, | ||||||
|  |         Node( | ||||||
|  |             54, | ||||||
|  |             None, | ||||||
|  |             Node(67) | ||||||
|  |         ), | ||||||
|  |         Node(76), | ||||||
|  |     ), | ||||||
|  | ) | ||||||
							
								
								
									
										13
									
								
								scratch/facebook/nth-fibonacci.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								scratch/facebook/nth-fibonacci.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | # 0, 1, 1, 2, 3, 5 | ||||||
|  | def fib(n): | ||||||
|  |     if n < 0: | ||||||
|  |         raise Exception("Need to supply an index that's >= 0. Not: {}".format(n)) | ||||||
|  |     elif n in {0, 1}: | ||||||
|  |         return n | ||||||
|  |     state = [0, 1] | ||||||
|  |     for i in range(1, n): | ||||||
|  |         state[0], state[1] = state[1], state[0] + state[1] | ||||||
|  |     return state[-1] | ||||||
|  | 
 | ||||||
|  | for i in range(10): | ||||||
|  |     print("fib({}) => {}".format(i, fib(i))) | ||||||
							
								
								
									
										22
									
								
								scratch/facebook/onsite.txt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								scratch/facebook/onsite.txt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | ** Behavior Interview ** | ||||||
|  | - Can I work in an unstructured environment? | ||||||
|  | - Do I have a growth mindset? | ||||||
|  | - How do I handle conflict? | ||||||
|  | - Am I empathic? | ||||||
|  | - Am I a self-starter? | ||||||
|  | - What is my communication style? | ||||||
|  | - Do I persevere? | ||||||
|  | - <forgot to write this one down> | ||||||
|  | 
 | ||||||
|  | ** Design Interview ** | ||||||
|  | - requirement gathering, problem exploring | ||||||
|  | - component analysis | ||||||
|  | - quantitative analysis | ||||||
|  | - trade-offs | ||||||
|  | - bottlenecks, weaknesses | ||||||
|  | - securing data (e.g. PII) | ||||||
|  | 
 | ||||||
|  | Consider: | ||||||
|  | - pagination | ||||||
|  | - push/pull requests | ||||||
|  | - API design | ||||||
							
								
								
									
										121
									
								
								scratch/facebook/parsing/json.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								scratch/facebook/parsing/json.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,121 @@ | ||||||
|  | from parser import Parser | ||||||
|  | 
 | ||||||
|  | # As an exercise to stress-test my understanding of recursive descent parsers, | ||||||
|  | # I'm attempting to write a JSON parser without referencing any existing BNF | ||||||
|  | # descriptions of JSON or existing JSON parser implementations. | ||||||
|  | # | ||||||
|  | # I'm only parsing a subset of JSON: enough to parse `sample`. Here is the BNF | ||||||
|  | # that I wrote to describe my expected input: | ||||||
|  | # | ||||||
|  | # expression -> object | ||||||
|  | # object     -> '{' ( STRING ':' expression ) ( ',' STRING ':' expression )* '}' | ||||||
|  | #            |  array | ||||||
|  | # array      -> '[' expression ( ',' expression )* ']' | ||||||
|  | #            |  literal | ||||||
|  | # literal    -> STRING | INT | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     """ | ||||||
|  |     Return a list of tokens from the string input, `xs`. | ||||||
|  |     """ | ||||||
|  |     result = [] | ||||||
|  |     i = 0 | ||||||
|  |     while i < len(xs): | ||||||
|  |         # single characters | ||||||
|  |         if xs[i] in ",{}:[]": | ||||||
|  |             result.append(xs[i]) | ||||||
|  |             i += 1 | ||||||
|  |         # strings | ||||||
|  |         elif xs[i] == "\"": | ||||||
|  |             curr = xs[i] | ||||||
|  |             i += 1 | ||||||
|  |             while xs[i] != "\"": | ||||||
|  |                 curr += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             curr += xs[i] | ||||||
|  |             result.append(curr) | ||||||
|  |             i += 1 | ||||||
|  |         # integers | ||||||
|  |         elif xs[i] in "0123456789": | ||||||
|  |             curr = xs[i] | ||||||
|  |             i += 1 | ||||||
|  |             while xs[i] in "0123456789": | ||||||
|  |                 curr += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             result.append(int(curr)) | ||||||
|  |         # whitespace | ||||||
|  |         elif xs[i] in {" ", "\n"}: | ||||||
|  |             i += 1 | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def parse_json(x): | ||||||
|  |     """ | ||||||
|  |     Attempt to parse the string, `x`, into JSON. | ||||||
|  |     """ | ||||||
|  |     tokens = tokenize(x) | ||||||
|  |     return parse_object(Parser(tokens)) | ||||||
|  | 
 | ||||||
|  | def parse_object(parser): | ||||||
|  |     if parser.match(['{']): | ||||||
|  |         key = parse_string(parser) | ||||||
|  |         parser.expect([':']) | ||||||
|  |         value = parse_object(parser) | ||||||
|  |         result = [(key, value)] | ||||||
|  |         while parser.match([',']): | ||||||
|  |             key = parse_string(parser) | ||||||
|  |             parser.match([':']) | ||||||
|  |             value = parse_object(parser) | ||||||
|  |             result.append((key, value)) | ||||||
|  |         return result | ||||||
|  |     return parse_array(parser) | ||||||
|  | 
 | ||||||
|  | def parse_array(parser): | ||||||
|  |     if parser.match(['[']): | ||||||
|  |         if parser.match([']']): | ||||||
|  |             return [] | ||||||
|  |         result = [parse_object(parser)] | ||||||
|  |         while parser.match([',']): | ||||||
|  |             result.append(parse_object(parser)) | ||||||
|  |         parser.expect([']']) | ||||||
|  |         return result | ||||||
|  |     else: | ||||||
|  |         return parse_literal(parser) | ||||||
|  | 
 | ||||||
|  | def parse_string(parser): | ||||||
|  |     if parser.curr().startswith("\""): | ||||||
|  |         return parser.consume() | ||||||
|  |     else: | ||||||
|  |         raise Exception("Unexpected token: {}".format(parser.curr())) | ||||||
|  | 
 | ||||||
|  | def parse_literal(parser): | ||||||
|  |     return parser.consume() | ||||||
|  | 
 | ||||||
|  | sample = """ | ||||||
|  | { | ||||||
|  |   "glossary": { | ||||||
|  |     "title": "example glossary", | ||||||
|  |     "GlossDiv": { | ||||||
|  |       "title": "S", | ||||||
|  |       "GlossList": { | ||||||
|  |         "GlossEntry": { | ||||||
|  |           "ID": "SGML", | ||||||
|  |           "SortAs": "SGML", | ||||||
|  |           "GlossTerm": "Standard Generalized Markup Language", | ||||||
|  |           "Acronym": "SGML", | ||||||
|  |           "Abbrev": "ISO 8879:1986", | ||||||
|  |           "GlossDef": { | ||||||
|  |             "para": "A meta-markup language, used to create markup languages such as DocBook.", | ||||||
|  |             "GlossSeeAlso": [ | ||||||
|  |               "GML", | ||||||
|  |               "XML" | ||||||
|  |             ] | ||||||
|  |           }, | ||||||
|  |           "GlossSee": "markup" | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | """ | ||||||
|  | 
 | ||||||
|  | print(parse_json(sample)) | ||||||
							
								
								
									
										28
									
								
								scratch/facebook/parsing/parser.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								scratch/facebook/parsing/parser.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,28 @@ | ||||||
|  | class Parser(object): | ||||||
|  |     def __init__(self, tokens): | ||||||
|  |         self.tokens = tokens | ||||||
|  |         self.i = 0 | ||||||
|  | 
 | ||||||
|  |     def prev(self): | ||||||
|  |         return self.tokens[self.i - 1] | ||||||
|  | 
 | ||||||
|  |     def curr(self): | ||||||
|  |         return self.tokens[self.i] | ||||||
|  | 
 | ||||||
|  |     def consume(self): | ||||||
|  |         if not self.exhausted(): | ||||||
|  |             self.i += 1 | ||||||
|  |             return self.prev() | ||||||
|  | 
 | ||||||
|  |     def match(self, xs): | ||||||
|  |         if not self.exhausted() and self.curr() in xs: | ||||||
|  |             self.consume() | ||||||
|  |             return True | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  |     def expect(self, xs): | ||||||
|  |         if not self.match(xs): | ||||||
|  |             raise Exception("Expected token \"{}\" but received \"{}\"".format(xs, self.curr())) | ||||||
|  | 
 | ||||||
|  |     def exhausted(self): | ||||||
|  |         return self.i >= len(self.tokens) | ||||||
							
								
								
									
										174
									
								
								scratch/facebook/parsing/regex.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								scratch/facebook/parsing/regex.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,174 @@ | ||||||
|  | # Writing a small proof-of-concept... | ||||||
|  | #   - lexer | ||||||
|  | #   - parser | ||||||
|  | #   - compiler | ||||||
|  | # ...for regex. | ||||||
|  | 
 | ||||||
|  | from parser import Parser | ||||||
|  | import string | ||||||
|  | 
 | ||||||
|  | ################################################################################ | ||||||
|  | # Top-Level API | ||||||
|  | ################################################################################ | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     """ | ||||||
|  |     Transform `xs` into a list of tokens. | ||||||
|  | 
 | ||||||
|  |     Also: expand shorthand symbols using the following table: | ||||||
|  |       - ? -> {0,1} | ||||||
|  |       - * -> {0,} | ||||||
|  |       - + -> {1,} | ||||||
|  |     """ | ||||||
|  |     result = [] | ||||||
|  |     i = 0 | ||||||
|  |     shorthand = { | ||||||
|  |         "?": ["{", 0, ",", 1, "}"], | ||||||
|  |         "*": ["{", 0, ",", "}"], | ||||||
|  |         "+": ["{", 1, ",", "}"], | ||||||
|  |     } | ||||||
|  |     while i < len(xs): | ||||||
|  |         if xs[i] in shorthand: | ||||||
|  |             for c in shorthand[xs[i]]: | ||||||
|  |                 result.append(c) | ||||||
|  |             i += 1 | ||||||
|  |         elif xs[i] == "{": | ||||||
|  |             result.append(xs[i]) | ||||||
|  |             i += 1 | ||||||
|  |             curr = "" | ||||||
|  |             while xs[i] in string.digits: | ||||||
|  |                 curr += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             result.append(int(curr)) | ||||||
|  |             assert xs[i] == "," | ||||||
|  |             result.append(",") | ||||||
|  |             i += 1 | ||||||
|  |             curr = "" | ||||||
|  |             while xs[i] in string.digits: | ||||||
|  |                 curr += xs[i] | ||||||
|  |                 i += 1 | ||||||
|  |             result.append(int(curr)) | ||||||
|  |         else: | ||||||
|  |             result.append(xs[i]) | ||||||
|  |             i += 1 | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def parse(expr): | ||||||
|  |     """ | ||||||
|  |     Tokenize `expr` and convert it into a parse-tree. | ||||||
|  |     """ | ||||||
|  |     tokens = tokenize(expr) | ||||||
|  |     return parse_tokens(tokens) | ||||||
|  | 
 | ||||||
|  | def compile(xs): | ||||||
|  |     """ | ||||||
|  |     Transform `xs`, a parse-tree representing a regex, into a function that | ||||||
|  |     accepts a string, and returns the substring that the regex matches. | ||||||
|  |     """ | ||||||
|  |     def fn(input): | ||||||
|  |         match = "" | ||||||
|  |         i = 0 | ||||||
|  |         for x in xs: | ||||||
|  |             matches, q = x[1], x[2] | ||||||
|  |             lo, hi = q[1], q[2] | ||||||
|  |             for j in range(lo): | ||||||
|  |                 if i < len(input) and input[i] in matches: | ||||||
|  |                     match += input[i] | ||||||
|  |                     i += 1 | ||||||
|  |                 else: | ||||||
|  |                     print("Failed to match {} with {}".format(input[i], matches)) | ||||||
|  |                     return None | ||||||
|  |             if hi == float('inf'): | ||||||
|  |                 while i < len(input) and input[i] in matches: | ||||||
|  |                     match += input[i] | ||||||
|  |                     i += 1 | ||||||
|  |             else: | ||||||
|  |                 for j in range(hi - lo): | ||||||
|  |                     if i < len(input) and input[i] in matches: | ||||||
|  |                         match += input[i] | ||||||
|  |                         i += 1 | ||||||
|  |         return match | ||||||
|  |     return fn | ||||||
|  | 
 | ||||||
|  | ################################################################################ | ||||||
|  | # Helper Functions | ||||||
|  | ################################################################################ | ||||||
|  | 
 | ||||||
|  | def parse_tokens(tokens): | ||||||
|  |     result = [] | ||||||
|  |     parser = Parser(tokens) | ||||||
|  |     while not parser.exhausted(): | ||||||
|  |         result.append(parse_expression(parser)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def parse_expression(parser): | ||||||
|  |     if parser.curr() == "[": | ||||||
|  |         return parse_character_class(parser) | ||||||
|  |     else: | ||||||
|  |         return parse_character(parser) | ||||||
|  | 
 | ||||||
|  | def parse_character_class(parser): | ||||||
|  |     parser.expect("[") | ||||||
|  |     beg = parser.consume() | ||||||
|  |     parser.expect("-") | ||||||
|  |     end = parser.consume() | ||||||
|  |     parser.expect("]") | ||||||
|  |     if parser.curr() == "{": | ||||||
|  |         q = parse_quantifier(parser) | ||||||
|  |     return char_class(xs=expand_range(beg, end), q=q) | ||||||
|  | 
 | ||||||
|  | def parse_quantifier(parser): | ||||||
|  |     parser.expect("{") | ||||||
|  |     if parser.match([","]): | ||||||
|  |         end = parser.consume() | ||||||
|  |         parser.expect("}") | ||||||
|  |         return quantifier(beg=0, end=end) | ||||||
|  |     else: | ||||||
|  |         beg = parser.consume() | ||||||
|  |         parser.expect(",") | ||||||
|  |         if parser.match(["}"]): | ||||||
|  |             return quantifier(beg=beg) | ||||||
|  |         else: | ||||||
|  |             end = parser.consume() | ||||||
|  |             parser.expect("}") | ||||||
|  |             return quantifier(beg=beg, end=end) | ||||||
|  | 
 | ||||||
|  | def parse_character(parser): | ||||||
|  |     c = parser.consume() | ||||||
|  |     q = None | ||||||
|  |     if parser.curr() == "{": | ||||||
|  |         q = parse_quantifier(parser) | ||||||
|  |     return char_class(xs={c}, q=q) | ||||||
|  | 
 | ||||||
|  | def char_class(xs=set(), q=None): | ||||||
|  |     if not q: | ||||||
|  |         q = quantifier(beg=1, end=1) | ||||||
|  |     return ["CHARACTER_CLASS", xs, q] | ||||||
|  | 
 | ||||||
|  | def expand_range(beg, end): | ||||||
|  |     # TODO: Implement this | ||||||
|  |     return {string.printable[i] | ||||||
|  |             for i in range(string.printable.index(beg), | ||||||
|  |                            string.printable.index(end) + 1)} | ||||||
|  | 
 | ||||||
|  | def quantifier(beg=0, end=float('inf')): | ||||||
|  |     return ['QUANTIFIER', beg, end] | ||||||
|  | 
 | ||||||
|  | ################################################################################ | ||||||
|  | # Tests | ||||||
|  | ################################################################################ | ||||||
|  | 
 | ||||||
|  | xs = [ | ||||||
|  |     ("[a-c]*[0-9]{2,3}", ["dog"]), | ||||||
|  |     ("ca+t?", ["cat", "caaaat", "ca", "dog"]), | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | for re, inputs in xs: | ||||||
|  |     print("Regex:  {}".format(re)) | ||||||
|  |     print("Tokens: {}".format(tokenize(re))) | ||||||
|  |     print("Parsed: {}".format(parse(re))) | ||||||
|  |     print("\nTESTS") | ||||||
|  |     for input in inputs: | ||||||
|  |         print("Attempting to match \"{}\"...".format(input)) | ||||||
|  |         parser = compile(parse(re)) | ||||||
|  |         print("Result: \"{}\"\n".format(parser(input))) | ||||||
							
								
								
									
										17
									
								
								scratch/facebook/permutation-palindrome.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								scratch/facebook/permutation-palindrome.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | from collections import Counter | ||||||
|  | 
 | ||||||
|  | def is_palindrome(x): | ||||||
|  |     return len([count for _, count in Counter(x).items() if count % 2 == 1]) <= 1 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | xs = [("civic", True), | ||||||
|  |       ("ivicc", True), | ||||||
|  |       ("civil", False), | ||||||
|  |       ("livci", False)] | ||||||
|  | 
 | ||||||
|  | for x, expected in xs: | ||||||
|  |     result = is_palindrome(x) | ||||||
|  |     print(x) | ||||||
|  |     print(result) | ||||||
|  |     assert result == expected | ||||||
|  |     print("Success!") | ||||||
							
								
								
									
										33
									
								
								scratch/facebook/product-of-all-other-numbers.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								scratch/facebook/product-of-all-other-numbers.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | ||||||
|  | from random import randint | ||||||
|  | from math import floor | ||||||
|  | 
 | ||||||
|  | # loop {forwards, backwards, up, down} | ||||||
|  | # through a table of values, [[a]]. | ||||||
|  | 
 | ||||||
|  | def product(xs): | ||||||
|  |     n = len(xs) | ||||||
|  |     lhs = [1] * (n + 1) | ||||||
|  |     for i in range(1, n): | ||||||
|  |         lhs[i] = lhs[i - 1] * xs[i - 1] | ||||||
|  |     rhs = [1] * (n + 1) | ||||||
|  |     for i in range(n - 1, 0, -1): | ||||||
|  |         rhs[i] = rhs[i + 1] * xs[i] | ||||||
|  |     result = [] | ||||||
|  |     for i in range(n): | ||||||
|  |         result.append(lhs[i] * rhs[i + 1]) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def computed_expected(xs): | ||||||
|  |     product = 1 | ||||||
|  |     for x in xs: | ||||||
|  |         product *= x | ||||||
|  |     return [floor(product / x) for x in xs] | ||||||
|  | 
 | ||||||
|  | xs = [randint(1, 10) for _ in range(5)] | ||||||
|  | expected = computed_expected(xs) | ||||||
|  | result = product(xs) | ||||||
|  | print(xs, result, expected) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
|  | 
 | ||||||
|  | print(product([2, 4, 3, 10, 5])) | ||||||
							
								
								
									
										20
									
								
								scratch/facebook/queue-two-stacks.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								scratch/facebook/queue-two-stacks.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | from stack import Stack | ||||||
|  | 
 | ||||||
|  | class Queue(object): | ||||||
|  |     def __init__(self): | ||||||
|  |         self.lhs = Stack() | ||||||
|  |         self.rhs = Stack() | ||||||
|  | 
 | ||||||
|  |     def enqueue(self, x): | ||||||
|  |         self.rhs.push(x) | ||||||
|  | 
 | ||||||
|  |     def dequeue(self, x): | ||||||
|  |         y = self.rhs.pop() | ||||||
|  |         while y: | ||||||
|  |             self.lhs.push(y) | ||||||
|  |             y = self.rhs.pop() | ||||||
|  |         result = self.lhs.pop() | ||||||
|  |         y = self.lhs.pop() | ||||||
|  |         while y: | ||||||
|  |             self.rhs.push(y) | ||||||
|  |         return result | ||||||
|  | @ -0,0 +1,33 @@ | ||||||
|  | from math import floor | ||||||
|  | 
 | ||||||
|  | def find_magic_index_brute(xs): | ||||||
|  |     for i in range(len(xs)): | ||||||
|  |         if xs[i] == i: | ||||||
|  |             return i | ||||||
|  |     return -1 | ||||||
|  | 
 | ||||||
|  | def mid(lo, hi): | ||||||
|  |     return lo + floor((hi - lo) / 2) | ||||||
|  | 
 | ||||||
|  | def find_magic_index(xs): | ||||||
|  |     lo, hi = 0, len(xs) - 1 | ||||||
|  |     return do_find_magic_index(xs, 0, len(xs) - 1) | ||||||
|  | 
 | ||||||
|  | def do_find_magic_index(xs, lo, hi): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | xss = [ | ||||||
|  |     [], | ||||||
|  |     [-1,0,2,4,5,6], | ||||||
|  |     [1,1,1,1,1,5], | ||||||
|  |     [-2,-2,-2,-2,4], | ||||||
|  |     [1,2,3,4,5], | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | for xs in xss: | ||||||
|  |     print(xs) | ||||||
|  |     a = find_magic_index_brute(xs) | ||||||
|  |     b = find_magic_index(xs) | ||||||
|  |     print(a, b) | ||||||
|  |     assert a == b | ||||||
|  |     print("Success!") | ||||||
|  | @ -0,0 +1,56 @@ | ||||||
|  | # Given an infinite supply of: | ||||||
|  | #   - quarters | ||||||
|  | #   - dimes | ||||||
|  | #   - nickels | ||||||
|  | #   - pennies | ||||||
|  | # Write a function to count the number of ways to make change of n. | ||||||
|  | 
 | ||||||
|  | def get(table, row, col): | ||||||
|  |     """ | ||||||
|  |     Defensively get cell `row`, `col` from `table`. | ||||||
|  |     """ | ||||||
|  |     if row < 0 or row >= len(table): | ||||||
|  |         return 0 | ||||||
|  |     if col < 0 or col >= len(table[0]): | ||||||
|  |         return 0 | ||||||
|  |     return table[row][col] | ||||||
|  | 
 | ||||||
|  | def print_table(table): | ||||||
|  |     print('\n'.join([ | ||||||
|  |         ','.join([str(col) for col in table[row]]) | ||||||
|  |         for row in range(len(table))])) | ||||||
|  | 
 | ||||||
|  | def init_table(rows=0, cols=0, default=0): | ||||||
|  |     result = [] | ||||||
|  |     for row in range(rows): | ||||||
|  |         r = [] | ||||||
|  |         for col in range(cols): | ||||||
|  |             r.append(default) | ||||||
|  |         result.append(r) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def make_change(n): | ||||||
|  |     coins = [1, 5, 10, 25] | ||||||
|  |     table = init_table(rows=len(coins), cols=n) | ||||||
|  | 
 | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             curr_coin = coins[row] | ||||||
|  |             curr_n = col + 1 | ||||||
|  |             # a | ||||||
|  |             a = get(table, row - 1, col) | ||||||
|  |             # b | ||||||
|  |             b = get(table, row, curr_n - curr_coin - 1) | ||||||
|  |             # c | ||||||
|  |             c = 1 if curr_coin <= curr_n else 0 | ||||||
|  |             # commit | ||||||
|  |             if curr_coin == curr_n: | ||||||
|  |                 table[row][col] = a + c | ||||||
|  |             else: | ||||||
|  |                 table[row][col] = a + b * c | ||||||
|  |             # debug | ||||||
|  |             print_table(table) | ||||||
|  |             print() | ||||||
|  |     return table[-1][-1] | ||||||
|  | 
 | ||||||
|  | print(make_change(7)) | ||||||
|  | @ -0,0 +1,36 @@ | ||||||
|  | from collection import deque | ||||||
|  | 
 | ||||||
|  | def fill(point, canvas, color): | ||||||
|  |     if x not in canvas: | ||||||
|  |         return | ||||||
|  |     elif y not in canvas[x]: | ||||||
|  |         return | ||||||
|  | 
 | ||||||
|  |     x, y = point | ||||||
|  |     if canvas[y][x] == color: | ||||||
|  |         return | ||||||
|  |     canvas[y][x] = color | ||||||
|  |     fill((x + 1, y), canvas, color) | ||||||
|  |     fill((x - 1, y), canvas, color) | ||||||
|  |     fill((x, y + 1), canvas, color) | ||||||
|  |     fill((x, y - 1), canvas, color) | ||||||
|  | 
 | ||||||
|  | def fill_bfs(point, canvas, color): | ||||||
|  |     x, y = point | ||||||
|  |     if x not in canvas: | ||||||
|  |         return None | ||||||
|  |     if y not in canvas[x]: | ||||||
|  |         return None | ||||||
|  |     xs = deque() | ||||||
|  |     xs.append((x, y)) | ||||||
|  |     while xs: | ||||||
|  |         x, y = xs.popleft() | ||||||
|  |         canvas[y][x] = color | ||||||
|  |         for x2, y2 in [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]: | ||||||
|  |             if x2 not in canvas: | ||||||
|  |                 continue | ||||||
|  |             elif y2 not in canvas[x2]: | ||||||
|  |                 continue | ||||||
|  |             if canvas[y2][x2] != color: | ||||||
|  |                 xs.append((x2, y2)) | ||||||
|  |     return None | ||||||
|  | @ -0,0 +1,114 @@ | ||||||
|  | # BNF | ||||||
|  | # expression -> bool ( ( '|' | '&' | '^' ) bool )* | ||||||
|  | # bool       -> '0' | '1' | ||||||
|  | 
 | ||||||
|  | def tokenize(xs): | ||||||
|  |     result = [] | ||||||
|  |     for c in xs: | ||||||
|  |         if c == '0': | ||||||
|  |             result.append(0) | ||||||
|  |         elif c == '1': | ||||||
|  |             result.append(1) | ||||||
|  |         elif c in "&|^": | ||||||
|  |             result.append(c) | ||||||
|  |         else: | ||||||
|  |             raise Exception("Unexpected token, \"{}\"".format(c)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | class Parser(object): | ||||||
|  |     def __init__(self, tokens): | ||||||
|  |         self.tokens = tokens | ||||||
|  |         self.i = 0 | ||||||
|  | 
 | ||||||
|  |     def prev(self): | ||||||
|  |         return self.tokens[self.i - 1] | ||||||
|  | 
 | ||||||
|  |     def curr(self): | ||||||
|  |         return self.tokens[self.i] | ||||||
|  | 
 | ||||||
|  |     def match(self, xs): | ||||||
|  |         if self.exhausted(): | ||||||
|  |             return False | ||||||
|  |         if (self.curr() in xs): | ||||||
|  |             self.consume() | ||||||
|  |             return True | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  |     def consume(self): | ||||||
|  |         result = self.curr() | ||||||
|  |         self.i += 1 | ||||||
|  |         return result | ||||||
|  | 
 | ||||||
|  |     def exhausted(self): | ||||||
|  |         return self.i >= len(self.tokens) | ||||||
|  | 
 | ||||||
|  | def recursive_descent(tokens): | ||||||
|  |     parser = Parser(tokens) | ||||||
|  |     return parse_expression(parser) | ||||||
|  | 
 | ||||||
|  | def parse_expression(parser): | ||||||
|  |     lhs = parse_bool(parser) | ||||||
|  |     while parser.match(['|', '&', '^']): | ||||||
|  |         op = parser.prev() | ||||||
|  |         rhs = parse_expression(parser) | ||||||
|  |         lhs = [op, lhs, rhs] | ||||||
|  |     return lhs | ||||||
|  | 
 | ||||||
|  | def parse_bool(parser): | ||||||
|  |     if parser.curr() == 0: | ||||||
|  |         parser.consume() | ||||||
|  |         return False | ||||||
|  |     elif parser.curr() == 1: | ||||||
|  |         parser.consume() | ||||||
|  |         return True | ||||||
|  |     else: | ||||||
|  |         raise Exception("Unexpected token: {}".format(parser.curr())) | ||||||
|  | 
 | ||||||
|  | def f(expr, result): | ||||||
|  |     tokens = tokenize(expr) | ||||||
|  |     tree = recursive_descent(tokens) | ||||||
|  |     return do_f(tree, result) | ||||||
|  | 
 | ||||||
|  | def do_f(tree, result): | ||||||
|  |     if type(tree) == bool: | ||||||
|  |         if tree == result: | ||||||
|  |             return 1 | ||||||
|  |         else: | ||||||
|  |             return 0 | ||||||
|  | 
 | ||||||
|  |     op, lhs, rhs = tree[0], tree[1], tree[2] | ||||||
|  |     truth_tables = { | ||||||
|  |         True: { | ||||||
|  |             '|': [ | ||||||
|  |                 (True, True), | ||||||
|  |                 (True, False), | ||||||
|  |                 (False, True), | ||||||
|  |             ], | ||||||
|  |             '&': [ | ||||||
|  |                 (True, True), | ||||||
|  |             ], | ||||||
|  |             '^': [ | ||||||
|  |                 (True, False), | ||||||
|  |                 (False, True), | ||||||
|  |             ], | ||||||
|  |         }, | ||||||
|  |         False: { | ||||||
|  |             '|': [ | ||||||
|  |                 (False, False), | ||||||
|  |             ], | ||||||
|  |             '&': [ | ||||||
|  |                 (False, False), | ||||||
|  |                 (True, False), | ||||||
|  |                 (False, True), | ||||||
|  |             ], | ||||||
|  |             '^': [ | ||||||
|  |                 (True, True), | ||||||
|  |                 (False, False), | ||||||
|  |             ], | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return sum([do_f(lhs, x) * do_f(rhs, y) for x, y in truth_tables[result][op]]) | ||||||
|  | 
 | ||||||
|  | print(f("1^0|0|1", False)) | ||||||
|  | print(f("1|0|1|1", False)) | ||||||
|  | @ -0,0 +1,13 @@ | ||||||
|  | def char_and_rest(i, xs): | ||||||
|  |     return xs[i], xs[:i] + xs[i+1:] | ||||||
|  | 
 | ||||||
|  | # perms :: String -> [String] | ||||||
|  | def perms(xs): | ||||||
|  |     if len(xs) == 1: | ||||||
|  |         return [xs] | ||||||
|  |     result = [] | ||||||
|  |     for c, rest in [char_and_rest(i, xs) for i in range(len(xs))]: | ||||||
|  |         result += [c + perm for perm in perms(rest)] | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | print(perms("cat")) | ||||||
|  | @ -0,0 +1,28 @@ | ||||||
|  | import random | ||||||
|  | 
 | ||||||
|  | def factorial(n): | ||||||
|  |     result = 1 | ||||||
|  |     for i in range(1, n + 1): | ||||||
|  |         result *= i | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def travel(a, b): | ||||||
|  |     if a == b: | ||||||
|  |         return 1 | ||||||
|  | 
 | ||||||
|  |     ax, ay = a | ||||||
|  |     bx, by = b | ||||||
|  |     if ax > bx or ay > by: | ||||||
|  |         return 0 | ||||||
|  | 
 | ||||||
|  |     return sum([travel((ax + 1, ay), b), travel((ax, ay + 1), b)]) | ||||||
|  | 
 | ||||||
|  | def travel_compute(a, b): | ||||||
|  |     bx, by = b | ||||||
|  |     return int(factorial(bx + by) / (factorial(bx) * factorial(by))) | ||||||
|  | 
 | ||||||
|  | a = (0, 0) | ||||||
|  | b = (random.randint(1, 10), random.randint(1, 10)) | ||||||
|  | print("Travelling to {}, {}".format(b[0], b[1])) | ||||||
|  | print(travel(a, b)) | ||||||
|  | print(travel_compute(a, b)) | ||||||
|  | @ -0,0 +1 @@ | ||||||
|  | # accidentally deleted my solution... TBI (again) | ||||||
|  | @ -0,0 +1,41 @@ | ||||||
|  | # take-aways: | ||||||
|  | #   - Use integers as lists of boolean values | ||||||
|  | #   - Use 1 << n to compute 2^n where n = len(xs) | ||||||
|  | 
 | ||||||
|  | def set_from_int(xs, n): | ||||||
|  |     result = [] | ||||||
|  |     for i in range(len(xs)): | ||||||
|  |         if n & (1 << i) != 0: | ||||||
|  |             result.append(xs[i]) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # subsets :: Set a -> List (Set a) | ||||||
|  | def subsets(xs): | ||||||
|  |     n = len(xs) | ||||||
|  |     return [set_from_int(xs, i) for i in range(1 << n)] | ||||||
|  | 
 | ||||||
|  | #   0 1 2 | ||||||
|  | # 0 N Y Y | ||||||
|  | # 1 _ N Y | ||||||
|  | # 2 _ _ N | ||||||
|  | 
 | ||||||
|  | # For my interview, be able to compute *permutations* and *combinations* | ||||||
|  | 
 | ||||||
|  | # This differs from permutations because this is about finding combinations... | ||||||
|  | # | ||||||
|  | # bottom-up | ||||||
|  | # 0 =>        { } | ||||||
|  | # 1 =>  {3}   {4}   {3} | ||||||
|  | # 2 => {5,4} {5,3} {4,3} | ||||||
|  | 
 | ||||||
|  | xs = [ | ||||||
|  |     ([], [[]]), | ||||||
|  |     ([5], [[], [5]]), | ||||||
|  |     ([5,4], [[],[5],[4],[5,4]]), | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | for x, expected in xs: | ||||||
|  |     result = subsets(x) | ||||||
|  |     print("subsets({}) => {} == {}".format(x, result, expected)) | ||||||
|  |     assert result == expected | ||||||
|  |     print("Success!") | ||||||
|  | @ -0,0 +1,50 @@ | ||||||
|  | def valid_parens(n): | ||||||
|  |     if n == 0: | ||||||
|  |         return [] | ||||||
|  |     if n == 1: | ||||||
|  |         return ["()"] | ||||||
|  | 
 | ||||||
|  |     result = set() | ||||||
|  |     for x in valid_parens(n - 1): | ||||||
|  |         result.add("({})".format(x)) | ||||||
|  |         result.add("(){}".format(x)) | ||||||
|  |         result.add("{}()".format(x)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def valid_parens_efficient(n): | ||||||
|  |     result = [] | ||||||
|  |     curr = [''] * n**2 | ||||||
|  |     do_valid_parens_efficient(result, curr, 0, n, n) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | def do_valid_parens_efficient(result, curr, i, lhs, rhs): | ||||||
|  |     if lhs == 0 and rhs == 0: | ||||||
|  |         result.append(''.join(curr)) | ||||||
|  |     else: | ||||||
|  |         if lhs > 0: | ||||||
|  |             curr[i] = '(' | ||||||
|  |             do_valid_parens_efficient(result, curr, i + 1, lhs - 1, rhs) | ||||||
|  |         if rhs > lhs: | ||||||
|  |             curr[i] = ')' | ||||||
|  |             do_valid_parens_efficient(result, curr, i + 1, lhs, rhs - 1) | ||||||
|  | 
 | ||||||
|  | # Avoids recursion by using either a stack or a queue. I think this version is | ||||||
|  | # easier to understand. | ||||||
|  | def valid_parens_efficient_2(n): | ||||||
|  |     result = [] | ||||||
|  |     xs = [] | ||||||
|  |     xs.append(('', n, n)) | ||||||
|  |     while xs: | ||||||
|  |         curr, lhs, rhs = xs.pop() | ||||||
|  |         print(curr) | ||||||
|  |         if lhs == 0 and rhs == 0: | ||||||
|  |             result.append(''.join(curr)) | ||||||
|  |         if lhs > 0: | ||||||
|  |             xs.append((curr + '(', lhs - 1, rhs)) | ||||||
|  |         if rhs > lhs: | ||||||
|  |             xs.append((curr + ')', lhs, rhs - 1)) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # print(valid_parens(4)) | ||||||
|  | print(valid_parens_efficient(3)) | ||||||
|  | print(valid_parens_efficient_2(3)) | ||||||
							
								
								
									
										19
									
								
								scratch/facebook/recursive-string-permutations.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scratch/facebook/recursive-string-permutations.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | # permutations: no repeat characters | ||||||
|  | 
 | ||||||
|  | def char_and_rest(i, xs): | ||||||
|  |     return xs[i], xs[0:i] + xs[i + 1:] | ||||||
|  | 
 | ||||||
|  | def permutations(xs): | ||||||
|  |     if len(xs) == 1: | ||||||
|  |         return [xs] | ||||||
|  |     result = [] | ||||||
|  |     for c, rest in [char_and_rest(i, xs) for i in range(len(xs))]: | ||||||
|  |         result += [c + perm for perm in permutations(rest)] | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | expected = ["cat", "cta", "act", "atc", "tca", "tac"] | ||||||
|  | result = permutations("cat") | ||||||
|  | print(result, expected) | ||||||
|  | assert len(result) == len(expected) | ||||||
|  | assert result == expected | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										25
									
								
								scratch/facebook/reverse-linked-list.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								scratch/facebook/reverse-linked-list.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | from linked_list import Node | ||||||
|  | 
 | ||||||
|  | def reverse(node): | ||||||
|  |     prev, curr, next = None, node, node.next | ||||||
|  | 
 | ||||||
|  |     while curr: | ||||||
|  |         curr.next = prev | ||||||
|  |         prev = curr | ||||||
|  |         curr = next | ||||||
|  |         next = curr.next if curr else None | ||||||
|  |     return prev | ||||||
|  | 
 | ||||||
|  | one = Node(1) | ||||||
|  | two = Node(2) | ||||||
|  | three = Node(3) | ||||||
|  | one.next = two | ||||||
|  | two.next = three | ||||||
|  | 
 | ||||||
|  | print(one) | ||||||
|  | result = reverse(one) | ||||||
|  | print(result) | ||||||
|  | assert all([result == three, | ||||||
|  |             three.next == two, | ||||||
|  |             two.next == one]) | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										14
									
								
								scratch/facebook/reverse-string-in-place.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								scratch/facebook/reverse-string-in-place.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | ||||||
|  | # reverse :: [Char] -> () | ||||||
|  | def reverse(xs): | ||||||
|  |     i = 0 | ||||||
|  |     j = len(xs) - 1 | ||||||
|  |     while i < j: | ||||||
|  |         xs[i], xs[j] = xs[j], xs[i] | ||||||
|  |         i += 1 | ||||||
|  |         j -= 1 | ||||||
|  | 
 | ||||||
|  | xs = [list("testing"), list("a"), list("to")] | ||||||
|  | for x in xs: | ||||||
|  |     print(x) | ||||||
|  |     reverse(x) | ||||||
|  |     print(x) | ||||||
							
								
								
									
										8
									
								
								scratch/facebook/reverse-words.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								scratch/facebook/reverse-words.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | # reverse_word :: [Char] -> () | ||||||
|  | def reverse_words(x): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | x = list("This is a test") | ||||||
|  | print(''.join(x)) | ||||||
|  | reverse_words(x) | ||||||
|  | print(''.join(result)) | ||||||
							
								
								
									
										94
									
								
								scratch/facebook/scratch.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								scratch/facebook/scratch.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,94 @@ | ||||||
|  | # This is a scratch pad for randomly selected questions | ||||||
|  | 
 | ||||||
|  | # def char_and_rest(i, xs): | ||||||
|  | #     return xs[i], xs[:i] + xs[i+1:] | ||||||
|  | 
 | ||||||
|  | # def perms(xs): | ||||||
|  | #     if len(xs) == 1: | ||||||
|  | #         return [xs] | ||||||
|  | #     result = [] | ||||||
|  | #     for i in range(len(xs)): | ||||||
|  | #         c, rest = char_and_rest(i, xs) | ||||||
|  | #         for perm in perms(rest): | ||||||
|  | #             result.append(c + ''.join(perm)) | ||||||
|  | #     return result | ||||||
|  | 
 | ||||||
|  | # print(perms(list("woah"))) | ||||||
|  | 
 | ||||||
|  | # def f(take_out, dine_in, served): | ||||||
|  | #     j, k = 0, 0 | ||||||
|  | #     for i in range(len(served)): | ||||||
|  | #         if j < len(take_out) and served[i] == take_out[j]: | ||||||
|  | #             j += 1 | ||||||
|  | #         elif k < len(dine_in) and served[i] == dine_in[k]: | ||||||
|  | #             k += 1 | ||||||
|  | #         else: | ||||||
|  | #             return False | ||||||
|  | #     if j < len(take_out) or k < len(dine_in): | ||||||
|  | #         return False | ||||||
|  | #     return True | ||||||
|  | 
 | ||||||
|  | # take_out = [17, 8, 24] | ||||||
|  | # dine_in = [12, 19, 2] | ||||||
|  | # served = [17, 8, 12, 19, 24, 2] | ||||||
|  | # print(f(take_out, dine_in, served)) | ||||||
|  | 
 | ||||||
|  | # def match(a, b): | ||||||
|  | #     if a == '{': | ||||||
|  | #         return b == '}' | ||||||
|  | #     if a == '[': | ||||||
|  | #         return b == ']' | ||||||
|  | #     if a == '(': | ||||||
|  | #         return b == ')' | ||||||
|  | #     return False | ||||||
|  | 
 | ||||||
|  | # def f(xs): | ||||||
|  | #     s = [] | ||||||
|  | #     for c in xs: | ||||||
|  | #         if c in {'{', '[', '('}: | ||||||
|  | #             s.append(c) | ||||||
|  | #         elif c in {'}', ']', ')'}: | ||||||
|  | #             opener = s.pop() | ||||||
|  | #             if not match(opener, c): | ||||||
|  | #                 return False | ||||||
|  | #     return len(s) == 0 | ||||||
|  | 
 | ||||||
|  | # assert f("{[]()}") | ||||||
|  | # assert f("{[(])}") == False | ||||||
|  | # assert f("{[}") == False | ||||||
|  | # print("Success!") | ||||||
|  | 
 | ||||||
|  | # def valid_bst(node): | ||||||
|  | #     lhs = max_bst_value(node.left) if node.left else float('-inf') | ||||||
|  | #     rhs = min_bst_value(node.right) if node.right else float('inf') | ||||||
|  | 
 | ||||||
|  | #     return and([ | ||||||
|  | #         lhs <= node.value, | ||||||
|  | #         rhs > node.value, | ||||||
|  | #         valid_bst(node.left), | ||||||
|  | #         valid_bst(node.right), | ||||||
|  | #     ]) | ||||||
|  | 
 | ||||||
|  | import random | ||||||
|  | import math | ||||||
|  | 
 | ||||||
|  | def shuffle(xs): | ||||||
|  |     n = len(xs) | ||||||
|  |     for i in range(n - 1): | ||||||
|  |         j = random.randint(i + 1, n - 1) | ||||||
|  |         xs[i], xs[j] = xs[j], xs[i] | ||||||
|  |     return xs | ||||||
|  | 
 | ||||||
|  | def as_card(i): | ||||||
|  |     if i not in range(1, 53): | ||||||
|  |         raise Exception("Not a card") | ||||||
|  |     # 1 | ||||||
|  |     suit = ['Hearts', 'Clubs', 'Diamonds', 'Spades'][math.floor((i - 1) / 13)] | ||||||
|  |     n = ['Ace',2,3,4,5,6,7,8,9,10,'Jack','Queen','King'][(i - 1) % 13] | ||||||
|  |     return '{} of {}'.format(n, suit) | ||||||
|  | 
 | ||||||
|  | xs = list(range(1, 53)) | ||||||
|  | print(xs) | ||||||
|  | shuffle(xs) | ||||||
|  | for x in xs: | ||||||
|  |     print(as_card(x)) | ||||||
							
								
								
									
										22
									
								
								scratch/facebook/second-largest-item-in-bst.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								scratch/facebook/second-largest-item-in-bst.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | from collections import deque | ||||||
|  | from node import Node, tree | ||||||
|  | 
 | ||||||
|  | def find_largest(node): | ||||||
|  |     while node.right: | ||||||
|  |         node = node.right | ||||||
|  |     return node.value | ||||||
|  | 
 | ||||||
|  | def find_second_largest(node): | ||||||
|  |     # parent of the rightmost, when rightmost is leaf | ||||||
|  |     # max(rightmost.left) | ||||||
|  |     prev = None | ||||||
|  |     while node.right: | ||||||
|  |         prev = node | ||||||
|  |         node = node.right | ||||||
|  |     if node.left: | ||||||
|  |         return find_largest(node.left) | ||||||
|  |     else: | ||||||
|  |         return prev.value | ||||||
|  | 
 | ||||||
|  | assert find_second_largest(tree) == 72 | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										17
									
								
								scratch/facebook/shuffle.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								scratch/facebook/shuffle.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,17 @@ | ||||||
|  | from random import randint | ||||||
|  | 
 | ||||||
|  | def get_random(i, j): | ||||||
|  |     return randint(i, j) | ||||||
|  | 
 | ||||||
|  | def shuffle(xs): | ||||||
|  |     for i in range(len(xs)): | ||||||
|  |         j = get_random(i, len(xs) - 1) | ||||||
|  |         xs[i], xs[j] = xs[j], xs[i] | ||||||
|  | 
 | ||||||
|  | xs = list(range(1, 53)) | ||||||
|  | print(xs) | ||||||
|  | assert len(set(xs)) == 52 | ||||||
|  | shuffle(xs) | ||||||
|  | assert len(set(xs)) == 52 | ||||||
|  | print(xs) | ||||||
|  | print("Success!") | ||||||
							
								
								
									
										25
									
								
								scratch/facebook/stack.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								scratch/facebook/stack.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | class Stack(object): | ||||||
|  |     def __init__(self): | ||||||
|  |         self.items = [] | ||||||
|  | 
 | ||||||
|  |     def __repr__(self): | ||||||
|  |         return self.items.__repr__() | ||||||
|  | 
 | ||||||
|  |     def push(self, x): | ||||||
|  |         self.items.append(x) | ||||||
|  | 
 | ||||||
|  |     def pop(self): | ||||||
|  |         if not self.items: | ||||||
|  |             return None | ||||||
|  |         return self.items.pop() | ||||||
|  | 
 | ||||||
|  |     def peek(self): | ||||||
|  |         if not self.items: | ||||||
|  |             return None | ||||||
|  |         return self.items[-1] | ||||||
|  | 
 | ||||||
|  | def from_list(xs): | ||||||
|  |     result = Stack() | ||||||
|  |     for x in xs: | ||||||
|  |         result.push(x) | ||||||
|  |     return result | ||||||
							
								
								
									
										16
									
								
								scratch/facebook/stock-price.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								scratch/facebook/stock-price.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | def max_profit(xs): | ||||||
|  |     buy = xs[0] | ||||||
|  |     profit = xs[1] - xs[0] | ||||||
|  |     for price in xs[1:]: | ||||||
|  |         profit = max(profit, price - buy) | ||||||
|  |         buy = min(buy, price) | ||||||
|  |     return profit | ||||||
|  | 
 | ||||||
|  | xs = [([10,7,5,8,11,9], 6), | ||||||
|  |       ([10,8,7,6,5], -1)] | ||||||
|  | 
 | ||||||
|  | for x, expected in xs: | ||||||
|  |     result = max_profit(x) | ||||||
|  |     print(x, result) | ||||||
|  |     assert result == expected | ||||||
|  |     print("Success!") | ||||||
							
								
								
									
										60
									
								
								scratch/facebook/todo.org
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								scratch/facebook/todo.org
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | ||||||
|  | * Array and string manipulation | ||||||
|  | ** DONE Merging Meeting Times | ||||||
|  | ** DONE Reverse String in Place | ||||||
|  | ** TODO Reverse Words | ||||||
|  | ** DONE Merge Sorted Arrays | ||||||
|  | ** DONE Cafe Order Checker | ||||||
|  | * Hashing and hash tables | ||||||
|  | ** DONE Inflight Entertainment | ||||||
|  | ** DONE Permutation Palindrome | ||||||
|  | ** DONE Word Cloud Data | ||||||
|  | ** DONE Top Scores | ||||||
|  | * Greedy Algorithms | ||||||
|  | ** DONE Apple Stocks | ||||||
|  | ** DONE Highest Product of 3 | ||||||
|  | ** DONE Product of All Other Numbers | ||||||
|  | ** DONE Cafe Order Checker | ||||||
|  | ** DONE In-Place Shuffle | ||||||
|  | * Sorting, searching, and logarithms | ||||||
|  | ** DONE Find Rotation Point | ||||||
|  | ** TODO Find Repeat, Space Edition | ||||||
|  | ** DONE Top Scores | ||||||
|  | ** DONE Merging Meeting Times | ||||||
|  | * Trees and graphs | ||||||
|  | ** DONE Balanced Binary Tree | ||||||
|  | ** DONE Binary Search Tree Checker | ||||||
|  | ** DONE 2nd Largest Item in a Binary Search Tree | ||||||
|  | ** DONE Graph Coloring | ||||||
|  | ** DONE MeshMessage | ||||||
|  | ** DONE Find Repeat, Space Edition BEAST MODE | ||||||
|  | * Dynamic programming and recursion | ||||||
|  | ** DONE Recursive String Permutations | ||||||
|  | ** DONE Compute nth Fibonacci Number | ||||||
|  | ** DONE Making Change | ||||||
|  | ** DONE The Cake Thief | ||||||
|  | ** DONE Balanced Binary Tree | ||||||
|  | ** DONE Binary Search Tree Checker | ||||||
|  | ** DONE 2nd Largest Item in a Binary Search Tree | ||||||
|  | * Queues and stacks | ||||||
|  | ** DONE Largest Stack | ||||||
|  | ** DONE Implement A Queue With Two Stacks | ||||||
|  | ** DONE Parenthesis Matching | ||||||
|  | ** DONE Bracket Validator | ||||||
|  | * Linked lists | ||||||
|  | ** DONE Delete Node | ||||||
|  | ** DONE Does This Linked List Have A Cycle? | ||||||
|  | ** DONE Reverse A Linked List | ||||||
|  | ** DONE Kth to Last Node in a Singly-Linked List | ||||||
|  | ** DONE Find Repeat, Space Edition BEAST MODE | ||||||
|  | * General programming | ||||||
|  | ** TODO Rectangular Love | ||||||
|  | ** TODO Temperature Tracker | ||||||
|  | * Bit manipulation | ||||||
|  | ** DONE The Stolen Breakfast Drone | ||||||
|  | * Combinatorics, probability, and other math | ||||||
|  | ** TODO Which Appears Twice | ||||||
|  | ** TODO Find in Ordered Set | ||||||
|  | ** TODO In-Place Shuffle | ||||||
|  | ** TODO Simulate 5-sided die | ||||||
|  | ** TODO Simulate 7-sided die | ||||||
|  | ** TODO Two Egg Problem | ||||||
							
								
								
									
										20
									
								
								scratch/facebook/top-scores.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								scratch/facebook/top-scores.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,20 @@ | ||||||
|  | import random | ||||||
|  | from collections import deque | ||||||
|  | 
 | ||||||
|  | def sorted(xs): | ||||||
|  |     result = [0] * 100 | ||||||
|  |     for x in xs: | ||||||
|  |         result[x - 1] += 1 | ||||||
|  | 
 | ||||||
|  |     answer = deque() | ||||||
|  |     for i in range(len(result)): | ||||||
|  |         x = result[i] | ||||||
|  |         for _ in range(x): | ||||||
|  |             answer.appendleft(i + 1) | ||||||
|  | 
 | ||||||
|  |     return list(answer) | ||||||
|  | 
 | ||||||
|  | scores = [random.choice(range(70, 100)) for _ in range(20)] | ||||||
|  | print(scores) | ||||||
|  | result = sorted(scores) | ||||||
|  | print(result) | ||||||
							
								
								
									
										61
									
								
								scratch/facebook/topo-sort.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								scratch/facebook/topo-sort.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | import random | ||||||
|  | from heapq import heappush, heappop | ||||||
|  | from collections import deque | ||||||
|  | 
 | ||||||
|  | # A topological sort returns the vertices of a graph sorted in an ascending | ||||||
|  | # order by the number of incoming edges each vertex has. | ||||||
|  | # | ||||||
|  | # A few algorithms for solving this exist, and at the time of this writing, I | ||||||
|  | # know none. I'm going to focus on two: | ||||||
|  | #   1. Kahn's | ||||||
|  | #   2. DFS (TODO) | ||||||
|  | 
 | ||||||
|  | def count_in_edges(graph): | ||||||
|  |     result = {k: 0 for k in graph.keys()} | ||||||
|  |     for xs in graph.values(): | ||||||
|  |         for x in xs: | ||||||
|  |             result[x] += 1 | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | # Kahn's algorithm for returning a topological sorting of the vertices in | ||||||
|  | # `graph`. | ||||||
|  | def kahns_sort(graph): | ||||||
|  |     result = [] | ||||||
|  |     q = deque() | ||||||
|  |     in_edges = count_in_edges(graph) | ||||||
|  |     for x in [k for k, v in in_edges.items() if v == 0]: | ||||||
|  |         q.append(x) | ||||||
|  |     while q: | ||||||
|  |         x = q.popleft() | ||||||
|  |         result.append(x) | ||||||
|  |         for c in graph[x]: | ||||||
|  |             in_edges[c] -= 1 | ||||||
|  |             if in_edges[c] == 0: | ||||||
|  |                 q.append(c) | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | graphs = [ | ||||||
|  |     { | ||||||
|  |         0: [], | ||||||
|  |         1: [], | ||||||
|  |         2: [3], | ||||||
|  |         3: [1], | ||||||
|  |         4: [0, 1], | ||||||
|  |         5: [0, 2], | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|  |         'A': ['C', 'D'], | ||||||
|  |         'B': ['D', 'E'], | ||||||
|  |         'C': [], | ||||||
|  |         'D': ['F', 'G'], | ||||||
|  |         'E': [], | ||||||
|  |         'F': [], | ||||||
|  |         'G': ['I'], | ||||||
|  |         'H': ['I'], | ||||||
|  |         'I': [], | ||||||
|  |     } | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | print("--- Kahn's --- ") | ||||||
|  | for graph in graphs: | ||||||
|  |     print(kahns_sort(graph)) | ||||||
							
								
								
									
										100
									
								
								scratch/facebook/traversals.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								scratch/facebook/traversals.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,100 @@ | ||||||
|  | from math import floor | ||||||
|  | 
 | ||||||
|  | # Lists | ||||||
|  | def cycle_backwards(times, xs): | ||||||
|  |     n = len(xs) | ||||||
|  |     for i in range(n * times): | ||||||
|  |         print(xs[n - 1 - i % n]) | ||||||
|  | 
 | ||||||
|  | def cycle_forwards(times, xs): | ||||||
|  |     n = len(xs) | ||||||
|  |     for i in range(n * times): | ||||||
|  |         print(xs[i % n]) | ||||||
|  | 
 | ||||||
|  | def backwards(xs): | ||||||
|  |     n = len(xs) | ||||||
|  |     for i in range(n): | ||||||
|  |         print(xs[n - 1 - i]) | ||||||
|  | 
 | ||||||
|  | def forwards(xs): | ||||||
|  |     for i in range(len(xs)): | ||||||
|  |         print(xs[i]) | ||||||
|  | 
 | ||||||
|  | xs = [2, 5, 6, 9, 12] | ||||||
|  | 
 | ||||||
|  | print("Forwards") | ||||||
|  | forwards(xs) | ||||||
|  | print("Backwards") | ||||||
|  | backwards(xs) | ||||||
|  | print("Cycle forwards") | ||||||
|  | cycle_forwards(2, xs) | ||||||
|  | print("Cycle backwards") | ||||||
|  | cycle_backwards(2, xs) | ||||||
|  | 
 | ||||||
|  | # Tables | ||||||
|  | def tblr(table): | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             print(table[row][col]) | ||||||
|  | 
 | ||||||
|  | def tbrl(table): | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         n = len(table[row]) | ||||||
|  |         for col in range(n): | ||||||
|  |             print(table[row][n - 1 - col]) | ||||||
|  | 
 | ||||||
|  | def btlr(table): | ||||||
|  |     n = len(table) | ||||||
|  |     for row in range(n): | ||||||
|  |         for col in range(len(table[row])): | ||||||
|  |             print(table[n - 1 - row][col]) | ||||||
|  | 
 | ||||||
|  | def btrl(table): | ||||||
|  |     rows = len(table) | ||||||
|  |     for row in range(rows): | ||||||
|  |         cols = len(table[row]) | ||||||
|  |         for col in range(cols): | ||||||
|  |             print(table[rows - 1 - row][cols - 1 - col]) | ||||||
|  | 
 | ||||||
|  | def special(table): | ||||||
|  |     rows = len(table) | ||||||
|  |     cols = len(table[0]) | ||||||
|  |     for col in range(cols): | ||||||
|  |         for row in range(rows): | ||||||
|  |             print(table[row][col]) | ||||||
|  | 
 | ||||||
|  | def double_bonus(table): | ||||||
|  |     rows = len(table) | ||||||
|  |     cols = len(table[0]) | ||||||
|  |     for i in range(rows): | ||||||
|  |         row = i | ||||||
|  |         for col in range(cols): | ||||||
|  |             print(table[row][col % cols]) | ||||||
|  |             row = (row + 1) % rows | ||||||
|  | 
 | ||||||
|  | def free(table): | ||||||
|  |     rows = len(table) | ||||||
|  |     cols = len(table[0]) | ||||||
|  |     d = rows * cols | ||||||
|  |     for i in range(d): | ||||||
|  |         row = floor((i % d) / cols) | ||||||
|  |         col = i % cols | ||||||
|  |         print(table[row][col]) | ||||||
|  | 
 | ||||||
|  | table = [[1,2,3,4], | ||||||
|  |          [5,6,7,8]] | ||||||
|  | 
 | ||||||
|  | print("Top->Bottom, Left->Right") | ||||||
|  | tblr(table) | ||||||
|  | print("Top->Bottom, Right->Left") | ||||||
|  | tbrl(table) | ||||||
|  | print("Bottom->Top, Left->Right") | ||||||
|  | btlr(table) | ||||||
|  | print("Bottom->Top, Right->Left") | ||||||
|  | btrl(table) | ||||||
|  | print("Special") | ||||||
|  | special(table) | ||||||
|  | print("2x Bonus") | ||||||
|  | double_bonus(table) | ||||||
|  | print("Free") | ||||||
|  | free(table) | ||||||
							
								
								
									
										19
									
								
								scratch/facebook/utils.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								scratch/facebook/utils.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | ||||||
|  | def init_table(rows=0, cols=0, default=None): | ||||||
|  |     table = [] | ||||||
|  |     for row in range(rows): | ||||||
|  |         x = [] | ||||||
|  |         for col in range(cols): | ||||||
|  |             x.append(default) | ||||||
|  |         table.append(x) | ||||||
|  |     return table | ||||||
|  | 
 | ||||||
|  | def get(table, row, col, default=0): | ||||||
|  |     if row < 0 or col < 0: | ||||||
|  |         return default | ||||||
|  |     return table[row][col] | ||||||
|  | 
 | ||||||
|  | def print_table(table): | ||||||
|  |     result = [] | ||||||
|  |     for row in range(len(table)): | ||||||
|  |         result.append(' '.join([str(cell) for cell in table[row]])) | ||||||
|  |     print('\n'.join(result)) | ||||||
							
								
								
									
										32
									
								
								scratch/facebook/word-cloud.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								scratch/facebook/word-cloud.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | def normalize(x): | ||||||
|  |     noise = ".,;-" | ||||||
|  |     for y in noise: | ||||||
|  |         if x.endswith(y): | ||||||
|  |             return normalize(x[0:-1]) | ||||||
|  |         if x.startswith(y): | ||||||
|  |             return normalize(x[1:]) | ||||||
|  |     return x.lower() | ||||||
|  | 
 | ||||||
|  | def word_cloud(xs): | ||||||
|  |     result = dict() | ||||||
|  | 
 | ||||||
|  |     for x in xs.split(' '): | ||||||
|  |         k = normalize(x) | ||||||
|  |         if k in result: | ||||||
|  |             result[k] += 1 | ||||||
|  |         else: | ||||||
|  |             result[k] = 1 | ||||||
|  | 
 | ||||||
|  |     return result | ||||||
|  | 
 | ||||||
|  | result = word_cloud("This is just the beginning. The UK will lockdown again.") | ||||||
|  | assert result.get('this') == 1 | ||||||
|  | assert result.get('is') == 1 | ||||||
|  | assert result.get('just') == 1 | ||||||
|  | assert result.get('the') == 2 | ||||||
|  | assert result.get('beginning') == 1 | ||||||
|  | assert result.get('uk') == 1 | ||||||
|  | assert result.get('will') == 1 | ||||||
|  | assert result.get('lockdown') == 1 | ||||||
|  | assert result.get('again') == 1 | ||||||
|  | print("Success!") | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue