Skip to content

Commit d305177

Browse files
committed
8/25/23
Shooting for 10: 1) evaluate_rpn.py 2) is_valid_parenthsization.py 3) directory_path_normalization.py 4) sunset_view.py 5) queue_from_stacks.py
1 parent 29c894d commit d305177

File tree

6 files changed

+171
-16
lines changed

6 files changed

+171
-16
lines changed

Diff for: elements-of-programming-interviews/problem_mapping.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ problem_mapping = {
896896
"total": 108
897897
},
898898
"Python: evaluate_rpn.py": {
899-
"passed": 0,
899+
"passed": 108,
900900
"total": 108
901901
}
902902
},
@@ -910,7 +910,7 @@ problem_mapping = {
910910
"total": 78
911911
},
912912
"Python: is_valid_parenthesization.py": {
913-
"passed": 0,
913+
"passed": 78,
914914
"total": 78
915915
}
916916
},
@@ -924,7 +924,7 @@ problem_mapping = {
924924
"total": 255
925925
},
926926
"Python: directory_path_normalization.py": {
927-
"passed": 0,
927+
"passed": 255,
928928
"total": 255
929929
}
930930
},
@@ -938,7 +938,7 @@ problem_mapping = {
938938
"total": 101
939939
},
940940
"Python: sunset_view.py": {
941-
"passed": 0,
941+
"passed": 101,
942942
"total": 101
943943
}
944944
},

Diff for: elements-of-programming-interviews/python/directory_path_normalization.py

+91-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,101 @@
11
from test_framework import generic_test
22

33

4+
"""
5+
Allowed chars:
6+
- . (current path)
7+
- .. (parent dir)
8+
- / (subdir)
9+
- alphanum (dir name)
10+
- empty (same as .)
11+
12+
cases:
13+
- empty
14+
- /////// -> /
15+
- / -> /
16+
- /../.. -> /
17+
- ../.. -> ../..
18+
- derp -> derp
19+
- /derp -> /derp
20+
- /derp/.. -> /
21+
- derp/.. -> empty?
22+
- derp/../.. -> ..
23+
24+
- Paths can be absolute (begin at '/') or relative (begin at current dir)
25+
- for abspaths, / is highest parent; any '..' from '/' yields '/'
26+
- for relpaths, each '..' either pops the last known dir, or appends '..'
27+
"""
28+
29+
30+
def shortest_equivalent_path_first(path: str) -> str:
31+
"""
32+
- is absolute? (first char)
33+
- split path on '/'
34+
- keep stack
35+
- for each item in path list:
36+
- if char is ., skip it
37+
- if item is alphanum, push it
38+
- if item is ..:
39+
- if dir is absolute, pop if stack is nonempty, else skip
40+
- if dir is rel, pop if stack is nonempty and stack top not .., else push
41+
- return joined stack; prepend '/' is absolute path
42+
"""
43+
if not path:
44+
return path
45+
absolute = path[0] == '/'
46+
47+
stack = []
48+
dirs = [item for item in path.split('/') if item]
49+
for item in dirs:
50+
if item == "..":
51+
if absolute and stack:
52+
stack.pop()
53+
elif not absolute and (not stack or stack[-1] == ".."):
54+
stack.append(item)
55+
elif not absolute and stack and stack[-1] != "..":
56+
stack.pop()
57+
elif item == ".":
58+
continue
59+
else:
60+
stack.append(item)
61+
62+
return ("/" if absolute else "") + "/".join(stack)
63+
64+
465
def shortest_equivalent_path(path: str) -> str:
5-
# TODO - you fill in here.
6-
return ''
66+
if not path:
67+
return path
68+
69+
stack = []
70+
for item in (item for item in path.split('/') if (item and item != ".")):
71+
if item == "..":
72+
if stack and (path[0] == '/' or stack[-1] != ".."):
73+
stack.pop()
74+
else:
75+
stack.append(item)
76+
else:
77+
stack.append(item)
78+
79+
return ("/" if path.startswith('/') else "") + "/".join(stack)
780

881

982
if __name__ == '__main__':
83+
cases = [
84+
("", ""),
85+
("///////", "/"),
86+
("/", "/"),
87+
("/../..", "/"),
88+
("../..", "../.."),
89+
("derp", "derp"),
90+
("/derp", "/derp"),
91+
("/derp/..", "/"),
92+
("derp/..", ""),
93+
("derp/../..", "..")
94+
]
95+
for path, expected in cases:
96+
actual = shortest_equivalent_path(path)
97+
assert actual == expected, f"{path}: {actual} != {expected}"
98+
1099
exit(
11100
generic_test.generic_test_main('directory_path_normalization.py',
12101
'directory_path_normalization.tsv',
+40-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,50 @@
11
from test_framework import generic_test
22

33

4+
OPERATIONS = ["*", "+", "/", "-"]
5+
6+
7+
def apply(operation, op1, op2):
8+
if operation == "*":
9+
return op1 * op2
10+
elif operation == "+":
11+
return op1+op2
12+
elif operation == "/":
13+
return op1 // op2
14+
else:
15+
return op1 - op2
16+
17+
418
def evaluate(expression: str) -> int:
5-
# TODO - you fill in here.
6-
return 0
19+
# NOTE: assuming valid expression
20+
if not expression:
21+
return 0
22+
stack = []
23+
expr = expression.split(",")
24+
for val in expr:
25+
if val not in OPERATIONS:
26+
stack.append(int(val))
27+
else:
28+
op2 = stack.pop()
29+
op1 = stack.pop()
30+
stack.append(apply(val, op1, op2))
31+
return stack.pop()
732

833

934
if __name__ == '__main__':
35+
"""
36+
cases = [
37+
("0", 0),
38+
("", 0),
39+
("4", 4),
40+
("-4", -4),
41+
("4,4,+", 8),
42+
("10,10,X,4,4,+,+,2,/", 54)
43+
44+
]
45+
for expression, expected in cases:
46+
assert evaluate(expression) == expected, f"{evaluate(expression)} != {expected}"
47+
"""
1048
exit(
1149
generic_test.generic_test_main('evaluate_rpn.py', 'evaluate_rpn.tsv',
1250
evaluate))

Diff for: elements-of-programming-interviews/python/is_valid_parenthesization.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@
22

33

44
def is_well_formed(s: str) -> bool:
5-
# TODO - you fill in here.
6-
return True
5+
BRACES = {
6+
'{': '}',
7+
'(': ')',
8+
'[': ']'
9+
}
10+
stack = []
11+
for c in s:
12+
if c in BRACES:
13+
stack.append(c)
14+
elif not stack or not (c == BRACES[stack.pop()]):
15+
return False
16+
return len(stack) == 0
717

818

919
if __name__ == '__main__':
20+
# is_well_formed("()")
1021
exit(
1122
generic_test.generic_test_main('is_valid_parenthesization.py',
1223
'is_valid_parenthesization.tsv',

Diff for: elements-of-programming-interviews/python/queue_from_stacks.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33

44

55
class Queue:
6+
def __init__(self):
7+
self.in_stack = []
8+
self.out_stack = []
9+
610
def enqueue(self, x: int) -> None:
7-
# TODO - you fill in here.
8-
return
11+
self.in_stack.append(x)
912

1013
def dequeue(self) -> int:
11-
# TODO - you fill in here.
12-
return 0
14+
if not self.out_stack:
15+
while self.in_stack:
16+
self.out_stack.append(self.in_stack.pop())
17+
return self.out_stack.pop()
1318

1419

1520
def queue_tester(ops):

Diff for: elements-of-programming-interviews/python/sunset_view.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,22 @@
22

33
from test_framework import generic_test
44

5+
"""
6+
- Input is a list of height
7+
- Output is list of indices
8+
9+
[6,5,4,3,2,1]
10+
[1,2,3,4]
11+
"""
12+
513

614
def examine_buildings_with_sunset(sequence: Iterator[int]) -> List[int]:
7-
# TODO - you fill in here.
8-
return []
15+
stack = []
16+
for i, height in enumerate(sequence):
17+
while stack and stack[-1][1] <= height:
18+
stack.pop()
19+
stack.append((i, height))
20+
return [item[0] for item in reversed(stack)]
921

1022

1123
def examine_buildings_with_sunset_wrapper(sequence):

0 commit comments

Comments
 (0)