예제 #1
0
        public Expression(string inputExpression)
        {
            InputExpression = inputExpression.Trim();

            try
            {
                ExpressionList = ExpressionManipulation.GetExpressionInListForm(inputExpression);
                IsValid        = IsExpressionValid();
            }
            catch (Exception)
            {
                IsValid = false;
            }
        }
예제 #2
0
        /** <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);
        }