public void Rules_DivisionEqualsOneRule() { ExpressionBase selection1; ExpressionBase parent; parent = selection1 = Make.Divide(Make.New(15), Make.New(15)); var suggestion = Rules.DivisionEqualsOneRule(parent, new List<ExpressionBase>() { selection1 }); Assert.IsNotNull(suggestion); NumericExpression a = new NumericExpression(1); NumericExpression b = new NumericExpression(2); Assert.IsTrue(suggestion == a); Assert.IsFalse(suggestion == b); }
public ExpressionBase Parse(List<Token> postFix) { var stack = new ExpressionStack(); ExpressionBase root = null; ExpressionBase left = null; ExpressionBase right = null; foreach (var token in postFix) { switch (token.Type) { case TokenType.Function: root = new FunctionExpression(stack.Pop(), (string)token.Data); stack.Push(root); break; case TokenType.Delimiter: switch (token.Data.ToString()) { case "()": root = new DelimiterExpression(stack.Pop()); stack.Push(root); break; case "{}": root = stack.Pop(); stack.Push(root); break; } break; case TokenType.Number: root = new NumericExpression(int.Parse(token.Data.ToString())); stack.Push(root); break; case TokenType.Constant: root = new ConstantExpression((ConstantType)token.Data); stack.Push(root); break; case TokenType.Variable: root = new VariableExpression((string)token.Data); stack.Push(root); break; case TokenType.Operator: switch (token.Data.ToString()) { case "~": root = new UnaryMinusExpression(stack.Pop()); stack.Push(root); break; case "+": right = stack.Pop(); left = stack.Pop(); if (left is VariadicOperatorExpression && (left as VariadicOperatorExpression).Type == OperatorType.Add) { (left as VariadicOperatorExpression).Add(right); root = left; stack.Push(root); } else { root = new VariadicOperatorExpression(OperatorType.Add, left, right); stack.Push(root); } break; case "-": if (this.TreatMinusAsUnaryMinusInVariadicPlus) { right = new UnaryMinusExpression(stack.Pop()); left = stack.Pop(); if (left is VariadicOperatorExpression && (left as VariadicOperatorExpression).Type == OperatorType.Add) { (left as VariadicOperatorExpression).Add(right); root = left; stack.Push(root); } else { root = new VariadicOperatorExpression(OperatorType.Add, left, right); stack.Push(root); } } else // treat it at binary operator { right = stack.Pop(); left = stack.Pop(); root = new BinaryOperatorExpression(left, right, OperatorType.Subtract); stack.Push(root); } break; case "*": right = stack.Pop(); left = stack.Pop(); if (left is VariadicOperatorExpression && (left as VariadicOperatorExpression).Type == OperatorType.Multiply) { (left as VariadicOperatorExpression).Add(right); root = left; stack.Push(root); } else { root = new VariadicOperatorExpression(OperatorType.Multiply, left, right); stack.Push(root); } break; case "/": right = stack.Pop(); left = stack.Pop(); root = new BinaryOperatorExpression(left, right, OperatorType.Divide); stack.Push(root); break; case "^": right = stack.Pop(); left = stack.Pop(); root = new BinaryOperatorExpression(left, right, OperatorType.Power); stack.Push(root); break; } break; } } return root; }
//-a = (-1)*a public static ExpressionBase FactorizeUnaryMinus(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is unary minus var unaryMinusExpression = expression as UnaryMinusExpression; if (unaryMinusExpression != null) { //Return product of operand and (-1) var numericExpression = new NumericExpression(1); var suggestion = new VariadicOperatorExpression(OperatorType.Multiply, new UnaryMinusExpression(numericExpression), unaryMinusExpression.Expression.Clone()); return suggestion; } return null; }
//6 = 2*3 public static ExpressionBase FactorizationRule(ExpressionBase expression, List<ExpressionBase> selection) { VariadicOperatorExpression suggestion; //If expression is a number if (expression is NumericExpression && expression != null) { var numericExpression = selection[0] as NumericExpression; var n = numericExpression.Number; //Find integers a != 1 and b != 1 such that n = a*b for (int count = 2; count < n; count++) { if (n % count == 0) { NumericExpression a = new NumericExpression(count); NumericExpression b = new NumericExpression(n / count); //Return product of a and b suggestion = new VariadicOperatorExpression(OperatorType.Multiply, a, b); return suggestion; } } } return null; }
//a^n*a^m = a^{n+m} public static ExpressionBase ExponentProduct(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a product. e.g. a*a^2 VariadicOperatorExpression product = expression as VariadicOperatorExpression; if (product != null && product.Type == OperatorType.Multiply) { List<ExpressionBase> sum = new List<ExpressionBase>(); ExpressionBase commonBase = null; //Foreach operand in product foreach (var operand in product) { ExpressionBase operandLeft = operand; ExpressionBase operandRight = new NumericExpression(1); BinaryOperatorExpression power = operand as BinaryOperatorExpression; if (power != null && power.Type == OperatorType.Power) { operandLeft = power.Left; operandRight = power.Right; } //If operand's base equals commonBase. if (operandLeft == commonBase || commonBase == null) { //Add operands exponent to sum. commonBase = operandLeft; sum.Add(operandRight.Clone()); } else { return null; } } if (sum.Count > 1) { //Return power with common base and sum of all operands' exponents. VariadicOperatorExpression suggestionRight = new VariadicOperatorExpression(OperatorType.Add, sum[0], sum[1]); suggestionRight.Add(sum.Skip(2).ToList()); return new BinaryOperatorExpression(commonBase, suggestionRight, OperatorType.Power); } } return null; }
//a/a = 1 public static ExpressionBase DivisionEqualsOneRule(ExpressionBase expression, List<ExpressionBase> selection) { //If expression is a fraction var fraction = expression as BinaryOperatorExpression; if (fraction != null && fraction.Type == OperatorType.Divide) { //If numerator and denominator are equal if (fraction.Left == fraction.Right) { //return 1 NumericExpression suggestion = new NumericExpression(1); return suggestion; } } return null; }