Skip to content

Commit a777150

Browse files
committed
8/16/23 - Heading to Clemson with Sophie
- evaluate_rpn.cc - sunset_view.cc - directory_path_normalization.cc
1 parent acd2996 commit a777150

File tree

5 files changed

+327
-9
lines changed

5 files changed

+327
-9
lines changed

elements-of-programming-interviews/cpp/directory_path_normalization.cc

Lines changed: 94 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,105 @@
11
#include <string>
2+
#include <vector>
23

34
#include "test_framework/generic_test.h"
45
using std::string;
6+
using std::vector;
7+
8+
/*
9+
- Cases:
10+
- absolute path (begins with /)
11+
- relative path (no prefix /)
12+
13+
- Tokens:
14+
- ".."
15+
- relative: if the top of the (nonempty) stack is not "..", should pop.
16+
Otherwise, push it.
17+
- nonrelative: always pop the top of the (nonempty) stack
18+
- "."
19+
- represents current dir; can be ignored
20+
- ""
21+
- represents "//"; can be ignored (or treated as ".")
22+
- (any chars)
23+
- represents a directory name. Has to be pushed, may be removed.
24+
*/
25+
26+
string assembleFinalPath(const vector<string>& dirs, bool isAbsolute) {
27+
string path = isAbsolute ? "/" : "";
28+
for (string dir : dirs) {
29+
path += dir + "/";
30+
}
31+
if (path.size() > 1) {
32+
path.erase(path.end() - 1);
33+
}
34+
return path;
35+
}
36+
37+
void processAbsolute(vector<string>& dirs, vector<string>& processedDirs) {
38+
for (string dir : dirs) {
39+
if (dir == "..") {
40+
if (!processedDirs.empty()) {
41+
processedDirs.pop_back();
42+
}
43+
} else {
44+
processedDirs.push_back(dir);
45+
}
46+
}
47+
}
48+
49+
void processRelative(vector<string>& dirs, vector<string>& processedDirs) {
50+
for (string dir : dirs) {
51+
if (dir == ".." && !processedDirs.empty() && processedDirs.back() != "..") {
52+
processedDirs.pop_back();
53+
} else {
54+
processedDirs.push_back(dir);
55+
}
56+
}
57+
}
58+
59+
void stripPath(const string& path, vector<string>& dirs) {
60+
string curr = "";
61+
for (int i = 0; i <= path.size(); i++) {
62+
if ((i == path.size() || path[i] == '/')) {
63+
if (!curr.empty() && curr != ".") {
64+
dirs.push_back(curr);
65+
}
66+
curr.clear();
67+
} else {
68+
curr += path[i];
69+
}
70+
}
71+
}
72+
573
string ShortestEquivalentPath(const string& path) {
6-
// TODO - you fill in here.
7-
return "";
74+
if (path.empty()) {
75+
return path;
76+
}
77+
bool isAbsolute = (path[0] == '/');
78+
vector<string> dirs, processedDirs;
79+
stripPath(path, dirs);
80+
isAbsolute ? processAbsolute(dirs, processedDirs)
81+
: processRelative(dirs, processedDirs);
82+
return assembleFinalPath(processedDirs, isAbsolute);
883
}
984

1085
int main(int argc, char* argv[]) {
86+
/*
87+
ShortestEquivalentPath("");
88+
ShortestEquivalentPath("home");
89+
ShortestEquivalentPath("home/foobar");
90+
ShortestEquivalentPath("../home/foobar");
91+
ShortestEquivalentPath("../../home/foobar");
92+
ShortestEquivalentPath("../../home/../foobar");
93+
ShortestEquivalentPath("/");
94+
ShortestEquivalentPath("/../../");
95+
ShortestEquivalentPath("/home");
96+
ShortestEquivalentPath("/home/foobar/");
97+
ShortestEquivalentPath("/../home/foobar/");
98+
ShortestEquivalentPath("/../../home/foobar");
99+
ShortestEquivalentPath("/../../home/../foobar");
100+
ShortestEquivalentPath("/.");
101+
*/
102+
11103
std::vector<std::string> args{argv + 1, argv + argc};
12104
std::vector<std::string> param_names{"path"};
13105
return GenericTestMain(args, "directory_path_normalization.cc",
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
#include <deque>
2+
#include <stack>
3+
#include <string>
4+
5+
#include "test_framework/generic_test.h"
6+
using std::deque;
7+
using std::stack;
8+
using std::string;
9+
10+
/*
11+
- Cases:
12+
- absolute path (begins with /)
13+
- relative path (no prefix /)
14+
15+
- Tokens:
16+
- ".."
17+
- relative: if the top of the (nonempty) stack is not "..", should pop.
18+
Otherwise, push it.
19+
- nonrelative: always pop the top of the (nonempty) stack
20+
- "."
21+
- represents current dir; can be ignored
22+
- ""
23+
- represents "//"; can be ignored (or treated as ".")
24+
- (any chars)
25+
- represents a directory name. Has to be pushed, may be removed.
26+
*/
27+
28+
#define PARENT_DIR ".."
29+
#define CURR_DIR "."
30+
#define CONTINUE_PARSING 1
31+
#define HALT_PARSING 0
32+
33+
string assemblePath(stack<string, deque<string>>& s, bool isAbsolute) {
34+
if (s.empty()) {
35+
return "";
36+
}
37+
string path = "";
38+
while (!s.empty()) {
39+
path = s.top() + "/" + path;
40+
s.pop();
41+
}
42+
path.erase(path.end() - 1);
43+
path = ((isAbsolute) ? "/" : "") + path;
44+
printf("Final path: %s\n", path.c_str());
45+
46+
return path;
47+
}
48+
49+
void handleDirRelative(stack<string>& s, const string& dir) {
50+
if (dir == "..") {
51+
if (s.empty() || s.top() == "..") {
52+
s.push(dir);
53+
} else {
54+
s.pop();
55+
}
56+
} else if (!(dir == ".") && !(dir == "")) {
57+
s.push(dir);
58+
}
59+
}
60+
61+
void handleDirAbsolute(stack<string>& s, const string& dir) {
62+
if (dir == ".." && !s.empty()) {
63+
s.pop();
64+
} else if (!(dir == ".") && !(dir == "")) {
65+
s.push(dir);
66+
}
67+
}
68+
69+
string ShortestEquivalentPath(const string& path) {
70+
if (path.empty()) {
71+
return "";
72+
}
73+
printf("\nInitial path: %s\n", path.c_str());
74+
stack<string> s;
75+
bool isAbsolute = (path[0] == '/');
76+
string currPath = path;
77+
78+
auto begin_it = path.begin(), end_it = path.begin();
79+
for (int i = 0; i < path.size(); i++) {
80+
// printf("i: %d\n", i);
81+
if (path[i] == '/' || i == path.size() - 1) {
82+
end_it = path.begin() + i;
83+
string dir(begin_it, end_it);
84+
// printf("dir: %s\n", dir.c_str());
85+
isAbsolute ? handleDirAbsolute(s, dir) : handleDirRelative(s, dir);
86+
begin_it = end_it + 1;
87+
}
88+
}
89+
90+
return assemblePath(s, isAbsolute);
91+
}
92+
93+
int main(int argc, char* argv[]) {
94+
/*
95+
ShortestEquivalentPath("");
96+
ShortestEquivalentPath("home");
97+
ShortestEquivalentPath("home/foobar");
98+
ShortestEquivalentPath("../home/foobar");
99+
ShortestEquivalentPath("../../home/foobar");
100+
ShortestEquivalentPath("../../home/../foobar");
101+
*/
102+
ShortestEquivalentPath("/");
103+
ShortestEquivalentPath("/../../");
104+
ShortestEquivalentPath("/home");
105+
ShortestEquivalentPath("/home/foobar/");
106+
ShortestEquivalentPath("/../home/foobar/");
107+
ShortestEquivalentPath("/../../home/foobar");
108+
ShortestEquivalentPath("/../../home/../foobar");
109+
/*
110+
std::vector<std::string> args{argv + 1, argv + argc};
111+
std::vector<std::string> param_names{"path"};
112+
return GenericTestMain(args, "directory_path_normalization.cc",
113+
"directory_path_normalization.tsv",
114+
&ShortestEquivalentPath, DefaultComparator{},
115+
param_names);
116+
*/
117+
}

elements-of-programming-interviews/cpp/evaluate_rpn.cc

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,93 @@
1+
#include <stack>
12
#include <string>
23

34
#include "test_framework/generic_test.h"
5+
using std::cout;
6+
using std::endl;
7+
using std::stack;
48
using std::string;
9+
10+
/*
11+
Cases:
12+
- Empty string
13+
- String of the following, comma separated (valid/well formed)
14+
- Last item in string won't be followed by comma
15+
- Integers, possibly prefixed with -
16+
- A B (op) expression; op can be + / * -
17+
- Division should be integer division, rounded down
18+
19+
Examples:
20+
- "-356" -> -356
21+
- "2,3,*" -> 6
22+
- "2,3,*,2,3,*,*" -> 36
23+
24+
Approach:
25+
- Helper function for converting num strings to ints (stoi?)
26+
- Helper for determining symbol or int
27+
- Once we have literal values, can just push to stack and pop/combine/repush
28+
on operators
29+
30+
*/
31+
32+
void applyOperator(const string& expr, stack<int>& data) {
33+
int op2 = data.top();
34+
data.pop();
35+
int op1 = data.top();
36+
data.pop();
37+
38+
int val;
39+
switch (expr[0]) {
40+
case '+':
41+
// printf("pushing %d\n", op1 + op2);
42+
data.push(op1 + op2);
43+
break;
44+
case '-':
45+
data.push(op1 - op2);
46+
break;
47+
case '*':
48+
data.push(op1 * op2);
49+
break;
50+
case '/':
51+
data.push(op1 / op2);
52+
break;
53+
}
54+
}
55+
56+
bool isOperator(const string& expr) {
57+
return expr == "-" || expr == "+" || expr == "/" || expr == "*";
58+
}
59+
560
int Evaluate(const string& expression) {
6-
// TODO - you fill in here.
7-
return 0;
61+
stack<int> data;
62+
auto start_it = expression.begin(), end_it = expression.begin();
63+
for (int i = 0; i <= expression.length(); i++) {
64+
if (expression[i] != ',' && i != expression.length()) {
65+
continue;
66+
}
67+
end_it = expression.begin() + i;
68+
string substr(start_it, end_it);
69+
if (!isOperator(substr)) {
70+
// cout << "i: " << i << endl;
71+
// cout << "pushing val: " << substr << endl;
72+
data.push(stoi(substr));
73+
} else {
74+
// cout << "Applying operator: " << substr << endl;
75+
applyOperator(substr, data);
76+
}
77+
start_it = end_it + 1;
78+
}
79+
80+
return data.top();
881
}
982

1083
int main(int argc, char* argv[]) {
84+
/*
85+
printf("\n%d\n", Evaluate("3"));
86+
printf("%d\n", Evaluate("-3"));
87+
printf("%d\n", Evaluate("3,3,+"));
88+
printf("%d\n", Evaluate("3,3,+,50,-2,*,+"));
89+
*/
90+
1191
std::vector<std::string> args{argv + 1, argv + argc};
1292
std::vector<std::string> param_names{"expression"};
1393
return GenericTestMain(args, "evaluate_rpn.cc", "evaluate_rpn.tsv", &Evaluate,

elements-of-programming-interviews/cpp/sunset_view.cc

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,41 @@
22
#include <vector>
33

44
#include "test_framework/generic_test.h"
5+
using std::pair;
56
using std::vector;
7+
8+
/*
9+
Cases:
10+
- Every building equal/ gets taller than previous; only last can view
11+
- Every building gets shorter; all can see it
12+
- Any time a taller building comes in, any previous shorter one can no longer
13+
see and nothing changes this
14+
- If building is shorter than top, push it.
15+
- If a building is equal or taller than top, pop until empty or we reach one
16+
that's taller, then push.
17+
O(n) space, O(n) time (evaluate, push, and pop almost every element)
18+
*/
19+
620
vector<int> ExamineBuildingsWithSunset(
721
vector<int>::const_iterator sequence_begin,
822
const vector<int>::const_iterator& sequence_end) {
9-
// TODO - you fill in here.
10-
return {};
23+
vector<pair<int, int>> s;
24+
int i = 0;
25+
for (auto it = sequence_begin; it != sequence_end; i++, it++) {
26+
if (s.empty() || s.back().first > *it) {
27+
s.push_back({*it, i});
28+
} else {
29+
while (!s.empty() && s.back().first <= *it) {
30+
s.pop_back();
31+
}
32+
s.push_back({*it, i});
33+
}
34+
}
35+
vector<int> final;
36+
for (auto it = s.rbegin(); it != s.rend(); it++) {
37+
final.push_back(it->second);
38+
}
39+
return final;
1140
}
1241
vector<int> ExamineBuildingsWithSunsetWrapper(const vector<int>& sequence) {
1342
return ExamineBuildingsWithSunset(cbegin(sequence), cend(sequence));

elements-of-programming-interviews/problem_mapping.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -888,7 +888,7 @@ problem_mapping = {
888888
},
889889
"8.02 Evaluate RPN expressions": {
890890
"C++: evaluate_rpn.cc": {
891-
"passed": 0,
891+
"passed": 108,
892892
"total": 108
893893
},
894894
"Java: EvaluateRpn.java": {
@@ -916,7 +916,7 @@ problem_mapping = {
916916
},
917917
"8.04 Normalize pathnames": {
918918
"C++: directory_path_normalization.cc": {
919-
"passed": 0,
919+
"passed": 255,
920920
"total": 255
921921
},
922922
"Java: DirectoryPathNormalization.java": {
@@ -930,7 +930,7 @@ problem_mapping = {
930930
},
931931
"8.05 Compute buildings with a sunset view": {
932932
"C++: sunset_view.cc": {
933-
"passed": 0,
933+
"passed": 101,
934934
"total": 101
935935
},
936936
"Java: SunsetView.java": {

0 commit comments

Comments
 (0)