diff --git a/QuicMaf/QuicMaf.vcxproj b/QuicMaf/QuicMaf.vcxproj index 42de025..86a8195 100644 --- a/QuicMaf/QuicMaf.vcxproj +++ b/QuicMaf/QuicMaf.vcxproj @@ -119,9 +119,15 @@ + + + + + + @@ -131,6 +137,7 @@ + diff --git a/QuicMaf/QuicMaf.vcxproj.filters b/QuicMaf/QuicMaf.vcxproj.filters index 6514295..bc41458 100644 --- a/QuicMaf/QuicMaf.vcxproj.filters +++ b/QuicMaf/QuicMaf.vcxproj.filters @@ -18,6 +18,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -53,5 +62,17 @@ 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 index 0b0f24d..66eed93 100644 --- a/QuicMaf/QuicMaf.vcxproj.user +++ b/QuicMaf/QuicMaf.vcxproj.user @@ -3,4 +3,7 @@ true + + WindowsLocalDebugger + \ No newline at end of file diff --git a/QuicMaf/app.cpp b/QuicMaf/app.cpp index 6f9bbc1..67af4c3 100644 --- a/QuicMaf/app.cpp +++ b/QuicMaf/app.cpp @@ -5,10 +5,11 @@ #include "vendor/lexertk.hpp" -#include "maths/tokenizer.h" +#include "maths/solver/Solver.h" +#include "maths/Equations.h" -#define MAIN_APP -//#define APP_TEST +//#define MAIN_APP +#define APP_TEST #ifdef MAIN_APP @@ -44,13 +45,14 @@ int main() { system("CLS"); return 1; } - + #ifdef DEBUG_MODE lexertk::helper::dump(generator); #endif // DEBUG_MODE + Equation equation; + equation.Parse(generator); - auto result = tokenize(generator); system("PAUSE"); system("CLS"); @@ -64,5 +66,14 @@ int main() { #ifdef APP_TEST +int main() { + lexertk::generator lexer; + lexer.process("_const+_const,_eval:no_diff_Var"); + + //auto result = tokenize(lexer); + + + return 0; +} #endif \ No newline at end of file diff --git a/QuicMaf/maths/Equations.h b/QuicMaf/maths/Equations.h new file mode 100644 index 0000000..78229f3 --- /dev/null +++ b/QuicMaf/maths/Equations.h @@ -0,0 +1,48 @@ +#ifndef EQUATIONS_H +#define EQUATIONS_H +#pragma once +#include "defines.h" +#include "terms/Brackets.h" +#include "terms/Constant.h" +#include "terms/Equal.h" +#include "terms/Operator.h" +#include "terms/Term.h" +#include "terms/Variable.h" +#include "terms/Paranthesis.h" +#include "tokenizer.h" + +#include "../vendor/lexertk.hpp" + +struct Equation { + vector lwing; + vector rwing; + + // TODO: Optimize this mess + void Parse(lexertk::generator expression) { + string lwing_str; + string rwing_str; + + bool left = true; + for (int i = 0; i < expression.size(); i++) { + if (expression[i].value[0] == '\0') continue; + + if (expression[i].value[0] == '=') { + left = !left; + continue; // dont add equal sign + } + else left = left; + (left) ? lwing_str.push_back(expression[i].value[0]) : rwing_str.push_back(expression[i].value[0]); // append to wings + } + + // Tokenize wings + lexertk::generator lwing_lexer; + lwing_lexer.process(lwing_str); + lwing = tokenize(lwing_lexer); + + lexertk::generator rwing_lexer; + rwing_lexer.process(rwing_str); + rwing = tokenize(rwing_lexer); + } +}; + +#endif // !EQUATIONS_H \ No newline at end of file diff --git a/QuicMaf/maths/defines.h b/QuicMaf/maths/defines.h index 75e34d9..44596e1 100644 --- a/QuicMaf/maths/defines.h +++ b/QuicMaf/maths/defines.h @@ -7,8 +7,12 @@ #include #include +#include #include +#include +#include + using namespace std; #define DEF_C -999 @@ -25,7 +29,6 @@ enum TermTypes { Equ, }; - // for string delimiter static vector split(string s, string delimiter) { size_t pos_start = 0, pos_end, delim_len = delimiter.length(); @@ -51,7 +54,7 @@ static void removeSubstrs(string& s, string& p) { s.erase(i, n); } -int getPrecedence(char c) { +static int getPrecedence(char c) { //if (!isArithmitic(c)) return -1; // invalid if (c == '*') return 1; @@ -64,7 +67,7 @@ int getPrecedence(char c) { // return true if c1 is higher precedence // return false if c2 is higher precedence -bool compPrecedence(char c1, char c2) { +static bool compPrecedence(char c1, char c2) { return getPrecedence(c1) > getPrecedence(c2); } @@ -149,4 +152,23 @@ static int getTermType(string str) { else return Var; } +// 1 is pos +// -1 is neg +// 0 is 0 +static int sign(NValue x) { + return (x > 0) ? 1 : ((x < 0) ? -1 : 0); +} + + +// Function to calculate highest common divisor +static int gcf(int x, int y) { + int gcd; + + for (int i = 1; i <= x && i <= y; i++) + if (x % i == 0 && y % i == 0) + gcd = i; + + return gcd; +} + #endif // ! diff --git a/QuicMaf/maths/solver/Solver.cpp b/QuicMaf/maths/solver/Solver.cpp new file mode 100644 index 0000000..ef27f99 --- /dev/null +++ b/QuicMaf/maths/solver/Solver.cpp @@ -0,0 +1 @@ +#include "Solver.h" diff --git a/QuicMaf/maths/solver/Solver.h b/QuicMaf/maths/solver/Solver.h new file mode 100644 index 0000000..aac7e5d --- /dev/null +++ b/QuicMaf/maths/solver/Solver.h @@ -0,0 +1,44 @@ +#ifndef SOLVER_H +#define SOLVER_H +#pragma once +#include "../Equations.h" +#include "../defines.h" +#include "../terms/Brackets.h" +#include "../terms/Constant.h" +#include "../terms/Equal.h" +#include "../terms/Operator.h" +#include "../terms/Term.h" +#include "../terms/Variable.h" +#include "../terms/Paranthesis.h" +#include "../tokenizer.h" + +#include "../../vendor/lexertk.hpp" + +class Solver +{ +public: + void Parse(string equation); + Term* Solve(); + +public: // PRIVATE MEMBERS TODO: MARK PRIVATE IN FINAL BUILD + Equation* equation = nullptr; +public: // Program Side Calcs TODO: MARK PRIVATE IN FINAL BUILD + bool CheckValidOps(Equation* equ); + + Equation* RemNonEssentialOp(Equation* equ); + bool CheckOpRemovalValidity(Operator* op); + bool CheckOpT2RemovalNeed(Operator* op); + Equation* BreakUselessBracks(Equation* equ); + Equation* RemoveWeightOfWings(Equation* equ); + Equation* OrderTerms(Equation* equ); + + Equation* CheckDiversionCalcs(Equation* equ); + Equation* DoDiversionCalcs(Equation* equ); + + Term* MergeOpTerm(Operator* op, Term* t1, Term* t2); + +public: // Math Side Calcs TODO: MARK PRIVATE IN FINAL BUIlD + Equation* Evaluate(Equation* equ); +}; + +#endif // !1 diff --git a/QuicMaf/maths/solver/term_rewriter/QMReducer.h b/QuicMaf/maths/solver/term_rewriter/QMReducer.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/QuicMaf/maths/solver/term_rewriter/QMReducer.h @@ -0,0 +1 @@ +#pragma once diff --git a/QuicMaf/maths/solver/term_rewriter/QMRule.cpp b/QuicMaf/maths/solver/term_rewriter/QMRule.cpp new file mode 100644 index 0000000..fc05a48 --- /dev/null +++ b/QuicMaf/maths/solver/term_rewriter/QMRule.cpp @@ -0,0 +1,6 @@ +#include "QMRule.h" + +vector QMRule::Reduce() +{ + return vector(); +} diff --git a/QuicMaf/maths/solver/term_rewriter/QMRule.h b/QuicMaf/maths/solver/term_rewriter/QMRule.h new file mode 100644 index 0000000..b3481d7 --- /dev/null +++ b/QuicMaf/maths/solver/term_rewriter/QMRule.h @@ -0,0 +1,73 @@ +#ifndef QMRULE_H +#define QMRULE_H +#include "../../Equations.h" +#include "../../defines.h" +#include "../../terms/Brackets.h" +#include "../../terms/Constant.h" +#include "../../terms/Equal.h" +#include "../../terms/Operator.h" +#include "../../terms/Term.h" +#include "../../terms/Variable.h" +#include "../../terms/Paranthesis.h" +#include "../../tokenizer.h" + +#include "../../../vendor/lexertk.hpp" + +enum Identifier_t { + _const = 1, + _var = 2, + _brack, + _eval, + _add, + _sub, + _mul, + _div, + _equ, + _const_aval, + _var_aval, + _pow_diff, + _no_pow_diff, + _var_diff, + _no_var_diff, + _high_order_left, + _high_order_right, + _priority1, + _priority2, + _priority3, + _priority4, + _priority5, +}; + +class QMRule { +public: + QMRule(vector rule, vector props, int prio) + : mRules(rule), mProps(props), mPrior(prio) {} + + vector GetRules() const { return mRules; } + vector GetProps() const { return mProps; } + int GetPrior() { return mPrior; } + + bool operator==(const QMRule& left) const { + if (left.mPrior != mPrior) return false; + if (left.mProps != mProps) return false; + if (left.mRules != mRules) return false; + return true; + } + + bool operator>(const QMRule& left) const { + return (left.mPrior > mPrior); + } + bool operator<(const QMRule& left) const { + return (left.mPrior < mPrior); + } + + vector Reduce(vector terms); // applies self rule on terms vector, only once +private: + vector Evaluate(); // evaluation method + + + vector mRules; + vector mProps; + int mPrior; +}; +#endif // QMRULE_H diff --git a/QuicMaf/maths/solver/term_rewriter/QMRuleSet.h b/QuicMaf/maths/solver/term_rewriter/QMRuleSet.h new file mode 100644 index 0000000..6c08446 --- /dev/null +++ b/QuicMaf/maths/solver/term_rewriter/QMRuleSet.h @@ -0,0 +1,35 @@ +#ifndef QMRULESET_H +#define QMRULESET_H +#pragma once +#include "../../Equations.h" +#include "../../defines.h" +#include "../../terms/Brackets.h" +#include "../../terms/Constant.h" +#include "../../terms/Equal.h" +#include "../../terms/Operator.h" +#include "../../terms/Term.h" +#include "../../terms/Variable.h" +#include "../../terms/Paranthesis.h" +#include "../../tokenizer.h" + +#include "../../../vendor/lexertk.hpp" + +#include "QMRule.h" + +class QMRuleSet { +public: + void push_back(QMRule rule); + void push_front(QMRule rule); + + void pop_back(QMRule rule); + void pop_front(QMRule rule); + + void order(); + + auto GetRuleSet() { return mRuleSet; } + +private: + deque mRuleSet; +}; + +#endif // !QMRULESET_H diff --git a/QuicMaf/maths/terms/Brackets.h b/QuicMaf/maths/terms/Brackets.h index 5f020ef..7a5e5b9 100644 --- a/QuicMaf/maths/terms/Brackets.h +++ b/QuicMaf/maths/terms/Brackets.h @@ -13,7 +13,12 @@ public: Bracket() { Term(); mType = TermTypes::Brack; - mConstant = new Constant(1); + } + + Bracket(vector ts) { + Term(); + mType = TermTypes::Brack; + mTerms = ts; } vector mTerms; @@ -21,6 +26,8 @@ public: void setConstant(Term* constant) { mConstant = constant; } + + Term* GetConstant() const { return mConstant; } private: Term *mConstant; diff --git a/QuicMaf/maths/terms/Term.h b/QuicMaf/maths/terms/Term.h index 4f56d4e..4cc4dea 100644 --- a/QuicMaf/maths/terms/Term.h +++ b/QuicMaf/maths/terms/Term.h @@ -23,8 +23,9 @@ public: NValue mValue = DEF_N; CValue mVariable = DEF_C; - CValue mOperator = DEF_C; NValue mPower = 1; + CValue mOperator = DEF_C; + bool mSquareRoot = false; int mType = -1; }; #endif // !TERM_H diff --git a/QuicMaf/maths/terms/Variable.h b/QuicMaf/maths/terms/Variable.h index a534085..df93e51 100644 --- a/QuicMaf/maths/terms/Variable.h +++ b/QuicMaf/maths/terms/Variable.h @@ -8,12 +8,11 @@ using namespace std; class Variable : public Term { public: - Variable(NValue val = 0, CValue var = DEF_C, NValue pwr = 1) { + Variable(NValue val = 1, 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 index 1d7cd0d..d81a5ae 100644 --- a/QuicMaf/maths/terms/term_parser.h +++ b/QuicMaf/maths/terms/term_parser.h @@ -1,3 +1,13 @@ +/* + **************************************************** + + This Code Is Depreciated + Remade and tuned in: + tokenizer.h + + **************************************************** +*/ + #ifndef TERM_PARSER_H #define TERM_PARSER_H #pragma once diff --git a/QuicMaf/maths/tokenizer.h b/QuicMaf/maths/tokenizer.h index b263dce..d6d464e 100644 --- a/QuicMaf/maths/tokenizer.h +++ b/QuicMaf/maths/tokenizer.h @@ -1,3 +1,20 @@ +/* + *************************************************************************** + + 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 + + *************************************************************************** +*/ #ifndef TOKENIZER_H #define TOKENIZER_H #pragma once @@ -75,11 +92,11 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co index++; } while (!(!state && counter == 0)); - bracks = retriveSubLexer(gen, Token(token->begin, index-1)); + bracks = retriveSubLexer(gen, Token(token->begin, index - 1)); token->end = index - 1; // to make sure we move the token pointer to the end of bracks // DELETE THIS BRACKET PARANTHESIS - bracks = retriveSubLexer(bracks, Token(1, bracks.size()-2)); + bracks = retriveSubLexer(bracks, Token(1, bracks.size() - 2)); // Tokenize its term // first make sure it is not empty @@ -102,6 +119,50 @@ static Bracket* tokenize_bracket(lexertk::generator gen, Token* token, string co return result; } +static vector combineBrackets(vector terms) { + vector result; + + for (int i = 0; i < terms.size(); i++) { + auto term = terms[i]; + + if (term->mType == TermTypes::Op && + (term->mOperator == '-' || term->mOperator == '+')) { + // if after it was a number + if (terms[i + 1]->mType == TermTypes::Const || terms[i + 1]->mType == TermTypes::Var) { + // check for safety + if (!(terms.size() <= i + 2)) + // if after it was a bracket too + if (terms[i + 2]->mType == TermTypes::Brack) { + // if so combine the terms + Bracket* brack = new Bracket(); + brack->mTerms = static_cast(terms[i + 2])->mTerms; + auto constant = static_cast(terms[i + 2])->GetConstant(); + constant->mValue *= (term->mOperator == '+') ? +1 : -1; + brack->setConstant(constant); + result.push_back(brack); + i += 2; + continue; + } + } + else { + if (terms[i + 1]->mType == TermTypes::Brack) { + // if so combine the terms + Bracket* brack = new Bracket(); + brack->mTerms = static_cast(terms[i + 1])->mTerms; + auto constant = static_cast(terms[i + 1])->GetConstant(); + constant->mValue *= (term->mOperator == '+') ? +1 : -1; + brack->setConstant(constant); + result.push_back(brack); + i += 1; + continue; + } + } + } + result.push_back(term); + } + return result; +} + static vector tokenize(lexertk::generator lexed) { vector result; @@ -130,18 +191,38 @@ static vector tokenize(lexertk::generator lexed) { /////// ENDING OF TREE } - Variable* Var = nullptr; - Var = new Variable(atof(&lex.value[0]), after_lex.value[0], atof(&lexed[i + 3].value[0])); - result.push_back(Var); - tok.end = i + 3; - /////// ENDING OF TREE + // check for bracket + if (lexed[i + 4].value == "(") { + // bracket detected + tok.begin += 4; // consume coefficient + result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value + lexed[i + 3].value)); + /////// ENDING OF TREE + } + else { + // simple power variable + Variable* Var = nullptr; + Var = new Variable(atof(&lex.value[0]), after_lex.value[0], atof(&lexed[i + 3].value[0])); + result.push_back(Var); + tok.end = i + 3; + /////// ENDING OF TREE + } } else { - // The variable is simple! - Variable* Var = nullptr; - Var = new Variable(atof(&lex.value[0]), after_lex.value[0]); - result.push_back(Var); - tok.end = i + 1; + + if (lexed[i + 2].value == "(") { + // bracket detected + tok.begin += 2; + result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value)); + /////// ENDING OF TREE + } + else { + // The variable is simple! + Variable* Var = nullptr; + Var = new Variable(atof(&lex.value[0]), after_lex.value[0]); + result.push_back(Var); + tok.end = i + 1; + /////// ENDING OF TREE + } } } else if (isBrackets(after_lex.value[0]) && isBracketsOpening(after_lex.value[0])) { @@ -163,11 +244,18 @@ static vector tokenize(lexertk::generator lexed) { /////// ENDING OF TREE } - Constant* Const = nullptr; - Const = new Constant(atof(&lex.value[0]), atof(&lexed[i + 2].value[0])); - result.push_back(Const); - tok.end = i + 2; - /////// ENDING OF TREE + // check for brackets + if (lexed[i + 3].value == "(") { + tok.begin += 3; + result.push_back(tokenize_bracket(lexed, &tok, lex.value + after_lex.value + lexed[i + 2].value)); + } + else { + Constant* Const = nullptr; + Const = new Constant(atof(&lex.value[0]), atof(&lexed[i + 2].value[0])); + result.push_back(Const); + tok.end = i + 2; + /////// ENDING OF TREE + } } else { // The number is simple! @@ -219,6 +307,7 @@ static vector tokenize(lexertk::generator lexed) { op = new Operator(lex.value[0]); result.push_back(op); tok.end = i; + } else if (isEqualChar(lex.value[0])) { // equal sign @@ -232,6 +321,8 @@ static vector tokenize(lexertk::generator lexed) { i = tok.end; // no need to increment, automatically done in loop statment } + result = combineBrackets(result); + return result; } #endif // !TOKENIZER_H diff --git a/bin/Debug-x64/QuicMaf.exe b/bin/Debug-x64/QuicMaf.exe index 5a07a84..ad45554 100644 Binary files a/bin/Debug-x64/QuicMaf.exe and b/bin/Debug-x64/QuicMaf.exe differ diff --git a/bin/Debug-x64/QuicMaf.ilk b/bin/Debug-x64/QuicMaf.ilk index 8832296..566f227 100644 Binary files a/bin/Debug-x64/QuicMaf.ilk and b/bin/Debug-x64/QuicMaf.ilk differ diff --git a/bin/Debug-x64/QuicMaf.pdb b/bin/Debug-x64/QuicMaf.pdb index a90f8be..b07b581 100644 Binary files a/bin/Debug-x64/QuicMaf.pdb and b/bin/Debug-x64/QuicMaf.pdb differ diff --git a/notes2.txt b/notes2.txt new file mode 100644 index 0000000..fc0cbab --- /dev/null +++ b/notes2.txt @@ -0,0 +1,17 @@ +Term1 Term2 +-------------- +Var Var +Var Bracket +Var Const +Var Op +Const Const +Const Var +Const Bracket +Const Op +Bracket Bracket +Bracket Var +Bracket Const +Bracket Op +Op Var +Op Const +Op Bracket \ No newline at end of file diff --git a/notes3.txt b/notes3.txt new file mode 100644 index 0000000..91b331f --- /dev/null +++ b/notes3.txt @@ -0,0 +1,43 @@ +- Break brackets: + - Mutliply each child term with coefficeint, ignore operators. +- Solve: + - Rules: + // These ruls are not complete in the application we should take in mind + // that 'const * var' might come as 'var * const' and still evaluate to the same thing + // Also it must always evaluate using the 'TermHelper' class. + - const * const, eval + - const * var, eval + - const * bracket, eval + - const / const, eval + - const / var, eval + - const / bracket, eval + - const + const, eval + - const + var, eval + - const + bracket, eval + - const - const, eval + - const - var, eval + - const - bracket, eval + - Apply Rules, until no difference. + +- Move variables to the right: + - Specific Rules: + // These rules are not complete in the application we should take in mind + // that 'const * var' might come as 'var * const' THIS IS FOR ALL RULES! + // Also it should evaluate to something like this, although not always: + - const * const, const * const + - const * var, const * var + - const * bracket, const * bracket + - const / const, const / const + - const / var, const / var + - const / bracket, const / bracket + - const + const, cosnt + const + - const + var, const + var + - const + bracket, const + bracket + - const - const, const - const + - const - var, const - var + - const - bracket, const - bracket + - Keep appling rules until there is no change. + +BreakBrackets() +Move_Variables_To_The_Right() +Solve()