Skip to content

Commit 3a606f1

Browse files
committed
Partial readme for chapter 17
1 parent 6c7e71f commit 3a606f1

20 files changed

+320
-185
lines changed

chapter_17/p17_1.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
2+
# Method: Bitwise addition, recurse with carry
3+
# Time: O(log(n))
4+
# Space: O(log(n))
5+
16
def add_overfill(left, res, ctr, carry):
27
while left:
38
# print(f"Diggin into {left:b}, resutl now {res:b}")
@@ -84,11 +89,13 @@ def add_no_alg_better(a, b):
8489
# exs = [(0b1011, 0b1011)]
8590
fails = 0
8691
for a, b in exs:
87-
if add_no_alg(a, b) != a+b or add_no_alg_better(a,b) != a+b:
92+
if add_no_alg(a, b) != a + b or add_no_alg_better(a, b) != a + b:
8893
print(
89-
f"Result\t{add_no_alg(a,b):b},\nsame as\t{(a+b):b} ? {add_no_alg(a,b) == a+b}, for inputs {a:b} and {b:b}")
94+
f"Result\t{add_no_alg(a,b):b},"
95+
f"same as\t{(a+b):b} ? {add_no_alg(a,b) == a+b}, for inputs {a:b} and {b:b}"
96+
)
9097
fails += 1
91-
print("*"*50)
98+
print("*" * 50)
9299
else:
93100
# print(f"Good for {a} and {b}")
94101
pass

chapter_17/p17_10.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
from typing import List
22

3+
# Method: If there is a majority element, it's going to have enough buget to displace all others
4+
# Time: O(n)
5+
# Space: O(1)
6+
37

48
def majority_elem(arr):
59
candidate = maj_elem(arr)
610
return candidate if is_majority(candidate, arr) else -1
711

812

9-
def is_majority(x, arr):
13+
def is_majority(x: int, arr: List[int]) -> bool:
1014
count = 0
1115
for elem in arr:
12-
count += (elem == x)
16+
count += elem == x
1317
print(f"Count is {count}")
14-
return count > len(arr)/2
18+
return count > len(arr) / 2
1519

1620

1721
def maj_elem(arr: List[int]) -> int:
1822
elem_now = arr[1]
1923
count = 1
20-
for x in arr[1:]:
24+
for i in range(1, len(arr)):
25+
x = arr[i]
2126
if x == elem_now:
2227
count += 1
2328
else:

chapter_17/p17_11.py

+21-10
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,23 @@
1-
# idea: Reverse index
2-
3-
# create mapping from key: word , value: sorted set of occurences (count words in book)
4-
5-
# when looking for shortest distance between 2 words, run 2 pointers in the sorted arr, find min diff
61
import re
72
from typing import List
83
from collections import defaultdict
94
import os
105

6+
# Method: Index occurences, run through 2 sorted occurence lists
7+
# Time: O(w*o + max(o))
8+
# Space: O(w*o)
9+
# Notes: o = nr of occurences of a word, max(o) = **the** most frequent word
10+
11+
# Idea: Reverse index
12+
# create mapping from
13+
# key: word ,
14+
# value: sorted set of occurences
15+
# (count words in book)
16+
17+
# when looking for shortest distance between 2 words,
18+
# run 2 pointers in the sorted arr,
19+
# find min diff
20+
1121

1222
def build_reverse_index(words: List[str]):
1323
rev_index = defaultdict(list)
@@ -24,7 +34,7 @@ def get_min_interword_distance(w1: str, w2: str, rev_index: dict):
2434
if not occ_w1 or not occ_w2:
2535
raise Exception("Not all words present")
2636

27-
min_sum = float('inf')
37+
min_sum = float("inf")
2838
p1 = 0
2939
p2 = 0
3040
while p1 < len(occ_w1) and p2 < len(occ_w2):
@@ -42,8 +52,7 @@ def get_min_interword_distance(w1: str, w2: str, rev_index: dict):
4252

4353
if __name__ == "__main__":
4454
with open(os.path.join("utils", "lorem_ipsum.txt")) as words_source:
45-
all_non_empty_words = filter(
46-
bool, re.split(" |\n|\.", words_source.read()))
55+
all_non_empty_words = filter(bool, re.split(" |\n|\.", words_source.read()))
4756
all_text = list(map(lambda x: x.lower(), all_non_empty_words))
4857

4958
reverse_index = build_reverse_index(all_text)
@@ -53,5 +62,7 @@ def get_min_interword_distance(w1: str, w2: str, rev_index: dict):
5362
]
5463

5564
for w1, w2 in exs:
56-
print(f"Shortest distance b/t {w1} and {w2}"
57-
f" at {get_min_interword_distance(w1,w2, reverse_index)}")
65+
print(
66+
f"Shortest distance b/t {w1} and {w2}"
67+
f" at {get_min_interword_distance(w1,w2, reverse_index)}"
68+
)

chapter_17/p17_12.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
from typing import Tuple
2+
3+
# Method: Recursive call, returning left and right edges of result linked list
4+
# Time: O(n)
5+
# Space: O(d)
6+
# Where d = depth of BST
7+
18

29
class BiNode:
310
def __init__(self, val):
@@ -11,16 +18,18 @@ def flatten_binary_tree(root: BiNode):
1118
return left_side
1219

1320

14-
def flat_helper(root: BiNode) -> tuple:
21+
def flat_helper(root: BiNode) -> Tuple[BiNode, BiNode]:
1522
left_edge = root
1623
right_edge = root
24+
1725
if root.node1:
1826
left_edge_left, left_edge_right = flat_helper(root.node1)
1927

2028
root.node1 = left_edge_right
2129
left_edge_right.node2 = root
2230

2331
left_edge = left_edge_left
32+
2433
if root.node2:
2534
right_edge_left, right_edge_right = flat_helper(root.node2)
2635

@@ -32,11 +41,6 @@ def flat_helper(root: BiNode) -> tuple:
3241
return (left_edge, right_edge)
3342

3443

35-
# 20
36-
# 10 25
37-
# 5 22
38-
# 21 23
39-
4044
if __name__ == "__main__":
4145
root = BiNode(20)
4246
root.node1 = BiNode(10)

chapter_17/p17_13.py

+20-19
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
11
from typing import List
2-
import utils.datasets
32
from functools import lru_cache
43

4+
# Method: DFS, prefix and best-of-rest with lookup against dict
5+
# Time: O(n^2)
6+
# Space: O(n)
7+
8+
59
def add_spaces(alltext: str, words: List[str]):
610
word_set = set(words)
711
space_arr, invalids = add_spaces_helper(alltext, 0, word_set, {})
812

9-
print(f"Managed to do it with {invalids} characters unknown, splits {space_arr}")
13+
# print(f"Managed to do it with {invalids} characters unknown, splits {space_arr}")
1014
i = 0
1115
spaced_text = []
1216
for i in range(len(alltext)):
1317
spaced_text.append(alltext[i])
1418
if i in space_arr:
1519
spaced_text.append(" ")
16-
1720

1821
return "".join(spaced_text)
1922

2023

21-
def add_spaces_helper(text: str,
22-
start_poz: int,
23-
# split_pozs: List[int],
24-
word_set: set,
25-
memo:dict):
26-
if (start_poz in memo):
24+
def add_spaces_helper(
25+
text: str,
26+
start_poz: int,
27+
word_set: set,
28+
memo: dict,
29+
):
30+
if start_poz in memo:
2731
return memo[start_poz]
28-
32+
2933
n = len(text)
3034
if start_poz == n:
3135
return [], 0
@@ -41,13 +45,14 @@ def add_spaces_helper(text: str,
4145

4246
if invals < best_invals:
4347

44-
rest_words, rest_invals_count = \
45-
add_spaces_helper(text, i + 1, word_set, memo)
48+
rest_words, rest_invals_count = add_spaces_helper(
49+
text, i + 1, word_set, memo
50+
)
4651

4752
if rest_invals_count + invals < best_invals:
48-
current_splits = [start_poz-1, i] if invals == 0 else []
53+
current_splits = [start_poz - 1, i] if invals == 0 else []
4954
best_invals = rest_invals_count + invals
50-
best_words = rest_words + current_splits
55+
best_words = rest_words + current_splits
5156

5257
# print(f"At start {start_poz} Got best words {best_words}, and invals {best_invals}")
5358
memo[start_poz] = (best_words, best_invals)
@@ -56,11 +61,7 @@ def add_spaces_helper(text: str,
5661

5762

5863
if __name__ == "__main__":
59-
exs = [
60-
"helplinustechtipsineedtorebootmypc",
61-
"linusz",
62-
"torebootmy"
63-
]
64+
exs = ["helplinustechtipsineedtorebootmypc", "linusz", "torebootmy"]
6465

6566
# words = utils.datasets.get_system_word_list()
6667
words = ["help", "tech", "tips", "boot", "my", "reboot", "need", "to", "linus"]

chapter_17/p17_14.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22
from typing import List
33
import heapq
44

5+
# Method: Minheap
6+
# Time: O(n * log(k))
7+
# Space: O(k)
8+
59

610
def smallest_k_elem(arr: List[int], k: int) -> List[int]:
711
heap = []
812

913
for i in range(k):
1014
heapq.heappush(heap, -arr[i])
1115

12-
for i in range(k+1, len(arr)):
16+
for i in range(k + 1, len(arr)):
1317
if arr[i] < -heap[0]:
1418
heapq.heappop(heap)
1519
heapq.heappush(heap, -arr[i])
@@ -18,10 +22,7 @@ def smallest_k_elem(arr: List[int], k: int) -> List[int]:
1822

1923

2024
if __name__ == "__main__":
21-
exs = [
22-
([1, 2, 3, 4, 5, 6], 4),
23-
([1, 2, 2, 2, 1, 1, 0], 3)
24-
]
25+
exs = [([1, 2, 3, 4, 5, 6], 4), ([1, 2, 2, 2, 1, 1, 0], 3)]
2526

2627
for ex, k in exs:
2728
print(f"{k} smalles in {ex} are {smallest_k_elem(ex,k)}")

chapter_17/p17_15.py

+30-15
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
from typing import List
22

3+
# Method: See if any split is buildable (left + right)
4+
# Time: O(w*(lw^2))
5+
# Space: O(w*(lw^2))
6+
# Note: w = nr of words lw: length of a word
7+
# Low confidence on both estimates
8+
39

410
def get_longest_gestaltwort(words: List[str]):
511
known_words = {word: True for word in words}
612

713
words_by_len = sorted(known_words, key=len, reverse=True)
814

915
for word in words_by_len:
10-
for i in range(1, len(word)):
11-
if can_build_word(word, True, known_words):
12-
print(known_words)
13-
return word
16+
if can_build_word(word, True, known_words):
17+
return word
1418

1519

1620
def can_build_word(word, is_given_word, known_words):
@@ -20,28 +24,39 @@ def can_build_word(word, is_given_word, known_words):
2024
for i in range(1, len(word)):
2125
left = word[:i]
2226
right = word[i:]
23-
if left in known_words and known_words[left]\
24-
and can_build_word(right, False, known_words):
27+
if (
28+
left in known_words
29+
and known_words[left]
30+
and can_build_word(right, False, known_words)
31+
):
2532
known_words[word] = True
26-
return True
33+
return known_words[word]
2734

2835
known_words[word] = False
29-
return False
36+
return known_words[word]
3037

3138

3239
def sys_word_test():
3340
with open("/usr/share/dict/words", "r") as system_words_file:
34-
big_list = list(map(lambda word: word.lower(),
35-
system_words_file.read().split("\n")))
41+
big_list = list(
42+
map(lambda word: word.lower(), system_words_file.read().split("\n"))
43+
)
3644

3745
print(f"Have a total of {len(big_list)} words")
3846
print(f"The longest is: {sorted(big_list, key = len)[-1]}")
3947

40-
print(
41-
f"For the words, the longest is {get_longest_gestaltwort(big_list[1:])}")
48+
print(f"For the words, the longest is: {get_longest_gestaltwort(big_list[1:])}")
4249

4350

4451
if __name__ == "__main__":
45-
words = ["cat", "banana", "dog", "nana",
46-
"walk", "walker", "dogwalker", "catdognana"]
47-
print(f"For the words, the longest is {get_longest_gestaltwort(words)}")
52+
words = [
53+
"cat",
54+
"banana",
55+
"dog",
56+
"nana",
57+
"walk",
58+
"walker",
59+
"dogwalker",
60+
"catdognana",
61+
]
62+
print(f"For the words, the longest is: {get_longest_gestaltwort(words)}")

chapter_17/p17_16.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
11
from typing import List
22

3+
# Method: Bottom-up DP, max of times considering gap
4+
# Time: O(n)
5+
# Space: O(n)
6+
37

48
def masseuse_sched(appointments: List[int]):
59
n = len(appointments)
610

7-
dp = [0 for _ in range(n+3)]
11+
dp = [0 for _ in range(n + 3)]
812
cmax = 0
913

10-
for i in range(n-1, -1, -1):
11-
dp[i] = appointments[i] + max(dp[i+2], dp[i+3])
14+
for i in range(n - 1, -1, -1):
15+
dp[i] = appointments[i] + max(dp[i + 2], dp[i + 3])
1216
if dp[i] > cmax:
1317
cmax = dp[i]
1418

1519
return max(dp[0], dp[1])
1620

1721

1822
if __name__ == "__main__":
19-
exs = [
20-
[30, 15, 60, 75, 45, 15, 15, 45],
21-
[150, 30, 45, 60, 75, 150]
22-
]
23+
exs = [[30, 15, 60, 75, 45, 15, 15, 45], [150, 30, 45, 60, 75, 150]]
2324

2425
for ex in exs:
2526
print(f"Max mins is {masseuse_sched(ex)} for bookings {ex}")

0 commit comments

Comments
 (0)