Guest User

Untitled

a guest
Aug 18th, 2014
258
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. namespace MathExpression
  2. {
  3.     using System;
  4.     using System.Collections.Generic;
  5.     using System.Globalization;
  6.     using System.Text;
  7.     using System.Threading;
  8.  
  9.     public class ExpressionCalculator
  10.     {
  11.         public static List<char> arithmeticOperations = new List<char>() { '+', '-', '*', '/' };
  12.         public static List<char> brackets = new List<char>() { '(', ')' };
  13.         public static List<string> functions = new List<string>() { "pow", "sqrt", "ln", "sin", "cos", "tan" };
  14.         public static readonly Dictionary<string, double> constants = InitConstants();
  15.  
  16.         private static Dictionary<string, double> InitConstants()
  17.         {
  18.             Dictionary<string, double> dic = new Dictionary<string, double>();
  19.             dic.Add("E", 2.71828182846);
  20.             dic.Add("PI", 3.14159265359);
  21.  
  22.             return dic;
  23.         }
  24.  
  25.         public static List<string> SeparateTokens(string input)
  26.         {
  27.             var result = new List<string>();
  28.  
  29.             var number = new StringBuilder();
  30.  
  31.             for (int i = 0; i < input.Length; i++)
  32.             {
  33.                 if (input[i] == '-' && (i == 0 || input[i - 1] == ',' || input[i - 1] == '('))
  34.                 {
  35.                     number.Append('-');
  36.                 }
  37.                 else if (char.IsDigit(input[i]) || input[i] == '.')
  38.                 {
  39.                     number.Append(input[i]);
  40.                 }
  41.                 else if (!char.IsDigit(input[i]) && input[i] != '.' && number.Length != 0)
  42.                 {
  43.                     result.Add(number.ToString());
  44.                     number.Clear();
  45.                     i--;
  46.                 }
  47.                 else if (brackets.Contains(input[i]))
  48.                 {
  49.                     result.Add(input[i].ToString());
  50.                 }
  51.                 else if (arithmeticOperations.Contains(input[i]))
  52.                 {
  53.                     result.Add(input[i].ToString());
  54.                 }
  55.                 else if (input[i] == ',')
  56.                 {
  57.                     result.Add(",");
  58.                 }
  59.                 else if (i + 1 < input.Length && input.Substring(i, 2).ToLower() == "ln")
  60.                 {
  61.                     result.Add("ln");
  62.                     i++;
  63.                 }
  64.                 else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "pow")
  65.                 {
  66.                     result.Add("pow");
  67.                     i += 2;
  68.                 }
  69.                 else if (i + 3 < input.Length && input.Substring(i, 4).ToLower() == "sqrt")
  70.                 {
  71.                     result.Add("sqrt");
  72.                     i += 3;
  73.                 }
  74.                 else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "sin")
  75.                 {
  76.                     result.Add("sin");
  77.                     i += 2;
  78.                 }
  79.                 else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "cos")
  80.                 {
  81.                     result.Add("cos");
  82.                     i += 2;
  83.                 }
  84.                 else if (i + 2 < input.Length && input.Substring(i, 3).ToLower() == "tan")
  85.                 {
  86.                     result.Add("tan");
  87.                     i += 2;
  88.                 }
  89.                 else if (i + 1 < input.Length && input.Substring(i, 2).ToLower() == "pi")
  90.                 {
  91.                     result.Add("PI");
  92.                     i++;
  93.                 }
  94.                 else if (input[i].ToString().ToLower() == "e")
  95.                 {
  96.                     result.Add("E");
  97.                 }
  98.                 else
  99.                 {
  100.                     throw new ArgumentException("Invalid expression");
  101.                 }
  102.             }
  103.  
  104.             if (number.Length != 0)
  105.             {
  106.                 result.Add(number.ToString());
  107.             }
  108.  
  109.             return result;
  110.         }
  111.  
  112.         public static int Precedence(string arithmeticOperator)
  113.         {
  114.             if (arithmeticOperator == "+" || arithmeticOperator == "-")
  115.             {
  116.                 return 1;
  117.             }
  118.             else
  119.             {
  120.                 return 2;
  121.             }
  122.         }
  123.  
  124.         public static Queue<string> ConvertToReversePolishNotation(List<string> tokens)
  125.         {
  126.             Stack<string> stack = new Stack<string>();
  127.             Queue<string> queue = new Queue<string>();
  128.  
  129.             for (int i = 0; i < tokens.Count; i++)
  130.             {
  131.                 var currentToken = tokens[i];
  132.                 double number;
  133.  
  134.                 if (double.TryParse(currentToken, out number))
  135.                 {
  136.                     queue.Enqueue(currentToken);
  137.                 }
  138.                 else if (constants.ContainsKey(currentToken.ToUpper()))
  139.                 {
  140.                     queue.Enqueue(constants[currentToken.ToUpper()].ToString());
  141.                 }
  142.                 else if (functions.Contains(currentToken))
  143.                 {
  144.                     stack.Push(currentToken);
  145.                 }
  146.                 else if (currentToken == ",")
  147.                 {
  148.                     if (!stack.Contains("(") || stack.Count == 0)
  149.                     {
  150.                         throw new ArgumentException("Invalid brackets or function separator");
  151.                     }
  152.  
  153.                     while (stack.Peek() != "(")
  154.                     {
  155.                         queue.Enqueue(stack.Pop());
  156.                         // if not working => you may need to pop the "("
  157.                     }
  158.                 }
  159.                 else if (arithmeticOperations.Contains(currentToken[0]))
  160.                 {
  161.                     // if not working => refactor logic for currentToken
  162.  
  163.                     while (stack.Count != 0 && arithmeticOperations.Contains(stack.Peek()[0]) && Precedence(currentToken) <= Precedence(stack.Peek()))
  164.                     {
  165.                         queue.Enqueue(stack.Pop());
  166.                     }
  167.  
  168.                     stack.Push(currentToken);
  169.                 }
  170.                 else if (currentToken == "(")
  171.                 {
  172.                     stack.Push("(");
  173.                 }
  174.                 else if (currentToken == ")")
  175.                 {
  176.                     if (!stack.Contains("(") || stack.Count == 0)
  177.                     {
  178.                         throw new ArgumentException("Invalid brackets position");
  179.                     }
  180.  
  181.                     while (stack.Peek() != "(")
  182.                     {
  183.                         queue.Enqueue(stack.Pop());
  184.                     }
  185.  
  186.                     stack.Pop();
  187.  
  188.                     if (stack.Count != 0 && functions.Contains(stack.Peek()))
  189.                     {
  190.                         queue.Enqueue(stack.Pop());
  191.                     }
  192.                 }
  193.             }
  194.  
  195.             while (stack.Count != 0)
  196.             {
  197.                 if (brackets.Contains(stack.Peek()[0]))
  198.                 {
  199.                     throw new ArgumentException("Invalid brackets position");
  200.                 }
  201.  
  202.                 queue.Enqueue(stack.Pop());
  203.             }
  204.  
  205.             return queue;
  206.         }
  207.  
  208.         public static double GetResultFromRPN(Queue<string> queue)
  209.         {
  210.             Stack<double> stack = new Stack<double>();
  211.  
  212.             while (queue.Count != 0)
  213.             {
  214.                 string currentToken = queue.Dequeue();
  215.                 double number;
  216.  
  217.                 if (double.TryParse(currentToken, out number))
  218.                 {
  219.                     stack.Push(number);
  220.                 }
  221.                 else if (arithmeticOperations.Contains(currentToken[0]) || functions.Contains(currentToken) || constants.ContainsKey(currentToken.ToUpper()))
  222.                 {
  223.                     if (currentToken == "+")
  224.                     {
  225.                         if (stack.Count < 2)
  226.                         {
  227.                             throw new ArgumentException("Invalid expression");
  228.                         }
  229.  
  230.                         double firstValue = stack.Pop();
  231.                         double secondValue = stack.Pop();
  232.  
  233.                         stack.Push(firstValue + secondValue);
  234.                     }
  235.                     else if (currentToken == "-")
  236.                     {
  237.                         if (stack.Count < 2)
  238.                         {
  239.                             throw new ArgumentException("Invalid expression");
  240.                         }
  241.  
  242.                         double firstValue = stack.Pop();
  243.                         double secondValue = stack.Pop();
  244.  
  245.                         stack.Push(secondValue - firstValue);
  246.                     }
  247.                     else if (currentToken == "*")
  248.                     {
  249.                         if (stack.Count < 2)
  250.                         {
  251.                             throw new ArgumentException("Invalid expression");
  252.                         }
  253.  
  254.                         double firstValue = stack.Pop();
  255.                         double secondValue = stack.Pop();
  256.  
  257.                         stack.Push(secondValue * firstValue);
  258.                     }
  259.                     else if (currentToken == "/")
  260.                     {
  261.                         if (stack.Count < 2)
  262.                         {
  263.                             throw new ArgumentException("Invalid expression");
  264.                         }
  265.  
  266.                         double firstValue = stack.Pop();
  267.                         double secondValue = stack.Pop();
  268.  
  269.                         stack.Push(secondValue / firstValue);
  270.                     }
  271.                     else if (currentToken == "pow")
  272.                     {
  273.                         if (stack.Count < 2)
  274.                         {
  275.                             throw new ArgumentException("Invalid expression");
  276.                         }
  277.  
  278.                         double firstValue = stack.Pop();
  279.                         double secondValue = stack.Pop();
  280.  
  281.                         stack.Push(Math.Pow(secondValue, firstValue));
  282.                     }
  283.                     else if (currentToken == "sqrt")
  284.                     {
  285.                         if (stack.Count < 1)
  286.                         {
  287.                             throw new ArgumentException("Invalid expression");
  288.                         }
  289.  
  290.                         double value = stack.Pop();
  291.  
  292.                         stack.Push(Math.Sqrt(value));
  293.                     }
  294.                     else if (currentToken == "ln")
  295.                     {
  296.                         if (stack.Count < 1)
  297.                         {
  298.                             throw new ArgumentException("Invalid expression");
  299.                         }
  300.  
  301.                         double value = stack.Pop();
  302.  
  303.                         stack.Push(Math.Log(value));
  304.                     }
  305.                     else if (currentToken == "sin")
  306.                     {
  307.                         if (stack.Count < 1)
  308.                         {
  309.                             throw new ArgumentException("Invalid expression");
  310.                         }
  311.  
  312.                         double value = stack.Pop();
  313.  
  314.                         stack.Push(Math.Sin(value));
  315.                     }
  316.                     else if (currentToken == "cos")
  317.                     {
  318.                         if (stack.Count < 1)
  319.                         {
  320.                             throw new ArgumentException("Invalid expression");
  321.                         }
  322.  
  323.                         double value = stack.Pop();
  324.  
  325.                         stack.Push(Math.Cos(value));
  326.                     }
  327.                     else if (currentToken == "tan")
  328.                     {
  329.                         if (stack.Count < 1)
  330.                         {
  331.                             throw new ArgumentException("Invalid expression");
  332.                         }
  333.  
  334.                         double value = stack.Pop();
  335.  
  336.                         stack.Push(Math.Tan(value));
  337.                     }
  338.                 }
  339.             }
  340.  
  341.             if (stack.Count == 1)
  342.             {
  343.                 return stack.Pop();
  344.             }
  345.             else
  346.             {
  347.                 throw new ArgumentException("Invalid expression");
  348.             }
  349.         }
  350.  
  351.         public static void StartCalculating()
  352.         {
  353.             string input = Console.ReadLine().Trim();
  354.  
  355.             while (input.ToLower() != "end")
  356.             {
  357.                 try
  358.                 {
  359.                     string trimmedInput = input.Replace(" ", string.Empty);
  360.                     var separatedTokens = SeparateTokens(trimmedInput);
  361.                     var reversePolishNotation = ConvertToReversePolishNotation(separatedTokens);
  362.                     var finalResult = GetResultFromRPN(reversePolishNotation);
  363.                     Console.WriteLine(finalResult);
  364.                 }
  365.                 catch (ArgumentException exeption)
  366.                 {
  367.                     Console.WriteLine(exeption.Message);
  368.                 }
  369.  
  370.                 input = Console.ReadLine().Trim();
  371.             }
  372.         }
  373.  
  374.         public static void Main()
  375.         {
  376.             StartCalculating();
  377.         }
  378.     }
  379. }
RAW Paste Data