UVa Problem
This problem is about how to solve a linear equation. Since we're sure that it will always be a linear equation, the solution is simple.
we have a complex equation like this "(42-6*7)*x=2*5-10"
my solution divides the equation into two expressions around the "=" operator.
then we reduce each expression into one of the form "a * x + b" where "a" and "b" are integers.
so we reduces the whole equation to "a1 * x + b1 = a2 * x + b2"
there are three possibilities:
Code:
This problem is about how to solve a linear equation. Since we're sure that it will always be a linear equation, the solution is simple.
we have a complex equation like this "(42-6*7)*x=2*5-10"
my solution divides the equation into two expressions around the "=" operator.
then we reduce each expression into one of the form "a * x + b" where "a" and "b" are integers.
so we reduces the whole equation to "a1 * x + b1 = a2 * x + b2"
there are three possibilities:
- "a1 = a2" and "b1 = b2", in this case we have an infinite number of solutions as any value of x will satisfy the equation.
- "a1 = a2" and "b1 != b2", then we have no solutions as no value of x will ever satisfy the equation.
- "a1 != a2", then we can calculate "x" simply as "x" = (b2 - b1) / (a1 - a2).
Code:
#include <iostream>
#include <vector>
#include <cstdio>
#include <string>
#include <sstream>
using namespace std;
enum TokenType
{
TOKEN_INT,
TOKEN_EQ,
TOKEN_X,
TOKEN_LP,
TOKEN_RP,
TOKEN_PLUS,
TOKEN_MINUS,
TOKEN_MUL,
TOKEN_END
};
class Token
{
public:
Token(TokenType tokType) : mType(tokType)
{
}
TokenType getType()
{
return mType;
}
private:
TokenType mType;
};
class IntToken : public Token
{
public:
IntToken(int value) : mValue(value),
Token(TOKEN_INT)
{
}
int getValue()
{
return mValue;
}
private:
int mValue;
};
class Lexer
{
public:
Lexer(istream& iStream) : mStream(iStream)
{
}
Token* getNextToken()
{
int ch = mStream.get();
char ccc = (char)ch;
while(ch == ' ')
ch = mStream.get();
switch(ch)
{
case '=':
return new Token(TOKEN_EQ);
break;
case '+':
return new Token(TOKEN_PLUS);
break;
case '-':
return new Token(TOKEN_MINUS);
break;
case '*':
return new Token(TOKEN_MUL);
break;
case 'x':
return new Token(TOKEN_X);
break;
case '(':
return new Token(TOKEN_LP);
break;
case ')':
return new Token(TOKEN_RP);
break;
case EOF:
return new Token(TOKEN_END);
break;
default:
if(ch >= '0' && ch <= '9')
{
int number = 0;
while(ch >= '0' && ch <= '9')
{
number *= 10;
number += ch - '0';
ch = mStream.get();
}
mStream.putback(ch);
return new IntToken(number);
}
else
{
return new Token(TOKEN_END);
}
break;
}
}
private:
istream& mStream;
};
class Solver
{
public:
Solver(istringstream& exprStream):
mLexer(exprStream), mCurrTok(0)
{
mCurrTok = mLexer.getNextToken();
pair<int, int> result = expr();
m_x = result.first;
m_num = result.second;
}
int get_xFactor()
{
return m_x;
}
int get_numFactor()
{
return m_num;
}
private:
pair<int, int> expr()
{
pair<int, int> result = term();
pair<int, int> tmp = rExpr();
result.first += tmp.first;
result.second += tmp.second;
return result;
}
pair<int, int> rExpr()
{
pair<int, int> result = make_pair(0, 0);
if(mCurrTok->getType() == TOKEN_PLUS)
{
match(TOKEN_PLUS);
pair<int, int> tmp = term();
result.first += tmp.first;
result.second += tmp.second;
tmp = rExpr();
result.first += tmp.first;
result.second += tmp.second;
}
else if (mCurrTok->getType() == TOKEN_MINUS)
{
match(TOKEN_MINUS);
pair<int, int> tmp = term();
result.first -= tmp.first;
result.second -= tmp.second;
tmp = rExpr();
result.first += tmp.first;
result.second += tmp.second;
}
return result;
}
pair<int, int> term()
{
pair<int, int> tmp1 = factor();
pair<int, int> tmp2 = rTerm();
return make_pair(tmp1.first * tmp2.second +
tmp1.second * tmp2.first,
tmp1.second * tmp2.second);
}
pair<int, int> rTerm()
{
if(mCurrTok->getType() == TOKEN_MUL)
{
match(TOKEN_MUL);
return term();
}
return make_pair(0, 1);;
}
pair<int, int> factor()
{
if(mCurrTok->getType() == TOKEN_X)
{
match(TOKEN_X);
return make_pair(1, 0);
}
else if(mCurrTok->getType() == TOKEN_INT)
{
IntToken* intTok = (IntToken*)mCurrTok;
int val = intTok->getValue();
match(TOKEN_INT);
return make_pair(0, val);
}
else
{
match(TOKEN_LP);
pair<int, int> exprVal = expr();
match(TOKEN_RP);
return exprVal;
}
}
bool match(TokenType tokType)
{
if(mCurrTok->getType() == tokType)
{
delete mCurrTok;
mCurrTok = mLexer.getNextToken();
return true;
}
else
{
// Handle errors
}
return false;
}
private:
Lexer mLexer;
Token *mCurrTok;
int m_num;
int m_x;
};
int main(int argc, char* argv[])
{
string strLine;
int iEqu = 1;
bool firstTime = true;
while(cin >> strLine)
{
istringstream inputStream(strLine);
int iPos = strLine.find_first_of('=');
string expr1 = strLine.substr(0, iPos);
string expr2 = strLine.substr(iPos+1);
istringstream strStream1(expr1);
istringstream strStream2(expr2);
Solver s1(strStream1);
Solver s2(strStream2);
if(!firstTime)
cout << '\n';
else
firstTime = false;
cout << "Equation #" << iEqu << endl;
if(s1.get_xFactor() == s2.get_xFactor())
{
if(s1.get_numFactor() == s2.get_numFactor())
{
cout << "Infinitely many solutions.\n";
}
else
{
cout << "No solution.\n";
}
}
else
{
double x = (double)(s2.get_numFactor() -
s1.get_numFactor())/
(double)(s1.get_xFactor() -
s2.get_xFactor());
printf("x = %.6f\n", x);
}
++iEqu;
}
return 0;
}
No comments:
Post a Comment