Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Първа и Втора задача са комбинирани в една задача като първа задача е описана в метода ReverseShuntingYard(), а втора в Calculator() – за да се проследят операциите една след друга.
- namespace ConsoleApp2
- {
- using System;
- using System.Collections.Generic;
- using System.Text;
- class Program
- {
- static void Main()
- {
- // 6/(2*3-4)+(9/3-2)*2 TEST
- // (9/(5-6/2)-1)*2+8/(7-3) HW
- string str = "(9/(5-6/2)-1)*2+8/(7-3)";
- Console.WriteLine(str);
- string reverse = ReverseShuntingYard(str);
- Console.WriteLine(reverse);
- char finalSum = Calculator(reverse);
- Console.WriteLine(finalSum);
- }
- private static string ReverseShuntingYard(string str)
- {
- Stack<char> stack = new Stack<char>();
- StringBuilder finalResult = new StringBuilder(); // Създаваме си StringBuilder за да пестим RAM памет
- for (int i = 0; i < str.Length; i++) // Обхождаме израза
- {
- char x = str[i]; // стойността на позицията която сме в момента
- if (x == '(')
- stack.Push(x); // От условие: Ако е отваряща скоба, се добавя в стека;
- else if (x == ')')
- {
- //Ако е затваряща скоба, от стека в крайния израз се прехвърлят всички операции
- while (stack.Count > 0 && stack.Peek() != '(')
- finalResult.Append(stack.Pop());
- stack.Pop(); //докато се достигне отваряща скоба, която се премахва.
- }
- else if (char.IsDigit(x)) // От 0 до 9
- {
- finalResult.Append(x); // Ако поредният символ е число, се прехвърля в крайния израз;
- }
- else // Тук могат да бъдат подадени '-','+','*','/' по условие няма други случаи
- {
- while (stack.Count > 0 && stack.Peek() != '(' && Prior(x) <= Prior(stack.Peek()))
- // Ако стекът е празен или стигнем да затваряща скоба спираме -> от условие
- //Ако е операция, от стека в крайния израз се прехвърлят всички операции
- //с равен или по - висок приоритет(Prior(x))
- finalResult.Append(stack.Pop());
- stack.Push(x); // Новата операция се добавя в стека
- }
- //За тестване
- //Console.WriteLine($"FinalResult: {finalResult.ToString()}");
- //Console.WriteLine($"Stack: {string.Join("", stack)}");
- }
- //Ако след прочитането на целия израз в стека са останали елементи,
- //те се прехвърлят в крайния израз
- while (stack.Count > 0)
- {
- finalResult.Append(stack.Pop());
- }
- return finalResult.ToString();
- }
- //По отношение на основните 4 операции се установяват следните приоритети:
- //1: събиране и изваждане
- //2: умножение и деление
- private static int Prior(char c)
- {
- return c switch
- {
- '+' => 1,
- '-' => 1,
- '*' => 2,
- _ => 2 // Default случеят е делене '/', защото по условие не се очаква да бъдат
- //подавани други стойности за да има exception
- };
- }
- private static char Calculator(string str)
- {
- Stack<char> stack = new Stack<char>();
- for (int i = 0; i < str.Length; i++) // Обхождаме ОПЗ
- {
- char x = str[i]; // стойността на позицията която сме в момента
- if (char.IsDigit(x)) // От 0 до 9
- {
- stack.Push(x);
- }
- else // По условие нямаме други случаи освен '*' '/' '+' '-' и горе споменатите 0 -9
- {
- // Взимаме Първият и Вторият елемент и извършваме дадената операция (в обратен ред понеже е стек)
- double secondNumber = double.Parse(FindFirstNumber(stack).ToString());
- double firstNumber = double.Parse(FindFirstNumber(stack).ToString());
- string charSum = Calculate(x, firstNumber, secondNumber).ToString();
- // Пресмятаме дадената операция и връщаме първият индекс на string-ът, защото стекът ни е от тип char
- stack.Push(charSum[0]);
- }
- }
- return stack.Peek();
- }
- private static char FindFirstNumber(Stack<char> stack)
- {
- char firstNumber = ' ';
- bool foundNumber = false;
- // Създаваме си опашка за да може в правилен ред да подредим същият ред на стека
- Stack<char> queue = new Stack<char>();
- while (stack.Count != 0)
- {
- // Ако е число и още не сме намерили число
- if (char.IsDigit(stack.Peek()) && foundNumber == false)
- {
- firstNumber = stack.Pop();
- foundNumber = true; // След като сме намерили число не е нужно да презаписваме стойността на firstNumber
- }
- else
- {
- queue.Push(stack.Pop());
- }
- }
- if(firstNumber == ' ') // Ако не е намерило число сме сбъркали някъде и дава грешка
- {
- throw new NotImplementedException("Error");
- }
- foreach (char symb in queue) // Връщаме стекът в началният му вид
- {
- stack.Push(symb);
- }
- return firstNumber;
- }
- private static double Calculate(char c, double firstNumber, double secondNumber)
- {
- return c switch
- {
- '+' => firstNumber + secondNumber,
- '-' => firstNumber - secondNumber,
- '*' => firstNumber * secondNumber,
- _ => firstNumber / secondNumber // Default случеят е делене '/', защото по условие не се очаква да бъдат
- //подавани други стойности за да има exception
- };
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement