//------------------------------------------------------------------------------------------------------------
        public static decimal Evaluate(string postfix)
        {
            bool debug = false;

            if (Toolbelt.HasLetters(postfix))
            {
                return(0M);
            }
            Stack <string>  expression = new Stack <string>(postfix.Split(' ').Reverse());
            Stack <decimal> operands   = new Stack <decimal>();

            while (expression.Count > 0)
            {
                if (debug)
                {
                    Toolbelt.DisplayStack(expression, "expression");
                    Toolbelt.DisplayStack(operands, "operands");
                }

                string  working = expression.Pop();
                decimal value;
                if (Decimal.TryParse(working, out value))
                {
                    operands.Push(value);
                }
                else if (working.Length == 1 && Toolbelt.IsOperator(working[0]))
                {
                    if (operands.Count >= 2)
                    {
                        var x = operands.Pop();
                        var y = operands.Pop();
                        operands.Push(calculate(y, working[0], x));
                    }
                }
            }

            return(operands.Pop());
        }
Exemplo n.º 2
0
        //------------------------------------------------------------------------------------------------------------
        public static string Convert(string infix, bool allowLetters = true)
        {
            string name = "InfixToPostfix.Convert";

            if (infix == null)
            {
                throw new ArgumentNullException($"{name} infix value cannot be null");
            }
            if (infix.Trim() == "")
            {
                throw new ArgumentException($"{name} infix value must not be empty");
            }
            if (infix.Trim().Length <= 0)
            {
                throw new ArgumentException($"{name} infix value must have at least one character");
            }
            Toolbelt.StripWhiteSpace(ref infix);

            Stack <char>   infixStack = new Stack <char>(infix.ToCharArray().Reverse());
            StringBuilder  postFix    = new StringBuilder();
            Stack <string> operators  = new Stack <string>();
            int            counter    = 0;

            while (infixStack.Count > 0)
            {
                ++counter;

                if (debug)
                {
                    Toolbelt.DisplayStack(infixStack, $"{counter}::  infixStack");
                    Toolbelt.DisplayStack(operators, $"{counter}::   operators");
                    Console.WriteLine(counter + "::     postfix: " + postFix.ToString() + "\n");
                }
                char          ch       = infixStack.Peek();
                StringBuilder newChars = new StringBuilder();
                if (Char.IsNumber(ch))
                {
                    StringBuilder number = new StringBuilder();
                    number.Append(infixStack.Pop());
                    while (infixStack.Count > 0 && Char.IsNumber(infixStack.Peek()))
                    {
                        number.Append(infixStack.Pop());
                    }
                    newChars.Append(number + " ");
                }
                else if (allowLetters && Char.IsLetter(ch))
                {
                    newChars.Append(infixStack.Pop() + " ");
                    if (infixStack.Count > 0 && Char.IsLetter(infixStack.Peek()))
                    {
                        throw new SystemException($"{name} variables in infix value can only be one character");
                    }
                }
                else if (ch == '(')
                {
                    operators.Push(infixStack.Pop().ToString());
                }
                else if (ch == ')')
                {
                    string op = operators.Pop();
                    while (op != "(")
                    {
                        newChars.Append(op + " ");
                        if (operators.Count == 0)
                        {
                            break;
                        }
                        op = operators.Pop();
                    }

                    infixStack.Pop(); // discard the left parenthesis
                }
                else
                {
                    if (operators.Count > 0 && comparePrecedence(operators.Peek(), ch) >= 0)
                    {
                        string op = operators.Pop();
                        while (true)
                        {
                            newChars.Append(op + " ");
                            if (operators.Count == 0)
                            {
                                break;
                            }
                            if (comparePrecedence(operators.Peek(), ch) < 0)
                            {
                                break;
                            }
                            op = operators.Pop();
                        }
                        operators.Push(infixStack.Pop().ToString());
                    }
                    else
                    {
                        operators.Push(infixStack.Pop().ToString());
                    }
                }
                int oldPFLengh     = postFix.Length;
                int newCharsLength = newChars.Length;
                postFix.Append(newChars);
                if (postFix.Length != (oldPFLengh + newCharsLength))
                {
                    Console.WriteLine("Error appending to postfix");
                    Toolbelt.DisplayStack(operators, "operators");
                    Console.WriteLine($"postfix: {postFix}");
                }
            }

            while (operators.Count > 0)
            {
                postFix.Append(operators.Pop() + " ");
            }
            if (infixStack.Count > 0 || operators.Count > 0)
            {
                Toolbelt.DisplayStack(infixStack, "infix");
                Toolbelt.DisplayStack(operators, "operators");
            }
            return(postFix.ToString().Trim());
        }