Skip to content

Commit 263db38

Browse files
committed
first try baby
0 parents  commit 263db38

File tree

4 files changed

+169
-0
lines changed

4 files changed

+169
-0
lines changed

build.sh

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#! /usr/bin/bash
2+
g++ ./src/main.cpp -o cppcompute

cppcompute

75.2 KB
Binary file not shown.

dev.sh

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#! /bin/bash
2+
./build.sh
3+
./cppcompute "1 + 2"
4+
while inotifywait -qq -e modify,create,delete ./src; do
5+
clear
6+
if [ -n "$pid" ] && [ -e /proc/$pid ]; then
7+
kill "$pid"
8+
fi
9+
./build.sh
10+
./cppcompute "1 + 2"
11+
done

src/main.cpp

+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#include <array>
2+
#include <cmath>
3+
#include <iostream>
4+
#include <iterator>
5+
#include <string>
6+
#include <vector>
7+
8+
//slices a vector, it's templated so that I may copy this for future needs
9+
template <typename T>
10+
std::vector<T> slice_vec(const std::vector<T> &vec, int start, int end){
11+
if(end < start) return std::vector<T>();
12+
start = std::max(0, start);
13+
end = std::min((int)vec.size(), end);
14+
std::vector<T> res(end - start);
15+
copy(vec.begin() + start, vec.begin() + end, res.begin());
16+
return res;
17+
}
18+
19+
//simple array that contains supported operation symbols
20+
const std::array<std::string, 6> supportedOperations = {"+", "-", "*", "/", "^","x"};
21+
22+
//determines if the c char is an operation character
23+
bool testOperation(std::string c){
24+
for(const auto t : supportedOperations){
25+
if(t == c) return true;
26+
}
27+
return false;
28+
}
29+
30+
//lv= left value, op= operation, rv= right value
31+
//simply computes one basic operation
32+
float simple_compute(std::string lv, std::string op, std::string rv){
33+
float nlv = std::stof(lv);
34+
float nrv = std::stof(rv);
35+
if(op == "+") return nlv + nrv;
36+
if(op == "-") return nlv - nrv;
37+
if(op == "*" || op == "x") return nlv * nrv;
38+
if(op == "/") return nlv / nrv;
39+
if(op == "^") return std::pow(nlv, nrv);
40+
41+
throw std::runtime_error("invalid operation: " + op);
42+
}
43+
44+
//main compute function, it accepts a string to compute and it parses it.
45+
//it will also call itself recursively to compute subcomputetions defined with () brakets.
46+
float compute(std::string computation){
47+
//in segments_vec I will add the components of of the computations.
48+
//components can only be numbers or operations,
49+
//brakets will be pre-computed into a number before pushing to the vector
50+
std::vector<std::string> segments_vec;
51+
52+
std::string numeric_cursor = "";
53+
std::string subcomputation = "";
54+
55+
//depth value is used to track brakets levels
56+
unsigned short depth = 0;
57+
58+
bool toNegate = false;
59+
60+
for(char c : computation){
61+
if(c == ' ') continue;
62+
//if opening braket, then increase depth
63+
if(c == '(') {
64+
//if no longer operating on depth 0, then add the braket to the subcomputation
65+
if(depth > 0) subcomputation += c;
66+
depth++;
67+
continue;
68+
}
69+
if(c == ')') {
70+
depth--;
71+
//if we reached back depth 0, compute subcomputation
72+
if(depth == 0) {
73+
const auto res = compute(subcomputation);
74+
75+
76+
segments_vec.push_back(std::to_string(res * (toNegate ? -1 : 1)));
77+
toNegate = false;
78+
subcomputation.clear();
79+
}
80+
//else add closing braket to subcomputation.
81+
else subcomputation += c;
82+
continue;
83+
}
84+
if(depth > 0) {
85+
//if not operating on depth 0, then just add characters to the subcomputation stirng
86+
subcomputation += c;
87+
continue;
88+
}
89+
//if character is numeric or . then add it to the numeric_cursor
90+
//nothing will happen if a _ or other characters are in the middle, so 1_000 and 1,000 are valid numbers
91+
if((c >= '0' && c <= '9') || c == '.') numeric_cursor += c;
92+
else if(numeric_cursor.length()) {
93+
const auto insertion = std::stof(numeric_cursor) * (toNegate ? -1 : 1);
94+
segments_vec.push_back(std::to_string(insertion));
95+
toNegate = false;
96+
numeric_cursor.clear();
97+
}
98+
//if a - symbol is encountered, and the last segment added was another operation...
99+
//then I assume that user wants to negate the following value in the computation.
100+
if(c == '-' && testOperation(segments_vec.back())){
101+
toNegate = true;
102+
103+
}
104+
//adding computation symbol to the vec
105+
else if(testOperation(std::string() + c)){
106+
segments_vec.push_back(std::string() + c);
107+
108+
}
109+
}
110+
//if numeric_cursor is not empty, at the end, I push it to the array
111+
if(numeric_cursor.length()) {
112+
const auto insertion = std::stof(numeric_cursor) * (toNegate ? -1 : 1);
113+
114+
segments_vec.push_back(std::to_string(insertion));
115+
}
116+
117+
118+
//this lambda function finds the first operation to compute
119+
//pow operation has prio, multiplication and division have secondary prio
120+
//if there is not pow, multiplication or division, I simply return 1
121+
//1 assumes that the first operation to compute is at idx 1
122+
const auto searchNextPivot = [](const std::vector<std::string> &vec){
123+
for(int i = 1; i < vec.size(); i += 2){
124+
if(vec[i] == "^") return i;
125+
}
126+
127+
for(int i = 1; i < vec.size(); i += 2){
128+
if(vec[i] == "*" || vec[i] == "/" || vec[i] == "x") return i;
129+
}
130+
return 1;
131+
};
132+
133+
//until my segments_vec is not empty, find the prio computation and compute itself
134+
while(segments_vec.size() > 1){
135+
const int pivot = searchNextPivot(segments_vec);
136+
137+
const auto head = slice_vec(segments_vec, 0, pivot - 1);
138+
const auto tail = slice_vec(segments_vec, pivot + 2, segments_vec.size());
139+
const auto needle = std::to_string(
140+
simple_compute(segments_vec[pivot - 1], segments_vec[pivot], segments_vec[pivot + 1])
141+
);
142+
143+
//replacing the 3 segments involved in the last computation with the result of it.
144+
segments_vec.clear();
145+
segments_vec.insert(segments_vec.end(), head.begin(), head.end());
146+
segments_vec.push_back(needle);
147+
segments_vec.insert(segments_vec.end(), tail.begin(), tail.end());
148+
}
149+
return std::stof(segments_vec[0]);
150+
}
151+
152+
int main(int argc, char* argv[]){
153+
// so proud! :D
154+
std::string computation = argv[1];
155+
std::cout << computation << " = " << compute(computation) << std::endl;
156+
}

0 commit comments

Comments
 (0)