Made Unfinished Divisions
This commit is contained in:
parent
cc743f1e54
commit
cd74a89e25
|
@ -131,6 +131,7 @@
|
|||
<ClInclude Include="maths\terms\Brackets.h" />
|
||||
<ClInclude Include="maths\terms\Constant.h" />
|
||||
<ClInclude Include="maths\terms\Equal.h" />
|
||||
<ClInclude Include="maths\terms\Fraction.h" />
|
||||
<ClInclude Include="maths\terms\Operator.h" />
|
||||
<ClInclude Include="maths\terms\Paranthesis.h" />
|
||||
<ClInclude Include="maths\terms\Term.h" />
|
||||
|
|
|
@ -74,5 +74,8 @@
|
|||
<ClInclude Include="maths\solver\term_rewriter\QMReducer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="maths\terms\Fraction.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -70,13 +70,15 @@ int main() {
|
|||
|
||||
int main() {
|
||||
lexertk::generator lexer;
|
||||
lexer.process("2(x + 2x) + 2x");
|
||||
lexer.process("2x/(4x+2)");
|
||||
|
||||
auto result = tokenize(lexer);
|
||||
|
||||
QMReducer reducer;
|
||||
reducer.setPool(result);
|
||||
auto res = reducer.Sub(result[0], result[2]);
|
||||
auto frac = static_cast<Fraction*>(result[0]);
|
||||
|
||||
auto res = reducer.Div(frac->mNomin[0], frac->mDomin[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ enum TermTypes {
|
|||
Op,
|
||||
Brack,
|
||||
Equ,
|
||||
Frac,
|
||||
};
|
||||
|
||||
// for string delimiter
|
||||
|
|
|
@ -63,7 +63,7 @@ Bracket * QMReducer::convertToBracket(Term * t1) {
|
|||
if (t1->mType != TermTypes::Brack) return false;
|
||||
return static_cast<Bracket*>(t1);
|
||||
}
|
||||
Variable * QMReducer::converToVariable(Term * t1) {
|
||||
Variable * QMReducer::convertToVariable(Term * t1) {
|
||||
if (t1->mType != TermTypes::Var) return false;
|
||||
return static_cast<Variable*>(t1);
|
||||
}
|
||||
|
@ -190,8 +190,8 @@ vector<Term*> QMReducer::Add(Term * t1, Term * t2, Identifier_t order) {
|
|||
return { Const };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
|
||||
auto t1_var = converToVariable(t1);
|
||||
auto t2_var = converToVariable(t2);
|
||||
auto t1_var = convertToVariable(t1);
|
||||
auto t2_var = convertToVariable(t2);
|
||||
|
||||
Variable* var = nullptr;
|
||||
var = new Variable();
|
||||
|
@ -265,8 +265,8 @@ vector<Term*> QMReducer::Sub(Term * t1, Term * t2, Identifier_t order) {
|
|||
return { Const };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
|
||||
auto t1_var = converToVariable(t1);
|
||||
auto t2_var = converToVariable(t2);
|
||||
auto t1_var = convertToVariable(t1);
|
||||
auto t2_var = convertToVariable(t2);
|
||||
|
||||
Variable* var = nullptr;
|
||||
var = new Variable();
|
||||
|
@ -346,8 +346,8 @@ vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
|
|||
else {
|
||||
// no need to check solvability
|
||||
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
|
||||
auto t1_var = converToVariable(t1);
|
||||
auto t2_var = converToVariable(t2);
|
||||
auto t1_var = convertToVariable(t1);
|
||||
auto t2_var = convertToVariable(t2);
|
||||
|
||||
Variable* var = nullptr;
|
||||
var = new Variable();
|
||||
|
@ -357,7 +357,7 @@ vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
|
|||
return { var };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Const) {
|
||||
auto t1_var = converToVariable(t1);
|
||||
auto t1_var = convertToVariable(t1);
|
||||
auto t2_const = convertToConstant(ReducePower(t2)[0]);
|
||||
|
||||
Variable* var = nullptr;
|
||||
|
@ -369,7 +369,7 @@ vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
|
|||
}
|
||||
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Var) {
|
||||
auto t1_const = convertToConstant(t1);
|
||||
auto t2_var = converToVariable(ReducePower(t2)[0]);
|
||||
auto t2_var = convertToVariable(ReducePower(t2)[0]);
|
||||
|
||||
Variable* var = nullptr;
|
||||
var = new Variable();
|
||||
|
@ -391,3 +391,232 @@ vector<Term*> QMReducer::Mul(Term * t1, Term * t2, Identifier_t order) {
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool QMReducer::IsDivSolvable(Term * t1, Term * t2) {
|
||||
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) return true;
|
||||
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QMReducer::IsDivSpecialCase(Term * t1, Term * t2) {
|
||||
if (t1->mType == TermTypes::Brack &&
|
||||
t2->mType != TermTypes::Brack) return true;
|
||||
|
||||
if (t1->mType != TermTypes::Brack &&
|
||||
t2->mType == TermTypes::Brack) return true;
|
||||
|
||||
if (t1->mType == TermTypes::Brack &&
|
||||
t2->mType == TermTypes::Brack) return true;
|
||||
|
||||
if (t1->mType == TermTypes::Const &&
|
||||
t2->mType == TermTypes::Var) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<Term*> QMReducer::gcdofTerms(Term * t1, Term * t2) {
|
||||
|
||||
if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) {
|
||||
auto t1_const = convertToConstant(ReducePower(t1)[0]);
|
||||
auto t2_const = convertToConstant(ReducePower(t2)[0]);
|
||||
|
||||
Constant* Const = new Constant();
|
||||
Const->mValue = gcf(t1->mValue, t2->mValue);
|
||||
return { Const };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
|
||||
auto t1_var = convertToVariable(t1);
|
||||
auto t2_var = convertToVariable(t2);
|
||||
|
||||
Variable* var = new Variable();
|
||||
var->mValue = gcf(t1_var->mValue, t2_var->mValue);
|
||||
var->mVariable = t1_var->mVariable;
|
||||
var->mPower = (t1_var->mPower > t2_var->mPower) ? t2_var->mPower : t1_var->mPower;
|
||||
|
||||
return { var };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Const) {
|
||||
auto t1_var = convertToVariable(t1);
|
||||
auto t2_const = convertToConstant(t2);
|
||||
|
||||
Constant* Const = new Constant();
|
||||
Const->mValue = gcf(t1_var->mValue, t2_const->mValue);
|
||||
return { Const };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Var) {
|
||||
auto t1_const = convertToConstant(t1);
|
||||
auto t2_var = convertToVariable(t2);
|
||||
|
||||
Constant* Const = new Constant();
|
||||
Const->mValue = gcf(t1_const->mValue, t2_var->mValue);
|
||||
return { Const };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
vector<Term*> QMReducer::FactorizeTermsToBrack(vector<Term*> terms, vector<Term*> terms2) {
|
||||
vector<Term*> allTerms = terms;
|
||||
for (int i = 0; i < terms2.size(); i++)
|
||||
allTerms.push_back(terms2[i]);
|
||||
|
||||
Term* HCF_all = new Term();
|
||||
*HCF_all = *allTerms[0];
|
||||
for (int i = 0; i < allTerms.size(); i++)
|
||||
*HCF_all = *gcdofTerms(HCF_all, allTerms[i])[0];
|
||||
|
||||
// make first bracket
|
||||
Bracket* brack1 = new Bracket();
|
||||
brack1->setConstant(HCF_all);
|
||||
for (int i = 0; i < terms.size(); i++)
|
||||
brack1->mTerms.push_back(Div(terms[i], HCF_all)[0]);
|
||||
|
||||
// make second bracket
|
||||
Bracket* brack2 = new Bracket();
|
||||
brack2->setConstant(HCF_all);
|
||||
for (int i = 0; i < terms2.size(); i++)
|
||||
brack2->mTerms.push_back(Div(terms[i], HCF_all)[0]);
|
||||
|
||||
return { brack1, brack2 };
|
||||
}
|
||||
|
||||
vector<Term*> QMReducer::FactorizeTermsToBrack(vector<Term*> allTerms) {
|
||||
Term* HCF_all = new Term();
|
||||
*HCF_all = *allTerms[0];
|
||||
for (int i = 0; i < allTerms.size(); i++)
|
||||
*HCF_all = *gcdofTerms(HCF_all, allTerms[i])[0];
|
||||
|
||||
// make bracket
|
||||
Bracket* brack = new Bracket();
|
||||
brack->setConstant(HCF_all);
|
||||
for (int i = 0; i < allTerms.size(); i++)
|
||||
brack->mTerms.push_back(Div(allTerms[i], HCF_all)[0]);
|
||||
|
||||
return { brack };
|
||||
}
|
||||
|
||||
bool QMReducer::TermsMatch(vector<Term*> terms1, vector<Term*> terms2) {
|
||||
terms1 = OrderTerms(terms1, Identifier_t::_high_order_left);
|
||||
terms2 = OrderTerms(terms2, Identifier_t::_high_order_left);
|
||||
return terms1 == terms2;
|
||||
}
|
||||
|
||||
// WARNING: Make sure that t1 and t2 are in the simplest form.
|
||||
vector<Term*> QMReducer::Div(Term * t1, Term * t2, Identifier_t order) {
|
||||
|
||||
|
||||
// Check if division is solvable
|
||||
if (IsDivSolvable(t1, t2)) {
|
||||
// only two situations
|
||||
// var / var, pow_no_matter
|
||||
// const / const, pow_no_matter
|
||||
|
||||
if (t1->mType == TermTypes::Var && t2->mType == TermTypes::Var) {
|
||||
// var / var
|
||||
Term* res = new Term();
|
||||
res->mValue = t1->mValue / t2->mValue;
|
||||
res->mPower = t1->mPower - t2->mPower;
|
||||
if (res->mPower == 0.0)
|
||||
// it is a constant
|
||||
res->mType = TermTypes::Const;
|
||||
else
|
||||
res->mVariable = t1->mVariable;
|
||||
return { res };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Const) {
|
||||
// const / const
|
||||
t1 = convertToConstant(ReducePower(t1)[0]);
|
||||
t2 = convertToConstant(ReducePower(t2)[0]);
|
||||
|
||||
Constant* Const = new Constant();
|
||||
Const->mValue = t1->mValue / t2->mValue;
|
||||
return { Const };
|
||||
}
|
||||
}
|
||||
// if it was a special case
|
||||
else if (IsDivSpecialCase(t1, t2)) {
|
||||
// only three situations:
|
||||
// mult term / mult term
|
||||
// one term const / one term var
|
||||
// multi terms / one term
|
||||
// one term / multi terms
|
||||
|
||||
if (t1->mType == TermTypes::Brack && t2->mType == TermTypes::Brack) {
|
||||
// multi terms / multi term
|
||||
auto t1_brack = convertToBracket(t1);
|
||||
auto t2_brack = convertToBracket(t2);
|
||||
|
||||
// check if taking out common factors makes common bracket terms
|
||||
auto fraction_nomin = convertToBracket(FactorizeTermsToBrack(t1_brack->mTerms)[0]);
|
||||
auto fraction_domin = convertToBracket(FactorizeTermsToBrack(t2_brack->mTerms)[0]);
|
||||
|
||||
if (TermsMatch(fraction_nomin->mTerms, fraction_domin->mTerms))
|
||||
// common bracket terms matched
|
||||
// TIME FOR RECURSION!
|
||||
return Div(fraction_nomin->GetConstant(), fraction_domin->GetConstant());
|
||||
|
||||
// check if taking out common factors make common bracket coeffiecient
|
||||
auto fraction = FactorizeTermsToBrack(t1_brack->mTerms, t2_brack->mTerms);
|
||||
// fraction[0] is nomin
|
||||
// fraction[1] is domin
|
||||
fraction_nomin = convertToBracket(fraction[0]);
|
||||
fraction_nomin->setConstant(nullptr); // Nullptr == 1
|
||||
fraction_domin = convertToBracket(fraction[1]);
|
||||
fraction_domin->setConstant(nullptr); // Nullptr == 1
|
||||
|
||||
Fraction* frac = new Fraction();
|
||||
|
||||
frac->mNomin = fraction_nomin->mTerms;
|
||||
frac->mDomin = fraction_domin->mTerms;
|
||||
return { frac };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Const && t2->mType == TermTypes::Var) {
|
||||
// const / var
|
||||
auto t1_const = convertToConstant(ReducePower(t1)[0]);
|
||||
auto t2_var = convertToVariable(t2);
|
||||
|
||||
Variable* var = new Variable();
|
||||
var->mVariable = t2_var->mVariable;
|
||||
var->mValue = t1_const->mValue / t2_var->mValue;
|
||||
var->mPower = t2_var->mPower;
|
||||
|
||||
return { var };
|
||||
}
|
||||
else if (t1->mType == TermTypes::Brack && t2->mType != TermTypes::Brack) {
|
||||
// multi terms / multi terms
|
||||
auto t1_brack = convertToBracket(t1);
|
||||
|
||||
vector<Term*> result;
|
||||
for (int i = 0; i < t1_brack->mTerms.size(); i++) {
|
||||
if (t1_brack->mTerms[i]->mType == TermTypes::Op) {
|
||||
result.push_back(t1_brack->mTerms[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
auto resultant = Div(t1_brack->mTerms[i], t2);
|
||||
for (auto *term : resultant) result.push_back(term);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else if (t1->mType != TermTypes::Brack && t2->mType == TermTypes::Brack) {
|
||||
// one term / multi terms
|
||||
auto t2_Brack = convertToBracket(t2);
|
||||
|
||||
vector<Term*> result;
|
||||
for (int i = 0; i < t2_Brack->mTerms.size(); i++) {
|
||||
if (t2_Brack->mTerms[i]->mType == TermTypes::Op) {
|
||||
result.push_back(t2_Brack->mTerms[i]);
|
||||
}
|
||||
|
||||
auto resultant = Div(t1, t2_Brack->mTerms[i]);
|
||||
for (auto *term : resultant) result.push_back(term);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "../../terms/Term.h"
|
||||
#include "../../terms/Variable.h"
|
||||
#include "../../terms/Paranthesis.h"
|
||||
#include "../../terms/Fraction.h"
|
||||
#include "../../tokenizer.h"
|
||||
|
||||
#include "../../../vendor/lexertk.hpp"
|
||||
|
@ -34,7 +35,7 @@ private: // General Utilites
|
|||
vector<Term*> getRangeOfTerms(vector<Term*> terms, int begin, int end);
|
||||
|
||||
Bracket* convertToBracket(Term* t1);
|
||||
Variable* converToVariable(Term* t1);
|
||||
Variable* convertToVariable(Term* t1);
|
||||
Constant* convertToConstant(Term* t1);
|
||||
|
||||
bool IsHigherSig(Term* t1, Term* t2);
|
||||
|
@ -49,15 +50,26 @@ private: // General Utilites
|
|||
private: // Power Evaluation
|
||||
vector<Term*> ReducePower(Term* t1);
|
||||
|
||||
public: // Addition Evaluation // TODO: PUBLIC AFTER TESTING
|
||||
public: // Addition Evaluation // TODO: PRIVATE AFTER TESTING
|
||||
vector<Term*> Add(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
|
||||
|
||||
public: // Subtraction Evaluation // TODO: PUBLIC AFTER TESTING
|
||||
public: // Subtraction Evaluation // TODO: PRIVATE AFTER TESTING
|
||||
vector<Term*> Sub(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
|
||||
|
||||
public: // Multiplication Evaluation // TODO: PUBLIC AFTER TESTING
|
||||
public: // Multiplication Evaluation // TODO: PRIVATE AFTER TESTING
|
||||
vector<Term*> Mul(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
|
||||
|
||||
public: // Division Evaluation // TODO: PRIVATE AFTER TESTING
|
||||
bool IsDivSolvable(Term* t1, Term* t2);
|
||||
bool IsDivSpecialCase(Term* t1, Term* t2);
|
||||
|
||||
vector<Term*> gcdofTerms(Term* t1, Term* t2);
|
||||
vector<Term*> FactorizeTermsToBrack(vector<Term*> terms, vector<Term*> terms2);
|
||||
vector<Term*> FactorizeTermsToBrack(vector<Term*> terms);
|
||||
|
||||
bool TermsMatch(vector<Term*> terms1, vector<Term*> terms2);
|
||||
|
||||
vector<Term*> Div(Term* t1, Term* t2, Identifier_t order = Identifier_t::_high_order_left);
|
||||
private:
|
||||
QMRuleSet mRuleSet;
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef FRACTION_H
|
||||
#define FRACTION_H
|
||||
#pragma once
|
||||
#include "../defines.h"
|
||||
#include "Term.h"
|
||||
using namespace std;
|
||||
|
||||
class Fraction: public Term {
|
||||
public:
|
||||
Fraction(vector<Term*> nomin = {}, vector<Term*> domin = {}) {
|
||||
Term();
|
||||
mNomin = nomin;
|
||||
mDomin = domin;
|
||||
mType = TermTypes::Frac;
|
||||
}
|
||||
|
||||
public: // TODO: try to change to private
|
||||
vector<Term*> mNomin;
|
||||
vector<Term*> mDomin;
|
||||
};
|
||||
#endif // !CONSTANT_H
|
|
@ -26,6 +26,7 @@
|
|||
#include "terms/Term.h"
|
||||
#include "terms/Variable.h"
|
||||
#include "terms/Paranthesis.h"
|
||||
#include "terms/Fraction.h"
|
||||
|
||||
#include "../vendor/lexertk.hpp"
|
||||
|
||||
|
@ -163,6 +164,43 @@ static vector<Term*> combineBrackets(vector<Term*> terms) {
|
|||
return result;
|
||||
}
|
||||
|
||||
static vector<Term*> combineOpWithTerms(vector<Term*> terms) {
|
||||
vector<Term*> result;
|
||||
|
||||
for (int i = 0; i < terms.size(); i++) {
|
||||
if (terms[i]->mType == TermTypes::Op) {
|
||||
// operator detected
|
||||
auto op = static_cast<Operator*>(terms[i]);
|
||||
if (op->mOperator == '/') {
|
||||
// division found
|
||||
|
||||
// check if it was the first
|
||||
if (i == 0) {
|
||||
// invalid
|
||||
cout << "Can't divide with a Nill nominator!" << endl;
|
||||
system("PAUSE");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
Fraction* frac = new Fraction();
|
||||
frac->mDomin.push_back(terms[i + 1]);
|
||||
frac->mNomin.push_back(terms[i - 1]);
|
||||
result.pop_back(); // pop the nominator, before push
|
||||
result.push_back(frac);
|
||||
|
||||
// consume the dominator
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
result.push_back(terms[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static vector<Term*> tokenize(lexertk::generator lexed) {
|
||||
vector<Term*> result;
|
||||
|
||||
|
@ -321,8 +359,9 @@ static vector<Term*> tokenize(lexertk::generator lexed) {
|
|||
i = tok.end; // no need to increment, automatically done in loop statment
|
||||
}
|
||||
|
||||
// post-fix fixes
|
||||
result = combineBrackets(result);
|
||||
|
||||
result = combineOpWithTerms(result);
|
||||
return result;
|
||||
}
|
||||
#endif // !TOKENIZER_H
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue