From 112675074acc07ce33c8f49ef63d09c0e108d864 Mon Sep 17 00:00:00 2001 From: chaemon Date: Mon, 2 Sep 2019 00:27:08 +0900 Subject: [PATCH] Support C# (#153) * Support C# --- .travis.yml | 2 +- atcodertools/codegen/code_generators/cs.py | 175 ++++++++++++++++++ atcodertools/common/language.py | 14 +- .../tools/templates/default_template.cs | 63 +++++++ tests/check_autopep8 | 0 tests/resources/test_codegen/template.cs | 46 +++++ .../resources/test_codegen/template_jinja.cs | 56 ++++++ .../cs/echo_template.cs | 80 ++++++++ .../cs/expected_default_generated_code.cs | 72 +++++++ .../cs/expected_echo_generated_code.cs | 95 ++++++++++ .../test_float_case/cs/generated_code.txt | 61 ++++++ .../test_long_case/cs/generated_code.txt | 71 +++++++ .../test_mod_case/cs/generated_code.txt | 51 +++++ .../cs/generated_code.txt | 61 ++++++ .../test_yes_no_case/cs/generated_code.txt | 56 ++++++ tests/test_codegen.py | 15 +- 16 files changed, 913 insertions(+), 5 deletions(-) create mode 100644 atcodertools/codegen/code_generators/cs.py create mode 100644 atcodertools/tools/templates/default_template.cs create mode 100644 tests/check_autopep8 create mode 100644 tests/resources/test_codegen/template.cs create mode 100644 tests/resources/test_codegen/template_jinja.cs create mode 100644 tests/resources/test_codegen/test_default_code_generators_and_templates/cs/echo_template.cs create mode 100644 tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_default_generated_code.cs create mode 100644 tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_echo_generated_code.cs create mode 100644 tests/resources/test_codegen/test_float_case/cs/generated_code.txt create mode 100644 tests/resources/test_codegen/test_long_case/cs/generated_code.txt create mode 100644 tests/resources/test_codegen/test_mod_case/cs/generated_code.txt create mode 100644 tests/resources/test_codegen/test_two_dimensional_case/cs/generated_code.txt create mode 100644 tests/resources/test_codegen/test_yes_no_case/cs/generated_code.txt diff --git a/.travis.yml b/.travis.yml index e25302aa..0a993886 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,7 @@ before_install: - sudo apt-get update --allow-insecure-repositories - sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring - sudo apt-get update - - sudo apt-get install rustc g++-4.9 openjdk-8-jdk nim dmd-compiler + - sudo apt-get install rustc g++-4.9 openjdk-8-jdk nim dmd-compiler mono-complete - sudo ln -f -s /usr/bin/g++-4.9 /usr/bin/g++ install: diff --git a/atcodertools/codegen/code_generators/cs.py b/atcodertools/codegen/code_generators/cs.py new file mode 100644 index 00000000..93e170a9 --- /dev/null +++ b/atcodertools/codegen/code_generators/cs.py @@ -0,0 +1,175 @@ +from typing import Dict, Any, Optional + +from atcodertools.codegen.code_style_config import CodeStyleConfig +from atcodertools.codegen.models.code_gen_args import CodeGenArgs +from atcodertools.codegen.template_engine import render +from atcodertools.fmtprediction.models.format import Pattern, SingularPattern, ParallelPattern, TwoDimensionalPattern, \ + Format +from atcodertools.fmtprediction.models.type import Type +from atcodertools.fmtprediction.models.variable import Variable + + +def _loop_header(var: Variable, for_second_index: bool): + if for_second_index: + index = var.second_index + loop_var = "j" + else: + index = var.first_index + loop_var = "i" + + return "for(int {loop_var} = 0;{loop_var} < {len};{loop_var}++)".format( + loop_var=loop_var, + len=index.get_length() + ) + "{" + + +class CSharpCodeGenerator: + + def __init__(self, + format_: Optional[Format[Variable]], + config: CodeStyleConfig): + self._format = format_ + self._config = config + + def generate_parameters(self) -> Dict[str, Any]: + if self._format is None: + return dict(prediction_success=False) + + return dict(formal_arguments=self._formal_arguments(), + actual_arguments=self._actual_arguments(), + input_part=self._input_part(), + prediction_success=True) + + def _input_part(self): + lines = [] + for pattern in self._format.sequence: + lines += self._render_pattern(pattern) + return "\n{indent}".format(indent=self._indent(2)).join(lines) + + def _convert_type(self, type_: Type) -> str: + if type_ == Type.float: + return "double" + elif type_ == Type.int: + return "long" + elif type_ == Type.str: + return "string" + else: + raise NotImplementedError + + def _get_declaration_type(self, var: Variable): + ctype = self._convert_type(var.type) + if var.dim_num() == 0: + return ctype + else: + return "{}[{}]".format(ctype, "," * (var.dim_num() - 1)) + + def _actual_arguments(self) -> str: + """ + :return the string form of actual arguments e.g. "N, K, a" + """ + return ", ".join([ + v.name if v.dim_num() == 0 else '{}'.format(v.name) + for v in self._format.all_vars()]) + + def _formal_arguments(self): + """ + :return the string form of formal arguments e.g. "int N, int K, std::vector a" + """ + return ", ".join([ + "{decl_type} {name}".format( + decl_type=self._get_declaration_type(v), + name=v.name) + for v in self._format.all_vars() + ]) + + def _generate_declaration(self, var: Variable): + """ + :return: Create declaration part E.g. array[1..n] -> std::vector array = std::vector(n-1+1); + """ + if var.dim_num() == 0: + dims = [] + elif var.dim_num() == 1: + dims = [var.first_index.get_length()] + elif var.dim_num() == 2: + dims = [var.first_index.get_length(), + var.second_index.get_length()] + else: + raise NotImplementedError + ret = "{decl_type} {name}".format( + decl_type=self._get_declaration_type(var), name=var.name) + if len(dims) > 0: + t = self._convert_type(var.type) + d = [] + for dim in dims: + d.append(str(dim)) + ret += " = new {type}[{dims}]".format(type=t, dims=",".join(d)) + ret += ";" + return ret + + def _input_code_for_var(self, var: Variable) -> str: + name = self._get_var_name(var) + if var.type == Type.float: + return '{name} = cin.ReadDouble;'.format(name=name) + elif var.type == Type.int: + return '{name} = cin.ReadLong;'.format(name=name) + elif var.type == Type.str: + return '{name} = cin.Read;'.format(name=name) + else: + raise NotImplementedError + + @staticmethod + def _get_var_name(var: Variable): + name = var.name + if var.dim_num() >= 1: + name += "[i" + if var.dim_num() >= 2: + name += ",j" + name += "]" + return name + + def _render_pattern(self, pattern: Pattern): + lines = [] + for var in pattern.all_vars(): + lines.append(self._generate_declaration(var)) + + representative_var = pattern.all_vars()[0] + if isinstance(pattern, SingularPattern): + lines.append(self._input_code_for_var(representative_var)) + elif isinstance(pattern, ParallelPattern): + lines.append(_loop_header(representative_var, False)) + for var in pattern.all_vars(): + lines.append("{indent}{line}".format(indent=self._indent(1), + line=self._input_code_for_var(var))) + lines.append("}") + elif isinstance(pattern, TwoDimensionalPattern): + lines.append(_loop_header(representative_var, False)) + lines.append( + "{indent}{line}".format(indent=self._indent(1), line=_loop_header(representative_var, True))) + for var in pattern.all_vars(): + lines.append("{indent}{line}".format(indent=self._indent(2), + line=self._input_code_for_var(var))) + lines.append("{indent}}}".format(indent=self._indent(1))) + lines.append("}") + else: + raise NotImplementedError + + return lines + + def _indent(self, depth): + return self._config.indent(depth) + + +class NoPredictionResultGiven(Exception): + pass + + +def main(args: CodeGenArgs) -> str: + code_parameters = CSharpCodeGenerator( + args.format, args.config).generate_parameters() + return render( + args.template, + mod=args.constants.mod, + yes_str=args.constants.yes_str, + no_str=args.constants.no_str, + **code_parameters + ) diff --git a/atcodertools/common/language.py b/atcodertools/common/language.py index 13408648..9d05e5ee 100644 --- a/atcodertools/common/language.py +++ b/atcodertools/common/language.py @@ -1,7 +1,7 @@ import re from typing import Pattern, Callable -from atcodertools.codegen.code_generators import cpp, java, rust, python, nim, d +from atcodertools.codegen.code_generators import cpp, java, rust, python, nim, d, cs from atcodertools.codegen.models.code_gen_args import CodeGenArgs from atcodertools.tools.templates import get_default_template_path @@ -103,5 +103,15 @@ def from_name(cls, name: str): default_code_style=CodeStyle(indent_width=2) ) -ALL_LANGUAGES = [CPP, JAVA, RUST, PYTHON, NIM, DLANG] +CSHARP = Language( + name="cs", + display_name="C#", + extension="cs", + submission_lang_pattern=re.compile(".*C# \\(Mono.*"), + default_code_generator=cs.main, + default_template_path=get_default_template_path('cs'), +) + + +ALL_LANGUAGES = [CPP, JAVA, RUST, PYTHON, NIM, DLANG, CSHARP] ALL_LANGUAGE_NAMES = [lang.display_name for lang in ALL_LANGUAGES] diff --git a/atcodertools/tools/templates/default_template.cs b/atcodertools/tools/templates/default_template.cs new file mode 100644 index 00000000..bd199cd7 --- /dev/null +++ b/atcodertools/tools/templates/default_template.cs @@ -0,0 +1,63 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; +using System.Diagnostics; + +public class Program{ + {% if mod %} + const long MOD = {{ mod }}; + {% endif %} + {% if yes_str %} + const string YES = "{{ yes_str }}"; + {% endif %} + {% if no_str %} + const string NO = "{{ no_str }}"; + {% endif %} + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + {% if prediction_success %} + {{ input_part }} + new Program().Solve({{ actual_arguments }}); + {% else %} + // Failed to predict input format + {% endif %} + } + + {% if prediction_success %} + public void Solve({{ formal_arguments }}){ + + } + {% endif %} +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/check_autopep8 b/tests/check_autopep8 new file mode 100644 index 00000000..e69de29b diff --git a/tests/resources/test_codegen/template.cs b/tests/resources/test_codegen/template.cs new file mode 100644 index 00000000..91004aa0 --- /dev/null +++ b/tests/resources/test_codegen/template.cs @@ -0,0 +1,46 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + ${input_part} + new Program().Solve(${actual_arguments}); + } + + public void Solve(${formal_arguments}){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/template_jinja.cs b/tests/resources/test_codegen/template_jinja.cs new file mode 100644 index 00000000..eca11f40 --- /dev/null +++ b/tests/resources/test_codegen/template_jinja.cs @@ -0,0 +1,56 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + {% if mod %} + const long MOD = {{ mod }}; + {% endif %} + {% if yes_str %} + const string YES = "{{ yes_str }}"; + {% endif %} + {% if no_str %} + const string NO = "{{ no_str }}"; + {% endif %} + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + {{ input_part }} + new Program().Solve({{ actual_arguments }}); + } + + public void Solve({{ formal_arguments }}){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/echo_template.cs b/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/echo_template.cs new file mode 100644 index 00000000..3752bd4d --- /dev/null +++ b/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/echo_template.cs @@ -0,0 +1,80 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; +using System.Diagnostics; + +public class Program{ + {% if mod %} + const long MOD = {{ mod }}; + {% endif %} + {% if yes_str %} + const string YES = "{{ yes_str }}"; + {% endif %} + {% if no_str %} + const string NO = "{{ no_str }}"; + {% endif %} + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + {{ input_part }} + new Program().Solve({{ actual_arguments }}); + } + + public void Solve({{ formal_arguments }}){ + WriteLine($"{N} {M}"); + Debug.Assert(H.GetLength(0) == N - 1); + for (int i = 0;i < N - 1;i++) { + Debug.Assert(H.GetLength(1) == M - 2); + for (int j = 0;j < M - 2;j++) { + Write((j > 0 ? " " : "") + $"{H[i,j]}"); + } + WriteLine(); + } + Debug.Assert(A.Length == N - 1); + Debug.Assert(B.Length == N - 1); + for(int i = 0;i < N - 1;i++){ + WriteLine($"{A[i]} {B[i]}"); + } + WriteLine(Q); + Debug.Assert(X.Length == M + Q); + for(int i = 0;i < M + Q;i++){ + WriteLine(X[i]); + } + + WriteLine(YES); + WriteLine(NO); + WriteLine(MOD); + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_default_generated_code.cs b/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_default_generated_code.cs new file mode 100644 index 00000000..750d8e28 --- /dev/null +++ b/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_default_generated_code.cs @@ -0,0 +1,72 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; +using System.Diagnostics; + +public class Program{ + const long MOD = 123; + const string YES = "yes"; + const string NO = "NO"; + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long N; + N = cin.ReadLong; + long M; + M = cin.ReadLong; + string[,] H = new string[N-2+1,M-1-2+1]; + for(int i = 0;i < N-2+1;i++){ + for(int j = 0;j < M-1-2+1;j++){ + H[i,j] = cin.Read; + } + } + long[] A = new long[N-2+1]; + double[] B = new double[N-2+1]; + for(int i = 0;i < N-2+1;i++){ + A[i] = cin.ReadLong; + B[i] = cin.ReadDouble; + } + long Q; + Q = cin.ReadLong; + long[] X = new long[M+Q]; + for(int i = 0;i < M+Q;i++){ + X[i] = cin.ReadLong; + } + new Program().Solve(N, M, H, A, B, Q, X); + } + + public void Solve(long N, long M, string[,] H, long[] A, double[] B, long Q, long[] X){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_echo_generated_code.cs b/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_echo_generated_code.cs new file mode 100644 index 00000000..ae28b81e --- /dev/null +++ b/tests/resources/test_codegen/test_default_code_generators_and_templates/cs/expected_echo_generated_code.cs @@ -0,0 +1,95 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; +using System.Diagnostics; + +public class Program{ + const long MOD = 123; + const string YES = "yes"; + const string NO = "NO"; + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long N; + N = cin.ReadLong; + long M; + M = cin.ReadLong; + string[,] H = new string[N-2+1,M-1-2+1]; + for(int i = 0;i < N-2+1;i++){ + for(int j = 0;j < M-1-2+1;j++){ + H[i,j] = cin.Read; + } + } + long[] A = new long[N-2+1]; + double[] B = new double[N-2+1]; + for(int i = 0;i < N-2+1;i++){ + A[i] = cin.ReadLong; + B[i] = cin.ReadDouble; + } + long Q; + Q = cin.ReadLong; + long[] X = new long[M+Q]; + for(int i = 0;i < M+Q;i++){ + X[i] = cin.ReadLong; + } + new Program().Solve(N, M, H, A, B, Q, X); + } + + public void Solve(long N, long M, string[,] H, long[] A, double[] B, long Q, long[] X){ + WriteLine($"{N} {M}"); + Debug.Assert(H.GetLength(0) == N - 1); + for (int i = 0;i < N - 1;i++) { + Debug.Assert(H.GetLength(1) == M - 2); + for (int j = 0;j < M - 2;j++) { + Write((j > 0 ? " " : "") + $"{H[i,j]}"); + } + WriteLine(); + } + Debug.Assert(A.Length == N - 1); + Debug.Assert(B.Length == N - 1); + for(int i = 0;i < N - 1;i++){ + WriteLine($"{A[i]} {B[i]}"); + } + WriteLine(Q); + Debug.Assert(X.Length == M + Q); + for(int i = 0;i < M + Q;i++){ + WriteLine(X[i]); + } + + WriteLine(YES); + WriteLine(NO); + WriteLine(MOD); + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_float_case/cs/generated_code.txt b/tests/resources/test_codegen/test_float_case/cs/generated_code.txt new file mode 100644 index 00000000..c8565745 --- /dev/null +++ b/tests/resources/test_codegen/test_float_case/cs/generated_code.txt @@ -0,0 +1,61 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long L; + L = cin.ReadLong; + long N; + N = cin.ReadLong; + long M; + M = cin.ReadLong; + double[] K = new double[L]; + for(int i = 0;i < L;i++){ + K[i] = cin.ReadDouble; + } + long[] A = new long[N]; + double[] S = new double[N]; + for(int i = 0;i < N;i++){ + A[i] = cin.ReadLong; + S[i] = cin.ReadDouble; + } + new Program().Solve(L, N, M, K, A, S); + } + + public void Solve(long L, long N, long M, double[] K, long[] A, double[] S){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_long_case/cs/generated_code.txt b/tests/resources/test_codegen/test_long_case/cs/generated_code.txt new file mode 100644 index 00000000..a700243b --- /dev/null +++ b/tests/resources/test_codegen/test_long_case/cs/generated_code.txt @@ -0,0 +1,71 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long H; + H = cin.ReadLong; + long W; + W = cin.ReadLong; + long K; + K = cin.ReadLong; + long sr; + sr = cin.ReadLong; + long sc; + sc = cin.ReadLong; + string[] s = new string[H]; + for(int i = 0;i < H;i++){ + s[i] = cin.Read; + } + long N; + N = cin.ReadLong; + long[] fr = new long[N]; + long[] fc = new long[N]; + long[] F = new long[N]; + long[] D = new long[N]; + for(int i = 0;i < N;i++){ + fr[i] = cin.ReadLong; + fc[i] = cin.ReadLong; + F[i] = cin.ReadLong; + D[i] = cin.ReadLong; + } + new Program().Solve(H, W, K, sr, sc, s, N, fr, fc, F, D); + } + + public void Solve(long H, long W, long K, long sr, long sc, string[] s, long N, long[] fr, long[] fc, long[] F, long[] D){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_mod_case/cs/generated_code.txt b/tests/resources/test_codegen/test_mod_case/cs/generated_code.txt new file mode 100644 index 00000000..c7837a25 --- /dev/null +++ b/tests/resources/test_codegen/test_mod_case/cs/generated_code.txt @@ -0,0 +1,51 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + const long MOD = 998244353; + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long A; + A = cin.ReadLong; + long B; + B = cin.ReadLong; + new Program().Solve(A, B); + } + + public void Solve(long A, long B){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_two_dimensional_case/cs/generated_code.txt b/tests/resources/test_codegen/test_two_dimensional_case/cs/generated_code.txt new file mode 100644 index 00000000..9dfba539 --- /dev/null +++ b/tests/resources/test_codegen/test_two_dimensional_case/cs/generated_code.txt @@ -0,0 +1,61 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long H; + H = cin.ReadLong; + long W; + W = cin.ReadLong; + long[,] c = new long[9-0+1,9-0+1]; + for(int i = 0;i < 9-0+1;i++){ + for(int j = 0;j < 9-0+1;j++){ + c[i,j] = cin.ReadLong; + } + } + long[,] A = new long[H,W]; + for(int i = 0;i < H;i++){ + for(int j = 0;j < W;j++){ + A[i,j] = cin.ReadLong; + } + } + new Program().Solve(H, W, c, A); + } + + public void Solve(long H, long W, long[,] c, long[,] A){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/resources/test_codegen/test_yes_no_case/cs/generated_code.txt b/tests/resources/test_codegen/test_yes_no_case/cs/generated_code.txt new file mode 100644 index 00000000..704a5453 --- /dev/null +++ b/tests/resources/test_codegen/test_yes_no_case/cs/generated_code.txt @@ -0,0 +1,56 @@ +using System; +using System.Text; +using System.Linq; +using System.Collections; +using System.Collections.Generic; +using static System.Console; +using static System.Math; + +public class Program{ + const string YES = "YES"; + const string NO = "NO"; + + public static void Main(string[] args){ + ConsoleInput cin = new ConsoleInput(Console.In, ' '); + long N; + N = cin.ReadLong; + long M; + M = cin.ReadLong; + long A; + A = cin.ReadLong; + long B; + B = cin.ReadLong; + new Program().Solve(N, M, A, B); + } + + public void Solve(long N, long M, long A, long B){ + + } +} + +public class ConsoleInput{ + private readonly System.IO.TextReader _stream; + private char _separator = ' '; + private Queue inputStream; + public ConsoleInput(System.IO.TextReader stream, char separator = ' '){ + this._separator = separator; + this._stream = stream; + inputStream = new Queue(); + } + public string Read{ + get{ + if (inputStream.Count != 0) return inputStream.Dequeue(); + string[] tmp = _stream.ReadLine().Split(_separator); + for (int i = 0; i < tmp.Length; ++i) + inputStream.Enqueue(tmp[i]); + return inputStream.Dequeue(); + } + } + public string ReadLine { get { return _stream.ReadLine(); } } + public int ReadInt { get { return int.Parse(Read); } } + public long ReadLong { get { return long.Parse(Read); } } + public double ReadDouble { get { return double.Parse(Read); } } + public string[] ReadStrArray(long N) { var ret = new string[N]; for (long i = 0; i < N; ++i) ret[i] = Read; return ret;} + public int[] ReadIntArray(long N) { var ret = new int[N]; for (long i = 0; i < N; ++i) ret[i] = ReadInt; return ret;} + public long[] ReadLongArray(long N) { var ret = new long[N]; for (long i = 0; i < N; ++i) ret[i] = ReadLong; return ret;} +} diff --git a/tests/test_codegen.py b/tests/test_codegen.py index f3cb0e98..aa831b83 100644 --- a/tests/test_codegen.py +++ b/tests/test_codegen.py @@ -7,14 +7,14 @@ from atcodertools.client.models.problem_content import ProblemContent from atcodertools.client.models.sample import Sample -from atcodertools.common.language import ALL_LANGUAGES, Language, CPP, JAVA, RUST, PYTHON, NIM, DLANG +from atcodertools.common.language import ALL_LANGUAGES, Language, CPP, JAVA, RUST, PYTHON, NIM, DLANG, CSHARP from atcodertools.executils.run_command import run_command from atcodertools.executils.run_program import run_program from atcodertools.fileutils.create_contest_file import create_code from atcodertools.fileutils.load_text_file import load_text_file from atcodertools.fmtprediction.predict_format import predict_format -from atcodertools.codegen.code_generators import cpp, java, rust, python, nim, d +from atcodertools.codegen.code_generators import cpp, java, rust, python, nim, d, cs from atcodertools.codegen.code_style_config import CodeStyleConfig from atcodertools.codegen.models.code_gen_args import CodeGenArgs from atcodertools.codegen.template_engine import render @@ -74,6 +74,10 @@ def setUp(self): DLANG: { "old": "template.d", "jinja": "template_jinja.d", + }, + CSHARP: { + "old": "template.cs", + "jinja": "template_jinja.cs", } } self.lang_to_code_generator_func = { @@ -83,6 +87,7 @@ def setUp(self): PYTHON: python.main, NIM: nim.main, DLANG: d.main, + CSHARP: cs.main, } self.maxDiff = None @@ -182,6 +187,8 @@ def _compile_command(self, lang: Language, code_file: str): return "nim c {}".format(code_file) elif lang == DLANG: return "dmd {} -of=main".format(code_file) + elif lang == CSHARP: + return "mcs {}".format(code_file) else: raise NotImplementedError() @@ -198,6 +205,8 @@ def _exec_file_and_args(self, lang: Language) -> Tuple[str, List[str]]: return "./main", [] elif lang == DLANG: return "./main", [] + elif lang == CSHARP: + return "mono", ["main.exe"] else: raise NotImplementedError() @@ -214,6 +223,8 @@ def _clean_up(self, lang: Language): os.remove(os.path.join(self.temp_dir, "main")) elif lang == DLANG: os.remove(os.path.join(self.temp_dir, "main")) + elif lang == CSHARP: + os.remove(os.path.join(self.temp_dir, "main.exe")) else: raise NotImplementedError()