結果
問題 | No.708 (+ー)の式 |
ユーザー | AreTrash |
提出日時 | 2019-04-28 02:41:44 |
言語 | C#(csc) (csc 3.9.0) |
結果 |
AC
|
実行時間 | 64 ms / 2,000 ms |
コード長 | 8,749 bytes |
コンパイル時間 | 4,882 ms |
コンパイル使用メモリ | 109,080 KB |
実行使用メモリ | 17,692 KB |
最終ジャッジ日時 | 2023-08-20 12:21:55 |
合計ジャッジ時間 | 6,245 ms |
ジャッジサーバーID (参考情報) |
judge12 / judge14 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 62 ms
17,432 KB |
testcase_01 | AC | 61 ms
17,484 KB |
testcase_02 | AC | 60 ms
17,444 KB |
testcase_03 | AC | 61 ms
17,692 KB |
testcase_04 | AC | 58 ms
15,608 KB |
testcase_05 | AC | 58 ms
15,548 KB |
testcase_06 | AC | 62 ms
17,440 KB |
testcase_07 | AC | 63 ms
17,596 KB |
testcase_08 | AC | 64 ms
17,448 KB |
testcase_09 | AC | 63 ms
17,588 KB |
testcase_10 | AC | 63 ms
17,480 KB |
testcase_11 | AC | 62 ms
17,572 KB |
testcase_12 | AC | 62 ms
17,576 KB |
testcase_13 | AC | 60 ms
15,684 KB |
testcase_14 | AC | 58 ms
15,608 KB |
コンパイルメッセージ
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 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 { //<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); } } }