/** <summary>Returns true/false depending on whether the expession is valid or not (Respectively)</summary> * * <remarks>The region "SPECIFIC_CASES" detect whether an expression is a lone variable or a lone number. * <example>"someVariable" for a lone variable, and "-10" for a lone number</example> * Furthermore, the function also checks the following: * <list type="bullet"> * <item><term>If the last character of the expression is an operator</term></item> * <item><term>If the all the values in the expression list are numbers separated by spaces</term></item> * <item><term>If the parenthesis are in the right order and properly formatted</term></item> * </list></remarks> */ // ReSharper disable once CognitiveComplexity private bool IsExpressionValid() { #region SPECIFIC_CASES //Lone number case if (CheckMethods.IsANumber(InputExpression)) { return(true); } //Lone variable case if (CheckMethods.IsAVariable(InputExpression) && ExpressionList.Count == 1) { return(true); } #endregion //checks if the last character is an operator if (CheckMethods.IsAValidOperator(InputExpression[^ 1].ToString()) ||
/** <summary>If the expression is valid, the method solves the expression. Otherwise, it will return null * if the method is called and the validity of the expression is false, it will return null </summary> * * <remarks>The method turns the expression (which is in infix notation) into its postfix expression using the * <see cref="ExpressionManipulation.InfixToPostfix(string[])"/> function, then solves the expression using * a postfix expression solving algorithm described * <a href="https://runestone.academy/runestone/books/published/pythonds/BasicDS/InfixPrefixandPostfixExpressions.html">here</a>. * </remarks>. */ // ReSharper disable once CognitiveComplexity public double?Solve() { if (!IsValid) { AnsiConsole.MarkupLine("[red]Cannot solve expression as it is invalid![/]"); return(null); } //If the expression is a lone number, output it back if (CheckMethods.IsANumber(InputExpression)) { var value = double.Parse(InputExpression); Variables.SetAns(value.ToString()); return(value); } //If the expression is a lone variable, output its value back if (CheckMethods.IsAVariable(InputExpression) && ExpressionList.Count == 1) { var value = Variables.GetValue(InputExpression); if (value is not null) { Variables.SetAns(value.ToString()); return(value); } AnsiConsole.MarkupLine($"[red]The variable \"{InputExpression}\" is not initialized![/]"); return(null); } //Creates a copy of the list int o a string array var tempExpressionList = new string[ExpressionList.Count]; for (var i = 0; i < ExpressionList.Count; i++) { tempExpressionList[i] = ExpressionList[i]; } //substitutes the values of the variables in the expression. At this point, ALL variables are defined (checked). //A copy is used so the expression can mamintain its variables, so the value of a variable can change if the //vaues in its variables (if it has any) change. for (var i = 0; i < tempExpressionList.Length; i++) { if (CheckMethods.IsAFunction(tempExpressionList[i])) { continue; } if (!CheckMethods.IsAVariable(tempExpressionList[i])) { continue; } tempExpressionList[i] = Variables.GetValue(tempExpressionList[i]).ToString(); } var postfixExpression = ExpressionManipulation.InfixToPostfix(tempExpressionList); Stack <double> operandStack = new Stack <double>(); foreach (var token in postfixExpression) { if (CheckMethods.IsANumber(token)) { operandStack.Push(double.Parse(token)); continue; } //if it is a trigonometric function, it only needs the top of the stack. So it pops, calculates, then //pushes again. if (CheckMethods.IsAFunction(token)) { operandStack.Push(Computation.Compute(operandStack.Pop(), token)); continue; } //if its not a number, it is an operator var number2 = operandStack.Pop(); var number1 = operandStack.Pop(); operandStack.Push(Computation.Compute(number1, number2, token)); } if (operandStack.Count == 1) { var value = operandStack.Pop(); Variables.SetAns(value.ToString()); //sets the "ans" variable to this value return(value); } AnsiConsole.MarkupLine("[red]Invalid Expression (at Solve)[/]"); return(null); }