diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62bfaf2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.vs + +bin-int/ \ No newline at end of file diff --git a/QuicMaf.sln b/QuicMaf.sln new file mode 100644 index 0000000..b25ee7f --- /dev/null +++ b/QuicMaf.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.28307.329 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "QuicMaf", "QuicMaf\QuicMaf.vcxproj", "{EA73D661-B6EB-4156-AC92-A470A6683307}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {EA73D661-B6EB-4156-AC92-A470A6683307}.Debug|x64.ActiveCfg = Debug|x64 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Debug|x64.Build.0 = Debug|x64 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Debug|x86.ActiveCfg = Debug|Win32 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Debug|x86.Build.0 = Debug|Win32 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x64.ActiveCfg = Release|x64 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x64.Build.0 = Release|x64 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x86.ActiveCfg = Release|Win32 + {EA73D661-B6EB-4156-AC92-A470A6683307}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {736D3806-EB68-4CBF-9C9F-0E50940C4F53} + EndGlobalSection +EndGlobal diff --git a/QuicMaf/EquationAdv.cpp b/QuicMaf/EquationAdv.cpp new file mode 100644 index 0000000..0cb8380 --- /dev/null +++ b/QuicMaf/EquationAdv.cpp @@ -0,0 +1,12 @@ +#include "EquationAdv.h" + + + +EquationAdv::EquationAdv() +{ +} + + +EquationAdv::~EquationAdv() +{ +} diff --git a/QuicMaf/EquationAdv.h b/QuicMaf/EquationAdv.h new file mode 100644 index 0000000..4fab2a7 --- /dev/null +++ b/QuicMaf/EquationAdv.h @@ -0,0 +1,8 @@ +#pragma once +class EquationAdv +{ +public: + EquationAdv(); + ~EquationAdv(); +}; + diff --git a/QuicMaf/QuicMaf.vcxproj b/QuicMaf/QuicMaf.vcxproj new file mode 100644 index 0000000..f1f9820 --- /dev/null +++ b/QuicMaf/QuicMaf.vcxproj @@ -0,0 +1,139 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {EA73D661-B6EB-4156-AC92-A470A6683307} + QuicMaf + 10.0.17763.0 + + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + Application + true + v141 + MultiByte + + + Application + false + v141 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + $(SolutionDir)bin\$(Configuration)-$(Platform)\ + $(SolutionDir)bin-int\$(Configuration)-$(Platform)\ + + + + Level3 + Disabled + true + true + + + + + Level3 + Disabled + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + + + + + Level3 + MaxSpeed + true + true + true + true + + + true + true + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/QuicMaf/QuicMaf.vcxproj.filters b/QuicMaf/QuicMaf.vcxproj.filters new file mode 100644 index 0000000..a0aa6f2 --- /dev/null +++ b/QuicMaf/QuicMaf.vcxproj.filters @@ -0,0 +1,57 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/QuicMaf/QuicMaf.vcxproj.user b/QuicMaf/QuicMaf.vcxproj.user new file mode 100644 index 0000000..0b0f24d --- /dev/null +++ b/QuicMaf/QuicMaf.vcxproj.user @@ -0,0 +1,6 @@ + + + + true + + \ No newline at end of file diff --git a/QuicMaf/app.cpp b/QuicMaf/app.cpp new file mode 100644 index 0000000..6579b62 --- /dev/null +++ b/QuicMaf/app.cpp @@ -0,0 +1,8 @@ + +#include "maths/Equation.h" + +int main() { + auto terms = split_terms("(4 + 2(2)) + 123 = 131x"); + + return true; +} \ No newline at end of file diff --git a/QuicMaf/maths/Equation.h b/QuicMaf/maths/Equation.h new file mode 100644 index 0000000..be5a4f7 --- /dev/null +++ b/QuicMaf/maths/Equation.h @@ -0,0 +1,128 @@ +#ifndef EQUATION_H +#define EQUATION_H +#pragma once + +using namespace std; +#include "terms/Term.h" +#include "terms/Brackets.h" +#include "terms/Constant.h" +#include "terms/Operator.h" +#include "terms/Variable.h" +#include "terms/Equal.h" + +#include "terms/term_parser.h" + +class Equation { +public: + vector lwing; + vector rwing; + + string Parse(std::string equation) { + + /* ALL OF THE COMMENTS GOT FROM THE NOTES.PARSING.ALGORITHM */ + + // - split the terms in the term of spaces + auto semi_terms = split(equation, " "); + + bool lwing_turn = true; + // - iterate over the terms + for (int i = 0; i < semi_terms.size(); i++) { + // , call the iterator mTerm: + auto term = semi_terms[i]; + // - if there exists an opening bracket in the mTerm + if (isContain(term, '(')) { + // find the closing. + vector terms_with_cbrack; + for (; i < semi_terms.size(); i++) { + if (isContain(semi_terms[i], ')')) { + terms_with_cbrack.push_back(semi_terms[i]); + break; + } + terms_with_cbrack.push_back(semi_terms[i]); + } + auto bracket = parseBracket(term, terms_with_cbrack); + (lwing_turn) ? lwing.push_back(bracket) : rwing.push_back(bracket); + continue; + } + auto _term = convertNormalToTerm(term); + if (_term->GetType() == TermTypes::Equ) { + lwing_turn = !lwing_turn; + continue; + } + + (lwing_turn) ? lwing.push_back(_term) : rwing.push_back(_term); + } + + return equation; + } +public: + Bracket* parseBracket(string str1, vector terms_with_cbrack) { + Bracket *bracket = nullptr; + bracket = new Bracket(); + + auto splitted = split(str1, "("); + string coefficient = splitted[0]; + + // convert coefficient to a term + if (coefficient != "") + bracket->setConstant((Term*)convertNormalToTerm(coefficient)); + + if (splitted.size() > 1) { + for (int i = 1; i < splitted.size(); i++) { + auto term = (Term*)convertNormalToTerm(splitted[i]); + bracket->mTerms.push_back(term); + } + } + + // terms: + for (int i = 1; i < terms_with_cbrack.size(); i++) { + auto term = terms_with_cbrack[i]; + if (isContain(term, ')')) { + term.erase(indexofChar(term, ')')); + bracket->mTerms.push_back(convertNormalToTerm(term)); + break; + } + bracket->mTerms.push_back(convertNormalToTerm(term)); + } + + return bracket; + } + + Term* convertNormalToTerm(string str) { + if (isContain(str, '^')) { + auto coeffic_terms = split(str, "^"); + if (isContainAlph(str)) { + auto terms = split(str, "^"); + Variable *var = nullptr; + var = new Variable(atof(&terms[0][0]), terms[0][indexofAlph(terms[0])], atof(&terms[1][0])); + return var; + } + else if (is_all_digits(coeffic_terms[0]) && is_all_digits(coeffic_terms[1])) { + Constant *Const = nullptr; + Const = new Constant(atof(&coeffic_terms[0][0]), atof(&coeffic_terms[1][0])); + return Const; + } + } + else if (is_all_digits(str)) { + Constant *Const = nullptr; + Const = new Constant(atof(&str[0])); + return Const; + } + else if (isContainAlph(str)) { + Variable *var = nullptr; + var = new Variable(atof(&str[0]), str[indexofAlph(str)]); + return var; + } + else if (isArithmitic(str[0])) { + Operator *op = nullptr; + op = new Operator(str[0]); + return op; + } + else if (isEqualChar(str[0])) { + Equal* equ = nullptr; + equ = new Equal(); + return equ; + } + } +}; +#endif // !EQUATION_H diff --git a/QuicMaf/maths/defines.h b/QuicMaf/maths/defines.h new file mode 100644 index 0000000..60e79bc --- /dev/null +++ b/QuicMaf/maths/defines.h @@ -0,0 +1,117 @@ +#ifndef DEFINES_H +#define DEFINES_H + +#include +#include +#include +#include + +#define DEF_C -999 +#define DEF_N 0.0 +typedef double NValue; +typedef char CValue; + +enum TermTypes { + None, + Const, + Var, + Op, + Brack, + Equ, +}; + + +// for string delimiter +vector split(string s, string delimiter) { + size_t pos_start = 0, pos_end, delim_len = delimiter.length(); + string token; + vector res; + + while ((pos_end = s.find(delimiter, pos_start)) != string::npos) { + token = s.substr(pos_start, pos_end - pos_start); + pos_start = pos_end + delim_len; + res.push_back(token); + } + + res.push_back(s.substr(pos_start)); + return res; +} + + +void removeSubstrs(string& s, string& p) { + string::size_type n = p.length(); + for (string::size_type i = s.find(p); + i != string::npos; + i = s.find(p)) + s.erase(i, n); +} + + +bool isArithmitic(char c) { + if (c == '-') return true; + if (c == '+') return true; + if (c == '/') return true; + if (c == '*') return true; + return false; +} + +bool isEqualChar(char c) { + if (c == '=') return true; + return false; +} +bool isBrackets(char c) { + if (c == '(') return true; + return false; +} + +bool isContain(string str, char c) { + for (int i = 0; i < str.size(); i++) if (str[i] == c) return true; + return false; +} + +bool isContainAlph(string str) { + for (int i = 0; i < str.size(); i++) + if (isalpha(str[i])) return true; + return false; +} + +bool isContainDigit(string str) { + for (int i = 0; i < str.size(); i++) + if (isdigit(str[i])) return true; + return false; +} + +int indexofAlph(string str) { + if (!isContainAlph(str)) return -1; + + for (int i = 0; i < str.size(); i++) + if (isalpha(str[i])) + return i; + + return-1; +} + +int indexofChar(string str, char c) { + for (int i = 0; i < str.size(); i++) + if (str[i] == c) return i; + return -1; +} + + +bool is_all_digits(const std::string &str) +{ + return std::all_of(str.begin(), str.end(), ::isdigit); // C++11 +} + +int getTermType(string str) { + if (isContain(str, '=')) return Equ; + if (isContain(str, '+')) return Op; + if (isContain(str, '-')) return Op; + if (isContain(str, '/')) return Op; + if (isContain(str, '*')) return Op; + + if (is_all_digits(str)) return Const; + else return Var; +} + +#endif // ! diff --git a/QuicMaf/maths/terms/Brackets.h b/QuicMaf/maths/terms/Brackets.h new file mode 100644 index 0000000..5f020ef --- /dev/null +++ b/QuicMaf/maths/terms/Brackets.h @@ -0,0 +1,28 @@ +#ifndef BRACKET_H +#define BRACKET_H +#pragma once + +#include "Term.h" +#include "Variable.h" +#include "../defines.h" +#include "Constant.h" +using namespace std; + +class Bracket : public Term { +public: + Bracket() { + Term(); + mType = TermTypes::Brack; + mConstant = new Constant(1); + } + + vector mTerms; + + void setConstant(Term* constant) { + mConstant = constant; + } + +private: + Term *mConstant; +}; +#endif // !BRACKET_H diff --git a/QuicMaf/maths/terms/Constant.h b/QuicMaf/maths/terms/Constant.h new file mode 100644 index 0000000..068dba1 --- /dev/null +++ b/QuicMaf/maths/terms/Constant.h @@ -0,0 +1,17 @@ +#ifndef CONSTANT_H +#define CONSTANT_H +#pragma once +#include "../defines.h" +#include "Term.h" +using namespace std; + +class Constant : public Term { +public: + Constant(NValue val = 0, NValue pwr = 1) { + Term(); + mValue = val; + mPower = pwr; + mType = TermTypes::Const; + } +}; +#endif // !CONSTANT_H diff --git a/QuicMaf/maths/terms/Equal.h b/QuicMaf/maths/terms/Equal.h new file mode 100644 index 0000000..d4ac55f --- /dev/null +++ b/QuicMaf/maths/terms/Equal.h @@ -0,0 +1,16 @@ +#ifndef EQUAL_H +#define EQUAL_H +#pragma once + +using namespace std; +#include "Term.h" +#include "../defines.h" + +class Equal : public Term { +public: + Equal() { + mType = TermTypes::Equ; + } +}; + +#endif // !EQUAL_H diff --git a/QuicMaf/maths/terms/Operator.h b/QuicMaf/maths/terms/Operator.h new file mode 100644 index 0000000..8ba40f0 --- /dev/null +++ b/QuicMaf/maths/terms/Operator.h @@ -0,0 +1,16 @@ +#ifndef OPERATOR_H +#define OPERATOR_H +#pragma once + +using namespace std; +#include "Term.h" +#include "../defines.h" + +class Operator : public Term { +public: + Operator(CValue oper) : Term() { + mOperator = oper; + mType = TermTypes::Op; + } +}; +#endif // !OPERATOR_ diff --git a/QuicMaf/maths/terms/Term.h b/QuicMaf/maths/terms/Term.h new file mode 100644 index 0000000..4f56d4e --- /dev/null +++ b/QuicMaf/maths/terms/Term.h @@ -0,0 +1,30 @@ +#ifndef TERM_H +#define TERM_H + +#pragma once +#include "../defines.h" +using namespace std; + +class Term { +public: + virtual NValue GetValue() { return mValue; } + virtual CValue GetVariable() { return mVariable; } + virtual CValue GetOperator() { return mOperator; } + virtual NValue GetPower() { return mPower; } + + virtual int GetType() { return mType; }; +public: + Term(NValue val = DEF_N, CValue var = DEF_C, CValue oper = DEF_C, NValue pwr = 1) { + mValue = val; + mVariable = var; + mOperator = oper; + mPower = pwr; + } + + NValue mValue = DEF_N; + CValue mVariable = DEF_C; + CValue mOperator = DEF_C; + NValue mPower = 1; + int mType = -1; +}; +#endif // !TERM_H diff --git a/QuicMaf/maths/terms/Variable.h b/QuicMaf/maths/terms/Variable.h new file mode 100644 index 0000000..a534085 --- /dev/null +++ b/QuicMaf/maths/terms/Variable.h @@ -0,0 +1,19 @@ +#ifndef VARIABLE_H +#define VARIABLE_H +#pragma once +#include "Term.h" +#include "../defines.h" + +using namespace std; + +class Variable : public Term { +public: + Variable(NValue val = 0, CValue var = DEF_C, NValue pwr = 1) { + mValue = val; + mVariable = var; + mPower = pwr; + mType = TermTypes::Var; + } + +}; +#endif // !VARIABLE_H diff --git a/QuicMaf/maths/terms/term_parser.h b/QuicMaf/maths/terms/term_parser.h new file mode 100644 index 0000000..7679a4e --- /dev/null +++ b/QuicMaf/maths/terms/term_parser.h @@ -0,0 +1,132 @@ +#ifndef TERM_PARSER_H +#define TERM_PARSER_H +#pragma once +#include "../defines.h" +using namespace std; + +/* + The goal of this class is to tokenize a string of equation and splits + it to mathematical term, with brackets begin a complete terms alone. + Ex: + 2(5 + 9) - 56=90 + If the above input was given to the main function in this class it must give an output of: + vector: + - 2(5 + 9) + - - + - 56 + - = + - 90 +*/ + +struct Token { + unsigned int begin = 0; + unsigned int end = 0; +}; + +string retrieveSubString(string str, Token token) { + string res; + for (int i = token.begin; i < token.end; i++) + res.push_back(str[i]); + return res; +} + +struct Paranthesis { + bool isOpening = false; + int index; + Paranthesis(bool is, int i) : isOpening(is), index(i) {} +}; + +vector split_terms(string str) { + vector result; + + for (int i = 0; i < str.size(); i++) { // iterate token wise. + Token token; + token.begin = i; + token.end = -1; + if (str[i] == '(') { + // expecting a bracket token + + // make bracket for evaluation of balance + vector brackets; + brackets.push_back(Paranthesis(true, i)); + for (int j = i + 1; j < str.size(); j++) + if (str[j] == ')') + brackets.push_back(Paranthesis(false, j)); + else if (str[j] == '(') + brackets.push_back(Paranthesis(true, j)); + + // Cant be empty + if (brackets.empty()) { + cout << "[PARSER][BRACKETS] Brackets stack can't be empty! Probably a bug!" << endl; + system("PAUSE"); + exit(1); + } + + // check for bracket balance + int brack_cnt = 0; + for (auto bracket : brackets) + if (bracket.isOpening)brack_cnt++; + else brack_cnt--; + + if (brack_cnt == 0) { + token.end = brackets[brackets.size() - 1].index+1; + // add one to compensate for the < and not <= in the retrievesubstring + } + else { + cout << "[PARSER][BRACKET] Brackets aren't balanced!" << endl; + system("PAUSE"); + exit(1); + } + } + else if (isdigit(str[i])) { + // expecting a digit token. + + // consume till the end of the digits + int endofconst = i; // points to the current char + while (isdigit(str[++endofconst])); // endofconst will have the index of the end of the term. + // ENDOFCONST WILL POINT ONE INDEX PLUS + + // check if there is a var + if (isalpha(str[endofconst])) endofconst++; + + // check for the power + if (str[endofconst] == '^') { + // consume till the end of the constant + while (isdigit(str[++endofconst])); + } + + token.end = endofconst; + } + else if (isalpha(str[i])) { + // expecting a variable token. + + int endofvar = i; + // check for the power + if (str[endofvar + 1] == '^') { + // consume till the end of the digits + endofvar++; // point the index to '^' + while (isdigit(++endofvar)); // endofconst wll have the index of the end of the term. + // ENDOFCONST WILL POINT ONE INDEX PLUS + } + + token.end = endofvar+1; // add one incase it was only a var + // to compensate over the < not <= in the retrievesubstring + } + else if (str[i] == ' ') { + // a space detected. + continue; // skip spaces + } + else { + // expecting either an equal or any of the arithmetic. + token.end = i+1; // the token is only one letter. + // add one incase it was only a char + // to compensate over the < not <= in the retrievesubstring + } + i = token.end-1; + result.push_back(retrieveSubString(str, token)); + } + return result; +} + +#endif // ! + diff --git a/bin/Debug-x64/QuicMaf.exe b/bin/Debug-x64/QuicMaf.exe new file mode 100644 index 0000000..69f577b Binary files /dev/null and b/bin/Debug-x64/QuicMaf.exe differ diff --git a/bin/Debug-x64/QuicMaf.ilk b/bin/Debug-x64/QuicMaf.ilk new file mode 100644 index 0000000..64296b1 Binary files /dev/null and b/bin/Debug-x64/QuicMaf.ilk differ diff --git a/bin/Debug-x64/QuicMaf.pdb b/bin/Debug-x64/QuicMaf.pdb new file mode 100644 index 0000000..be83069 Binary files /dev/null and b/bin/Debug-x64/QuicMaf.pdb differ diff --git a/notes.txt b/notes.txt new file mode 100644 index 0000000..81cbe70 --- /dev/null +++ b/notes.txt @@ -0,0 +1,87 @@ + +In all equations the goal is the same, finding the unknown, +Between every term there must be a space ex: +x = 50 +x = x - 50 +x - 10 = 50 +x - 10 = x - 50 +5x = 50 +5x = x - 50 +5x - 10 = 50 +5x - 10 = x - 50 + +BEDMAS + +2(x^2 + 50) = 50 + x +-2(x^2 + 50) is a term +-50 is a term +-x is a term + +- Term: + - Variable + - Value + - Power + +- Constant: + - Value + - Power + +- Variable: + - Value + - Char var + - Power + +- Operator: + - char + +- Bracket: + - Value + - Terms vector + +- Equation: + - lwing // Contains list of terms on the left side of the equation + - rwing // Conatins list of terms on the right side of the equation + // lwing = rwing + +Parsing Algorithim: + - split the terms in the term of spaces + - iterate over the terms, call the iterator mTerm: + - if there exists an opening bracket in the mTerm + - split upon the bracket + - make the coefficient of the bracket the first item in the split, + - make the other terms in the mTerms vector. + - consume the other terms until a closing bracket is found. + *- if the bracket is found delete the char and convert normally to valid term and append. + - add the bracket to the list of terms in the correct wing. + - if mTerm contains a '^': + - if a character is detected: + - split upon the power. + - the first split is converted to a variable. + - the second split is added to the power of the variable. + - add the variable to the list of the terms in the correct wing. + - if all of the mTerm is digits with '^': + - split upon the power. + - the fist split is converted to a constant. + - the second split is added to the power of the variable. + - add the constant to the list of the terms in the correct wing. + - if mTerm is all digits: + - convert to a constant. + - add the constant to the list of the terms in the correct wing. + - if mTerm contains a character: + - convert to a variable. + - add the constant to the list of the terms in the correct wing. + - if mTerm is an Operator: + - convert to an operator; + - add the operator to the list of the terms in the correct wing. + - if the mTerm is an equality operator: + - switch the bool of lwing_turn. + + +Initialization: +1. Seperate the terms. +2. Put the lwing and rwing correctly. +3. Put all of the data in memory correctly + +In Case of One unknown: +1. Swap like terms to keep the unknowns in one side and constants on other. +2. Combine the terms \ No newline at end of file