using System;
using System.Collections.Generic;
using System.Linq;
namespace Lib.Mathematics
{
public class Expression
{
internal Expression()
{
}
private List<Stack> _stacks = new List<Stack>();
public object Result { get; set; }
public string Term
{
get { return _term; }
internal set { _term = value;}
}
public readonly Dictionary<string, Expression> Variables = new Dictionary<string, Expression>();
private string _term;
public static Expression Parse(string expr)
{
var returns = new Expression {Term = expr};
expr = expr.Replace("²", "²0");
expr = expr.Replace("³", "³0");
expr = expr.Replace("sqrt[", "√");
expr = expr.Replace("pi", "π");
expr = expr.Replace("]", "");
expr = expr.Replace("√", "1√");
expr = expr.Replace("π", "1π1");
expr = expr.Replace("True", "1");
expr = expr.Replace("False", "0");
expr = returns.Variables.Aggregate(expr, (current, var) => current.Replace(var.Key + "*1", var.Value));
var chars = expr.ToCharArray();
var result = "";
foreach (var c in chars)
{
if (isNum(c))
{
result += c;
}
else
{
if (isOP(c))
{
returns._stacks.Add(new NumStack(Convert.ToDouble(result)));
returns._stacks.Add(new OpStack(c.ToString()));
result = "";
}
}
}
returns._stacks.Add(returns.getLastNum(expr));
returns._stacks = returns.dotbeforestatement(returns._stacks);
returns.Calculate();
return returns;
}
internal void Calculate()
{
for (var i = 0; i < _stacks.Count - 1; i++)
{
var stack = _stacks[i];
var opStack = stack as OpStack;
if (opStack != null)
{
var first = (NumStack)_stacks[i - 1];
var second = (NumStack)_stacks[i + 1];
var op = opStack;
var _result = new NumStack(0);
var resultisbool = false;
var boolresult = false;
switch (op.Value)
{
case "+":
_result = new NumStack(first.Value + second.Value);
break;
case "-":
_result = new NumStack(first.Value - second.Value);
break;
case "*":
_result = new NumStack(first.Value * second.Value);
break;
case "/":
_result = new NumStack(first.Value / second.Value);
break;
case "^":
_result = new NumStack(Math.Pow(first.Value, second.Value));
break;
case "%":
_result = new NumStack(first.Value % second.Value);
break;
case "&":
_result = new NumStack(Convert.ToDouble(first.Value.ToString() + second.Value.ToString()));
break;
case "²":
_result = new NumStack(first.Value * first.Value);
break;
case "³":
_result = new NumStack(first.Value * first.Value * first.Value);
break;
case "√":
_result = new NumStack(Math.Sqrt(second.Value));
break;
case "π":
_result = new NumStack(Math.PI);
break;
case "<":
resultisbool = true;
boolresult = first.Value < second.Value;
break;
case ">":
resultisbool = true;
boolresult = first.Value > second.Value;
break;
case "!":
resultisbool = true;
boolresult = first.Value != second.Value;
break;
}
_stacks.RemoveAt(0);
_stacks.RemoveAt(0);
_stacks.RemoveAt(0);
_stacks.Insert(0, _result);
Result = (_stacks[0] as NumStack).Value;
if (_stacks.Count != 1)
{
if (_stacks[0] != null && _stacks[1] != null && _stacks[2] != null)
{
Calculate();
}
}
if (resultisbool)
{
Result = boolresult;
}
}
}
}
#region "ObjectOperators"
public static Expression operator +(Expression e1, Expression e2)
{
return Parse(e1.Result + "+" + e2.Result);
}
public static bool operator ==(Expression e1, Expression e2)
{
return e1 == e2;
}
public static bool operator !=(Expression e1, Expression e2)
{
return e1 != e2;
}
public static Expression operator +(Expression e1, string e2)
{
e2 = e2.Replace("=", "");
return Parse(e2);
}
public static Expression operator -(Expression e1, Expression e2)
{
return Parse(e1.Result + "-" + e2.Result);
}
public static Expression operator *(Expression e1, Expression e2)
{
return Parse(e1.Result + "*" + e2.Result);
}
public static Expression operator /(Expression e1, Expression e2)
{
return Parse(e1.Result + "/" + e2.Result);
}
public static Expression operator <(Expression e1, Expression e2)
{
return Parse(e1.Result + "<" + e2.Result);
}
public static Expression operator >(Expression e1, Expression e2)
{
return Parse(e1.Result + ">" + e2.Result);
}
public static implicit operator Expression(string v)
{
return Parse(v);
}
public static implicit operator double(Expression instance)
{
return (double) instance.Result;
}
public static implicit operator bool(Expression instance)
{
return (bool) instance.Result;
}
public static implicit operator string(Expression instance)
{
return instance.Result.ToString();
}
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
{
return false;
}
return base.Equals(obj);
}
#endregion
#region "Help Functions"
private static bool isNum(char s)
{
double result;
return double.TryParse(s.ToString(), out result);
}
private static bool isOP(char s)
{
return s == '+' | s == '-' | s == '*' | s == '/' | s == '^' | s == '%' | s == '&' | s == '²' | s == '3' | s == '<' | s == '>' | s == '!' | s == '√' | s == 'π';
}
private bool isPunctiaton(char s)
{
return s == '*' | s == '/';
}
private bool isBracketOpen(char s)
{
return s == '(';
}
private bool isBracketClosed(char s)
{
return s == ')';
}
private NumStack getLastNum(string s)
{
var c = s.Split(Convert.ToChar((_stacks[_stacks.Count - 1] as OpStack).Value));
return new NumStack(Convert.ToInt32(c[c.Length - 1]));
}
private List<Stack> dotbeforestatement(List<Stack> st)
{
var returns = st;
for (var i = 0; i < st.Count; i++)
{
var s = st[i];
if (s is OpStack)
{
var op = s as OpStack;
if (isPunctiaton(Convert.ToChar(op.Value)))
{
if (st.Count < 3)
{
var firstop = st[i - 2];
var first = st[i - 1];
var ops = s;
var second = st[i + 1];
returns.Remove(first);
returns.Remove(ops);
returns.Remove(second);
returns.Remove(firstop);
returns.InsertRange(0, new[] { first, ops, second, firstop });
}
}
}
}
return returns;
}
#endregion
#region "Implementations"
public override int GetHashCode()
{
return base.GetHashCode();
}
public Expression Clone()
{
return this;
}
public override string ToString()
{
return Result.ToString();
}
#endregion
}
}
namespace Lib.Mathematics
{
public class CalcedStack : Stack
{
public NumStack first { get; set; }
public OpStack op { get; set; }
public NumStack second { get; set; }
public NumStack result { get; set; }
public CalcedStack()
{
first = new NumStack(0);
op = new OpStack("");
second = new NumStack(0);
}
public override string ToString()
{
return first.Value.ToString() + op.Value + second.Value.ToString();
}
}
}
namespace Lib.Mathematics
{
public class NumStack : Stack<double>
{
public NumStack(double v)
: base(v)
{
}
}
}
namespace Lib.Mathematics
{
public class OpStack : Stack<string>
{
public OpStack(string v)
: base(v)
{
}
}
}
namespace Lib.Mathematics
{
public abstract class Stack<t> : Stack
{
public t Value { get; set; }
protected Stack(t v)
{
Value = v;
}
public override string ToString()
{
return Value.ToString();
}
}
public abstract class Stack
{
}
}