using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace No708 { public class Program { static void Main(string[] args) { var syntax = new Syntax(Console.ReadLine()); var expression = new Expression(); expression.Parse(syntax); var res = expression.Calc(); Console.WriteLine(res); } } public class Syntax { readonly string expression; int prev = -1; int index = 0; public char Previous => prev < 0 ? '\0' : expression[prev]; public char Current => index >= expression.Length ? '\0' : expression[index]; public Syntax(string expression) { this.expression = expression; } public void Next() { prev = index; do index++; while (Current == ' '); } } public abstract class Node { Syntax syntax; readonly List nodes = new List(); protected IReadOnlyList Nodes => nodes; protected void Add(Node node) { node.Parse(syntax); nodes.Add(node); } protected abstract void ParseCore(Syntax syntax); // ReSharper disable once ParameterHidesMember public void Parse(Syntax syntax) { nodes.Clear(); ParseCore(this.syntax = syntax); } public abstract double Calc(); } public class Letter : Node { string letter; protected override void ParseCore(Syntax syntax) { letter = syntax.Current.ToString(); syntax.Next(); } public override double Calc() { throw new Exception("LetterNodeは計算できません"); } public override string ToString() { return letter; } } public class Number : Node { // ::= ('0'-'9') {'0'-'9'} ['.'{'0'-'9'}] protected override void ParseCore(Syntax syntax) { var dots = 0; if (!char.IsDigit(syntax.Current)) throw new Exception("NumberNodeは数字から始まる必要があります"); while (char.IsDigit(syntax.Current) || (syntax.Current == '.' && ++dots <= 1)) Add(new Letter()); } public override double Calc() { return double.Parse(ToString()); } public override string ToString() { return string.Join("", Nodes); } } public class Bracket : Node { // ::= '(' ')' protected override void ParseCore(Syntax syntax) { if (syntax.Current != '(') throw new Exception("BracketNodeは丸かっこから始まる必要があります"); Add(new Letter()); Add(new Expression()); if (syntax.Current != ')') throw new Exception("BracketNodeは丸かっこで終了する必要があります"); Add(new Letter()); } public override double Calc() { return Nodes[1].Calc(); } public override string ToString() { return string.Join("", Nodes); } } public class Factor : Node { bool isNegative = false; // ::= (|) protected override void ParseCore(Syntax syntax) { if (syntax.Current == '-') { if (syntax.Previous != '\0' && syntax.Previous != '(') throw new Exception("不正な位置にマイナス記号が存在します"); isNegative = true; Add(new Letter()); } if (char.IsDigit(syntax.Current)) Add(new Number()); else if (syntax.Current == '(') Add(new Bracket()); else throw new Exception("FactorNode で NumberNode もしくは BracketNode に該当しそうなものがありません"); } public override double Calc() { return (isNegative ? -1 : 1) * Nodes.Last().Calc(); } public override string ToString() { return string.Join("", Nodes); } } public class SquareRoot : Node { // ::= {'r'} protected override void ParseCore(Syntax syntax) { while (syntax.Current == 'r') Add(new Letter()); Add(new Factor()); } public override double Calc() { var x = Nodes.Last().Calc(); if (Nodes.Count == 1) return x; if (x < 0) throw new Exception("負数の平方根には対応してません"); for (var i = 0; i < Nodes.Count - 1; i++) x = Math.Sqrt(x); return x; } public override string ToString() { return string.Join("", Nodes); } } public class Factorial : Node { // ::= {'!'} protected override void ParseCore(Syntax syntax) { Add(new SquareRoot()); while (syntax.Current == '!') Add(new Letter()); } public override double Calc() { var d = Nodes.First().Calc(); var x = (int)Math.Round(d); if (Nodes.Count == 1) return d; if (Math.Abs(d - x) > double.Epsilon || x < 0) throw new Exception("階乗を計算できるのは0以上の整数のみです"); if (x == 0) return 1; for (var i = 0; i < Nodes.Count - 1; i++) { for (var y = x - 1; y >= 2; y--) x *= y; } return x; } public override string ToString() { return string.Join("", Nodes); } } public class Power : Node { // ::= {'^' } protected override void ParseCore(Syntax syntax) { Add(new Factorial()); while (syntax.Current == '^') { Add(new Letter()); Add(new Factorial()); } } public override double Calc() { var x = Nodes[0].Calc(); for (var i = 2; i < Nodes.Count; i += 2) { var y = Nodes[i].Calc(); x = Math.Pow(x, y); } return x; } public override string ToString() { return string.Join(" ", Nodes); } } public class MulDiv : Node { // ::= {('*'|'/') } protected override void ParseCore(Syntax syntax) { Add(new Power()); while (syntax.Current == '*' || syntax.Current == '/') { Add(new Letter()); Add(new Power()); } } public override double Calc() { var x = Nodes[0].Calc(); for (var i = 2; i < Nodes.Count; i += 2) { var op = Nodes[i - 1].ToString(); var y = Nodes[i].Calc(); if (op == "*") x *= y; if (op == "/") x /= y; } return x; } public override string ToString() { return string.Join(" ", Nodes); } } public class AddSub : Node { // ::= {('+'|'-') } protected override void ParseCore(Syntax syntax) { Add(new MulDiv()); while (syntax.Current == '+' || syntax.Current == '-') { Add(new Letter()); Add(new MulDiv()); } } public override double Calc() { var x = Nodes[0].Calc(); for (var i = 2; i < Nodes.Count; i += 2) { var op = Nodes[i - 1].ToString(); var y = Nodes[i].Calc(); if (op == "+") x += y; if (op == "-") x -= y; } return x; } public override string ToString() { return string.Join(" ", Nodes); } } public class Expression : Node { // ::= protected override void ParseCore(Syntax syntax) { Add(new AddSub()); } public override double Calc() { return Nodes.Last().Calc(); } public override string ToString() { return string.Join("", Nodes); } } }