Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 120 additions & 82 deletions Formula evaluator/Formula evaluator.cpp
Original file line number Diff line number Diff line change
@@ -1,105 +1,143 @@
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <cctype> // for std::isspace, std::tolower
#include <sstream>

using namespace std;

// trim whitespace from both ends
string trim(const string& str) {
size_t first = str.find_first_not_of(" \t\n\r");
if (first == string::npos)
return "";

size_t last = str.find_last_not_of(" \t\n\r");
return str.substr(first, last - first + 1);
}

auto trim = [](string& s) {
s.erase(remove_if(s.begin(), s.end(), ::isspace), s.end());
};
// remove all whitespace and parentheses, make lowercase
string normalize(const string& s) {
string result;
result.reserve(s.size());

string trimz(const string& s) {
string result;
for (char c : s) {
if (!isspace(c) && c != '(' && c != ')') {
result.push_back(c);
}
for (char ch : s) {
if (!isspace(static_cast<unsigned char>(ch)) && ch != '(' && ch != ')') {
result += tolower(static_cast<unsigned char>(ch));
}
return result;
}
vector<string> splitFactors(const string & expr) {
vector<string> parts;
string token;
stringstream ss(expr);
while (getline(ss, token, '*')) {
if (!token.empty()) parts.push_back(token);
return result;
}

// split them by '*' and normalize each factor
vector<string> split_and_normalize_factors(const string& expr) {
vector<string> factors;
stringstream ss(expr);
string token;

while (getline(ss, token, '*')) {
string cleaned = normalize(token);
if (!cleaned.empty()) {
factors.push_back(cleaned);
}
return parts;
}
//TODO: make it not case sensitive
int main() {
auto trim = [](string& s) {
s.erase(remove_if(s.begin(), s.end(), ::isspace), s.end());
};
string formula;
cout << "Enter a formula (e.g., R = (rho * L) / A):" << endl;
getline(cin, formula);

string target;
cout << "Which variable do you want to isolate? ";
cin >> target;

size_t eqPos = formula.find('=');
if (eqPos == string::npos) {
cout << "Invalid formula." << endl;
return 0;
}
return factors;
}

string left = trimz(formula.substr(0, eqPos));
string right = trimz(formula.substr(eqPos + 1));
string join_factors(const vector<string>& factors, const string& sep = " * ") {
if (factors.empty()) return "1";

if (left == target) {
cout << target << " = " << right << endl;
return 0;
}
string result = factors[0];
for (size_t i = 1; i < factors.size(); ++i) {
result += sep + factors[i];
}
return result;
}

int main() {
string full_formula;
cout << "Enter formula (e.g. R = (rho * L) / A): ";
getline(cin, full_formula);

string target;
cout << "Variable to isolate: ";
cin >> target;
cin.ignore(); // consume newline after cin >>

// normalize target for comparison
string target_norm = normalize(target);
if (target_norm.empty()) {
cout << "Invalid variable name.\n";
return 1;
}

size_t eq_pos = full_formula.find('=');
if (eq_pos == string::npos) {
cout << "Formula must contain '=' sign.\n";
return 1;
}

string left_side = trim(full_formula.substr(0, eq_pos));
string right_side = trim(full_formula.substr(eq_pos + 1));

string numerator = right, denominator = "1";
size_t divPos = right.find('/');
if (divPos != string::npos) {
numerator = right.substr(0, divPos);
denominator = right.substr(divPos + 1);
string left_norm = normalize(left_side);
string right_norm = normalize(right_side);

// early exit target is already on left
if (left_norm == target_norm) {
cout << target << " = " << right_side << "\n";
return 0;
}

// find division (only supported though)
size_t div_pos = right_side.find('/');
string numerator_str = right_side;
string denominator_str = "1";

if (div_pos != string::npos) {
numerator_str = trim(right_side.substr(0, div_pos));
denominator_str = trim(right_side.substr(div_pos + 1));
}

// get normalized factors
auto num_factors = split_and_normalize_factors(numerator_str);
auto den_factors = split_and_normalize_factors(denominator_str);

// in numerator
auto it_num = find(num_factors.begin(), num_factors.end(), target_norm);
if (it_num != num_factors.end()) {
num_factors.erase(it_num);

cout << target << " = " << left_side;

if (!den_factors.empty()) {
cout << " * (" << join_factors(den_factors) << ")";
}

numerator = trimz(numerator);
denominator = trimz(denominator);

vector<string> numFactors = splitFactors(numerator);
vector<string> denFactors = splitFactors(denominator);

auto it = find(numFactors.begin(), numFactors.end(), target);
if (it != numFactors.end()) {
numFactors.erase(it);
cout << target << " = (" << left << " * " << denominator << ")";
if (!numFactors.empty()) {
cout << " / (";
for (size_t i = 0; i < numFactors.size(); i++) {
if (i > 0) cout << " * ";
cout << numFactors[i];
}
cout << ")";
}
cout << endl;
return 0;
if (!num_factors.empty()) {
cout << " / (" << join_factors(num_factors) << ")";
}

it = find(denFactors.begin(), denFactors.end(), target);
if (it != denFactors.end()) {
denFactors.erase(it);
cout << target << " = (" << numerator << ")";
if (!denFactors.empty()) {
cout << " / (";
for (size_t i = 0; i < denFactors.size(); i++) {
if (i > 0) cout << " * ";
cout << denFactors[i];
}
cout << ")";
}
cout << " / " << left << endl;
return 0;
cout << "\n";
return 0;
}

// target in denominator
auto it_den = find(den_factors.begin(), den_factors.end(), target_norm);
if (it_den != den_factors.end()) {
den_factors.erase(it_den);

cout << target << " = (" << numerator_str << ")";

if (!den_factors.empty()) {
cout << " / (" << join_factors(den_factors) << ")";
}

cout << "Variable not found." << endl;
cout << " / " << left_side << "\n";
return 0;
}

cout << "Variable '" << target << "' not found in the formula.\n";
return 1;
}