結果
問題 | No.708 (+ー)の式 |
ユーザー |
![]() |
提出日時 | 2019-04-28 02:41:44 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
AC
|
実行時間 | 32 ms / 2,000 ms |
コード長 | 8,749 bytes |
コンパイル時間 | 1,030 ms |
コンパイル使用メモリ | 109,568 KB |
実行使用メモリ | 19,712 KB |
最終ジャッジ日時 | 2024-11-30 14:03:42 |
合計ジャッジ時間 | 2,308 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 12 |
コンパイルメッセージ
Microsoft (R) Visual C# Compiler version 3.9.0-6.21124.20 (db94f4cc) Copyright (C) Microsoft Corporation. All rights reserved.
ソースコード
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<Node> nodes = new List<Node>();protected IReadOnlyList<Node> Nodes => nodes;protected void Add(Node node){node.Parse(syntax);nodes.Add(node);}protected abstract void ParseCore(Syntax syntax);// ReSharper disable once ParameterHidesMemberpublic 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{//<number> ::= ('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{//<bracket> ::= '(' <expression> ')'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;//<factor> ::= (<number>|<bracket>)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{//<root> ::= {'r'} <factor>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{//<factorial> ::= <square_root> {'!'}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{//<power> ::= <factorial> {'^' <factorial>}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{//<mul_div> ::= <power> {('*'|'/') <power>}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{//<add_sub> ::= <mul_div> {('+'|'-') <mul_div>}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{//<expression> ::= <add_sub>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);}}}