示例#1
0
        /** <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()) ||
示例#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);
        }