Advertisement
Guest User

Untitled

a guest
Jul 21st, 2017
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.35 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6. using System.Threading;
  7. using System.Globalization;
  8.  
  9. namespace ShuntingYardAlgorithm
  10. {
  11.     class ShuntingYardAlgorithm
  12.     {
  13.         private Stack<string> pendingTokens;
  14.         private string[] inputTokens;
  15.         private List<string> outputTokens;
  16.  
  17.         public List<string> Transform(string expression)
  18.         {
  19.             Initialize(expression);
  20.             ProcessTokens();
  21.             return outputTokens;
  22.         }
  23.  
  24.         private void Initialize(string expression)
  25.         {
  26.             pendingTokens = new Stack<string>();
  27.             inputTokens = new string[expression.Length];
  28.             inputTokens = DevideExpressionIntoPieces(expression ?? "");
  29.             outputTokens = new List<string>();
  30.         }
  31.  
  32.         private string[] DevideExpressionIntoPieces(string expression)
  33.         {
  34.             string current = String.Empty;
  35.             int inputIndex = 0;
  36.             for (int i = 0; i < expression.Length; i++)
  37.             {
  38.                 current = expression[i].ToString();
  39.                 if (IsTokenPartOfNumber(current, inputIndex))
  40.                 {
  41.                     inputTokens[inputIndex - 1] += current;
  42.                 }
  43.                 else if (IsTokenPartOfFunctionName(current, inputIndex))
  44.                 {
  45.                     inputTokens[inputIndex - 1] += current;
  46.                 }
  47.                 else
  48.                 {
  49.                     if (current == " ")
  50.                     {
  51.                         continue;
  52.                     }
  53.                     inputTokens[inputIndex++] = current;
  54.                 }
  55.             }
  56.             return inputTokens;
  57.         }
  58.  
  59.         private bool IsTokenPartOfFunctionName(string current, int inputIndex)
  60.         {
  61.             return inputIndex > 0 && IsFunctionName(current) && isPreviousTokenPartOfFunctionName(inputTokens[inputIndex - 1]);
  62.         }
  63.  
  64.         private bool IsTokenPartOfNumber(string current, int inputIndex)
  65.         {
  66.             return inputIndex > 0 && isNumber(current) && isNumber(inputTokens[inputIndex - 1]);
  67.         }
  68.  
  69.         private bool isPreviousTokenPartOfFunctionName(string token)
  70.         {
  71.             return Regex.IsMatch(token, @"([a-zA-Z])");
  72.         }
  73.  
  74.         private bool isNumber(string token)
  75.         {
  76.             return Regex.IsMatch(token, @"([0-9.])");
  77.         }
  78.  
  79.         private void ProcessTokens()
  80.         {
  81.             foreach (string current in inputTokens)
  82.             {
  83.                 if (current == null)
  84.                 {
  85.                     break;
  86.                 }
  87.                 if (current == String.Empty)
  88.                 {
  89.                     continue;
  90.                 }
  91.                 if (isNumber(current))
  92.                 {
  93.                     AppendToken(current);
  94.                 }
  95.                 else if ("(" == current)
  96.                 {
  97.                     HandleOpenParantheses();
  98.                 }
  99.                 else if (")" == current)
  100.                 {
  101.                     HandleCloseParantheses();
  102.                 }
  103.                 else if ("," == current)
  104.                 {
  105.                     HandleParameterSeperator();
  106.                 }
  107.                 else
  108.                 {
  109.                     HandleOperator(current);
  110.                 }
  111.             }
  112.             AppendAllPendingTokens();
  113.         }
  114.  
  115.         private void HandleParameterSeperator()
  116.         {
  117.             while (!pendingTokens.Peek().Equals("("))
  118.             {
  119.                 AppendPendingToken();
  120.             }
  121.         }
  122.  
  123.         private void HandleOpenParantheses()
  124.         {
  125.             pendingTokens.Push("(");
  126.         }
  127.  
  128.         private void MoveLastOutputTokenToPendingTokens()
  129.         {
  130.             pendingTokens.Push(outputTokens[CalculateIndexOfLastOutputToken()]);
  131.             outputTokens.RemoveAt(CalculateIndexOfLastOutputToken());
  132.         }
  133.  
  134.         private int CalculateIndexOfLastOutputToken()
  135.         {
  136.             return outputTokens.Count - 1;
  137.         }
  138.  
  139.         private bool LastOutputTokenIsFunctionName()
  140.         {
  141.             return outputTokens.Count > 0 && IsFunctionName(outputTokens[CalculateIndexOfLastOutputToken()]);
  142.         }
  143.  
  144.         private bool IsFunctionName(string token)
  145.         {
  146.             bool result = isPreviousTokenPartOfFunctionName(token);
  147.             if (token[token.Length - 1] == ')')
  148.             {
  149.                 return false;
  150.             }
  151.             return result;
  152.         }
  153.  
  154.         private void HandleCloseParantheses()
  155.         {
  156.             while (!pendingTokens.Peek().Equals("("))
  157.             {
  158.                 AppendPendingToken();
  159.             }
  160.             pendingTokens.Pop();
  161.             ConditionallyAddFunctionNameToPendingTokens();
  162.         }
  163.  
  164.         private void ConditionallyAddFunctionNameToPendingTokens()
  165.         {
  166.             if (LastPendingTokenIsFunctionName())
  167.             {
  168.                 AppendToken(pendingTokens.Pop());
  169.             }
  170.         }
  171.  
  172.         private bool LastPendingTokenIsFunctionName()
  173.         {
  174.             return pendingTokens.Count > 0 && IsFunctionName(pendingTokens.Peek());
  175.         }
  176.  
  177.         private void HandleOperator(string current)
  178.         {
  179.             while (PendingTokenExecutesBefore(current))
  180.             {
  181.                 AppendPendingToken();
  182.             }
  183.             pendingTokens.Push(current);
  184.         }
  185.  
  186.         private void AppendAllPendingTokens()
  187.         {
  188.             while (ThereArePendingTokens())
  189.             {
  190.                 AppendPendingToken();
  191.             }
  192.         }
  193.  
  194.         private void AppendPendingToken()
  195.         {
  196.             string current;
  197.             if (ThereArePendingTokens())
  198.             {
  199.                 current = pendingTokens.Pop();
  200.                 AppendToken(current);
  201.             }
  202.         }
  203.  
  204.         private bool PendingTokenExecutesBefore(string current)
  205.         {
  206.             if (ThereArePendingTokens())
  207.             {
  208.                 int pendingPrecedence = CalculatePrecedence(pendingTokens.Peek());
  209.                 int currentPrecedence = CalculatePrecedence(current);
  210.                 return pendingPrecedence >= currentPrecedence;
  211.             }
  212.             return false;
  213.         }
  214.  
  215.         private bool ThereArePendingTokens()
  216.         {
  217.             return pendingTokens.Count > 0;
  218.         }
  219.  
  220.         private int CalculatePrecedence(string current)
  221.         {
  222.             switch (current)
  223.             {
  224.                 case "*":
  225.                 case "/":
  226.                     return 100;
  227.                 case "+":
  228.                 case "-":
  229.                     return 10;
  230.                 case "pow":
  231.                 case "ln":
  232.                 case "sqrt":
  233.                     return 1000;
  234.                 case "(":
  235.                 case ")":
  236.                     return -1;
  237.                 default:
  238.                     return 1;
  239.             }
  240.         }
  241.  
  242.         private void AppendToken(string token)
  243.         {
  244.             if (token.Length > 0)
  245.             {
  246.                 outputTokens.Add(token);
  247.             }
  248.         }
  249.  
  250.         private double CalculateOutputTokens(ref List<string> output)
  251.         {
  252.             Stack<double> outputStack = new Stack<double>();
  253.             string current;
  254.             for (int indexCurrent = 0; indexCurrent < output.Count; indexCurrent++)
  255.             {
  256.                 current = output[indexCurrent];
  257.                 if (isNumber(current))
  258.                 {
  259.                     outputStack.Push(double.Parse(current));
  260.                 }
  261.                 else
  262.                 {
  263.                     switch (current)
  264.                     {
  265.                         case "+":
  266.                             outputStack.Push(outputStack.Pop() + outputStack.Pop());
  267.                             break;
  268.                         case "-":
  269.                             if (outputStack.Count > 1)
  270.                             {
  271.                                 outputStack.Push(outputStack.Pop() * (-1) + outputStack.Pop());
  272.                             }
  273.                             else
  274.                             {
  275.                                 outputStack.Push(outputStack.Pop() * (-1));
  276.                             }
  277.                             break;
  278.                         case "*":
  279.                             outputStack.Push(outputStack.Pop() * outputStack.Pop());
  280.                             break;
  281.                         case "/":
  282.                             double devider = outputStack.Pop();
  283.                             outputStack.Push(outputStack.Pop() / devider);
  284.                             break;
  285.                         case "sqrt":
  286.                             outputStack.Push(Math.Sqrt(outputStack.Pop()));
  287.                             break;
  288.                         case "pow":
  289.                             double power = outputStack.Pop();
  290.                             outputStack.Push(Math.Pow(outputStack.Pop(), power));
  291.                             break;
  292.                         case "ln":
  293.                             outputStack.Push(Math.Log(outputStack.Pop()));
  294.                             break;
  295.                         default:
  296.                             Console.WriteLine("Error.");
  297.                             break;
  298.                     }
  299.                 }
  300.             }
  301.             double result = outputStack.Pop();
  302.             return result;
  303.         }
  304.  
  305.         static void Main(string[] args)
  306.         {
  307.             Thread.CurrentThread.CurrentCulture =
  308.             CultureInfo.GetCultureInfo("en-US");
  309.             ShuntingYardAlgorithm tr = new ShuntingYardAlgorithm();
  310.             string[] expressions = {
  311.                                      
  312.                                        "pow(2, 3.14) * (3 - (3 * sqrt(2) - 3.2) + 1.5*0.3)",
  313.                                        "  (-3 +5.3)*  2.7-  ln(22)   /  pow( 5  +  3 ,    ln  (  10  )  )   ",
  314.                                        "-(-15) - 10",
  315.                                        "-(-15 - 10)",
  316.                                        "ln(ln(ln(pow(10, sqrt(pow(1 + 2, (2 + 2*9)/10))))))",
  317.                                     };
  318.             foreach (var item in expressions)
  319.             {
  320.                 tr.Transform(item);
  321.                 Console.WriteLine(tr.CalculateOutputTokens(ref tr.outputTokens));
  322.             }
  323.         }
  324.     }
  325. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement