Giter Club home page Giter Club logo

template-generator's Introduction

online-judge-tools/oj

test PyPI Downloads PyPI Join the chat at https://gitter.im/online-judge-tools/community

日本語版の README.md

oj is a command to help solving problems on various online judges. This command automates downloading sample cases, generating additional test cases, testing for your code, and submitting it.

Screencast

screencast

Features

  • Download sample cases
  • Download system test cases
  • Login
  • Submit your code
  • Test your code
  • Test your code for reactive problems
  • Generate input files from generators
  • Generate output files from input and reference implementation

For the detailed documentation, read docs/getting-started.md.

Many online judges (Codeforces, AtCoder, HackerRank, etc.) are supported. For the full list, see the table of online-judge-tools/api-client.

How to install

The package is https://pypi.python.org/pypi/online-judge-tools PyPI.

$ pip3 install online-judge-tools

For detailed instructions, read docs/INSTALL.md.

How to use

$ oj download [--system] URL
$ oj login URL
$ oj submit [URL] FILE
$ oj test [-c COMMAND] [TEST...]
$ oj test-reactive [-c COMMAND] JUDGE_COMMAND
$ oj generate-input GENERATOR_COMMAND
$ oj generate-output [-c COMMAND] [TEST...]

For details, see $ oj --help.

Example

$ oj download http://agc001.contest.atcoder.jp/tasks/agc001_a
[INFO] online-judge-tools 11.2.0 (+ online-judge-api-client 10.8.0)
[INFO] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
[NETWORK] GET: https://atcoder.jp/contests/agc001/tasks/agc001_a
[NETWORK] 200 OK

[INFO] sample 0
[INFO] input: sample-1
2
1 3 1 2

[SUCCESS] saved to: test/sample-1.in
[INFO] output: sample-1
3

[SUCCESS] saved to: test/sample-1.out

[INFO] sample 1
[INFO] input: sample-2
5
100 1 2 3 14 15 58 58 58 29

[SUCCESS] saved to: test/sample-2.in
[INFO] output: sample-2
135

[SUCCESS] saved to: test/sample-2.out

$ cat <<EOF > main.py
#!/usr/bin/env python3
n = int(input())
a = list(map(int, input().split()))
ans = max(a)
print(ans)
EOF

$ oj t -c "python3 main.py"
[INFO] online-judge-tools 11.2.0 (+ online-judge-api-client 10.8.0)
[INFO] 2 cases found

[INFO] sample-1
[INFO] time: 0.043601 sec
[SUCCESS] AC

[INFO] sample-2
[INFO] time: 0.043763 sec
[FAILURE] WA
input:
5
100 1 2 3 14 15 58 58 58 29

output:
3

expected:
135


[INFO] slowest: 0.043763 sec  (for sample-2)
[INFO] max memory: 10.064000 MB  (for sample-2)
[FAILURE] test failed: 1 AC / 2 cases

FAQ

  • Can I use Python (or Rust, D, Java, F#, Haskell, etc.) instead of C++?
    • Yes. Please use --command (-c) option if needed. For example, for Python, you can run $ oj t -c "python3 main.py".
  • I usually make one directory per one contest (or, site). Can I keep using this style?
    • Yes, you can use the --directory (-d) option or $ rm -rf test/. However, we don't recommend this style, because you should make additional test cases by yourself and run stress tests to maximize your rating.
  • Can I download all sample cases of all problems at once?
  • Can I automatically compile my source code before testing?
    • Yes, use your shell. Run $ g++ main.cpp && oj t.
  • Can I automatically submit code after it passes tests?
    • Yes, use your shell. Run $ oj t && oj s main.cpp. By the way, you need to take care of problems whose sample cases are not so strong.
  • Can I remove the delays and the [y/N] confirmation before submitting code?
    • Yes, put --wait=0 option and --yes option to oj s subcommand. Of course, we don't recommend this. These options exist for failsafe. For example, please consider a situation where if you save 3 seconds, you will move up 3 places on the standings. In such a case, if you get a penalty of 5 minutes, then you will move down at least 300 places on the standings.
  • Are my passwords stored?
  • Does the config file exist?
    • No. You can use your .bashrc (or similar files) instead. It's a config file of your shell. Read man bash and write shell aliases or shell functions. For example, if you want to use Python code for tests by default, write alias oj-test-python='oj t -c "python3 main.py"' to .bashrc and use $ oj-test-python.

For other questions, use Gitter Join the chat at https://gitter.im/online-judge-tools/community or other SNSs.

Resources

Related Tools

conflicted:

not conflicted:

projects collaborating with kmyk/online-judge-tools:

Maintainers

License

MIT License

template-generator's People

Contributors

beet-aizu avatar isym444 avatar kmyk avatar koba-e964 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

template-generator's Issues

Replace simple_patterns.py with more theoretical parser

サンプルからのフォーマット推測の v4.3.1 現在でのアルゴリズムは「頻出のパターンを手動で列挙しておき、それらの中から与えられたサンプルとマッチするフォーマットを検索する」という ad-hoc なものになっています (実装: simple_patterns.py)。
これを「フォーマットについての「大きさ」の概念を定義し、与えられたサンプルすべてにマッチする最小のフォーマットを求める」という、理論的にきれいなアルゴリズムに改善したい。文脈依存文法の言語に含まれる語のいくつかを見て文法を復元するみたいな問題になっていてるはずで、開発のわりには競技としておもしろいはず。

failure to detect MOD on Topcoder SRM AppleTrees

Description

On the problem https://community.topcoder.com/stat?c=problem_statement&pm=11213, it says

Return the number of ways to plant all apple trees modulo 1,000,000,007.

but oj-template fails to detect the MOD.

Error log

$ oj-template 'https://community.topcoder.com/stat?c=problem_statement&pm=11213'
#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;


int64_t solve(int n, const vector<int64_t> & a) {
    // TODO: edit here
}

// generated by online-judge-template-generator v4.1.1 (https://github.com/kmyk/online-judge-template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    // failed to analyze input format
    // TODO: edit here
    int n;
    cin >> n;
    vector<int64_t> a(n);
    REP (i, n) {
        cin >> a[i];
    }
    auto ans = solve(n, a);
    cout << ans << endl;
    return 0;
}

web frontend

Command-line tools are difficult for most competitive programmers, so making a web frontend may be good as an friendly entrance for this tool.

The analyzer for Topcoder fails when `long` type is used

Description

https://community.topcoder.com/stat?c=problem_statement&pm=10727

Error log

$ oj-template -t topcoder.cpp 'https://community.topcoder.com/stat?c=problem_statement&pm=10727'    
INFO:onlinejudge._implementation.logging:[x] problem recognized: TopcoderProblem.from_url('https://community.topcoder.com/stat?c=problem_statement&pm=10727'): https://community.topcoder.com/stat?c=problem_statement&pm=10727
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: TopcoderProblem.from_url('https://community.topcoder.com/stat?c=problem_statement&pm=10727'): https://community.topcoder.com/stat?c=problem_statement&pm=10727
INFO:onlinejudge._implementation.logging:[x] GET: https://community.topcoder.com/stat?c=problem_statement&pm=10727
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/user/.local/share/online-judge-tools/cookie.jar
ERROR:onlinejudge_template.analyzer.combined:input analyzer failed: 
ERROR:onlinejudge_template.analyzer.combined:output analyzer failed: 
Traceback (most recent call last):
  File "/home/user/.local/bin/oj-template", line 8, in <module>
    sys.exit(main())
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/main.py", line 43, in main
    analyzed = onlinejudge_template.analyzer.combined.run(resources)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/combined.py", line 52, in run
    topcoder_class_definition = onlinejudge_template.analyzer.topcoder.parse_topcoder_class_definition(resources.html, url=resources.url)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/topcoder.py", line 96, in parse_topcoder_class_definition
    return_type, formal_arguments = _parse_topcoder_method_signature(definition['Method signature'])
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/topcoder.py", line 81, in _parse_topcoder_method_signature
    formal_arguments.append((type_table[type_], name))
KeyError: 'long[]'

典型ランダムケースの生成

「ほとんど同じ文字な文字列を生成する機能」「高度合成数や素冪を生成する機能」「ほとんどウニなグラフを生成する機能」などです。

やることもその価値も明らかなはず。
そういう機能をライブラリとして使えるように用意したい。実装の枠組みを整えれば、「列が与えられる問題のテストケースであって撃墜力が高いものをたくさん考えてください」とか「頂点数 N の木 (頂点にラベル付き) は全体で N^{N-1} 個あるが、この中から一様ランダムにひとつ作れ」とかをやることになるので、普通に競プロになる。手伝ってくれる人もわりといそう。

問題はどこにどう実装するか。言語は C++ でよいだろう。場所について、以下のような選択肢があるはず。

  • Library-Checker に足させてもらう
  • このリポジトリ内に持つ
    • 作りかけのものがある onlinejudge_random/__init__.py
    • 短期的にはもっとも楽だが、役割が違うものを混ぜることになるため、これを選ぶべきではない
  • 外部にライブラリを作る
    • 私がやるなら online-judge-tools/random-cases みたいなのを作る
    • 誰かやる気のある人にまったく独自でやってもらってもよさそう

関連:

  • 作問用機能 #35
  • generator.py の C++ 版を書く #5
  • cc @monkukui

crash on ARC 066 E

$ pip3 show online-judge-template-generator | grep Version      
Version: 4.1.1

$ oj-template https://atcoder.jp/contests/arc066/tasks/arc066_c
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: AtCoderProblem.from_url('https://atcoder.jp/contests/arc066/tasks/arc066_c'): https://atcoder.jp/contests/arc066/tasks/arc066_c
INFO:onlinejudge._implementation.logging:[x] GET: https://atcoder.jp/contests/arc066/tasks/arc066_c
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/user/.local/share/online-judge-tools/cookie.jar
ERROR:onlinejudge_template.analyzer.combined:output analyzer failed: 
Traceback (most recent call last):
  File "/home/user/.local/bin/oj-template", line 8, in <module>
    sys.exit(main())
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/main.py", line 36, in main
    analyzed = onlinejudge_template.analyzer.combined.run(resources)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/combined.py", line 47, in run
    input_format = onlinejudge_template.analyzer.parser.run(resources.input_format_string)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/parser.py", line 451, in run
    parsed = parser.parse(lexer=lexer)
  File "/usr/lib/python3/dist-packages/ply/yacc.py", line 333, in parse
    return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
  File "/usr/lib/python3/dist-packages/ply/yacc.py", line 1120, in parseopt_notrack
    p.callable(pslice)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/parser.py", line 212, in p_items
    p[0] = SequenceParserNode(items=[dots] + p[2].items, **loc(p))
AttributeError: 'str' object has no attribute 'items'

@kimiyuki_u
Online Judge Template Generatorにいつもお世話になってます バグ(?)報告ですhttps://t.co/GVLkwTRaNx
この問題でtemplate生成に失敗するようです

— こるとん (@kyort0n) May 27, 2020

About the "template" part (i.e. including headers, defining macros) of the default template

Description

現在のバージョン v4.7.1 の default の main.cpp はたいてい次を出力する。

#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;

この #include 部分は platform.system()$CXX で制御されていて、環境によっては bits/stdc++.h は回避される。

if platform.system() == "Linux" and "clang" not in os.environ.get("CXX", "g++"):
include = "#include <bits/stdc++.h>"
else:
include = "\n".join([
"#include <iostream>",
"#include <string>",
"#include <vector>",
])

全員が満足するものは不可能なので「不満なら申し訳ないが自分でカスタマイズしてね」と言うしかないが、それでもできるだけ多くのユーザにとって使いやすいものにしておきたい。いまのところ現状の main.cpp は妥当であると (@kmyk は) 判断しているが、そうでなさそうなら代替案を提案してください。

Possible implementations and the analysis

#include について:

  • このまま
  • 常に #include <bits/stdc++h> を使う
    • これは環境によって壊れるからだめ
  • 常に #include <bits/stdc++h> を避ける (include は必要最小限に留める)
    • これは不便なだけだと思う
  • 常に #include <bits/stdc++h> を避ける (よく使う標準ヘッダをいくつか選んで include しておく)
    • 「よく使う」の定義が人によって変わるので「全員にとって不便でない」を目指すと「すべて include する」になるはず
  • 常に #include <bits/stdc++h> を避ける (すべての標準ヘッダを include しておく)
    • 長くなってつらい
    • C++17 で新規に追加された標準ヘッダなどをどうすればよいのか

#define されている REP macro などについて:

  • 使う (このまま)
    -「macro には MACRO_CASE を使う」という通常の作法と「できるだけ混乱のなさそうな名前を使う」を満たしてはいるはず
  • 使う (名前や定義を修正する)
    • 現状の名前がどれくらい標準的なのかの調査はしてない。より標準的かつ適切な名前があるなら乗り換えたい
    • repREP が両方 define されている」「FORREP が両方 define されている」などのとき、たいていどちらかは #define X(i, n) for (int i = 0; i < n; ++ i) でもう一方は #define Y(i, m, n) for (int i = m; i < n; ++ i) だと思うが、初見で自信を持って見分けられるものであってほしい
  • 消す
    • 不便

using namespace std; について:

  • 使う
    • 特にデメリットないので足しておきたい
    • left とか y0 みたいな名前のグローバル変数を定義できなかったりすると思うけど、そもそもグローバル変数は使うべきでない。不適切なことをすると不適切な結果になるのは当然であり、これは気にしなくてよい
  • 消す
    • 不便なだけだと思う

その他について:

  • このまま
  • なにか追加する
    • 例: typedef long long ll;
    • 例: template <class T, class U> using P = pair<T, U>;

oj-template fails with "Cant locate template for uri 'template.cpp'"

$ pip3 show online-judge-template-generator | grep Version
Version: 4.0.1

$ oj-template https://codeforces.com/contest/1333/problem/D
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: CodeforcesProblem.from_url('https://codeforces.com/contest/1333/problem/D'): https://codeforces.com/contest/1333/problem/D
INFO:onlinejudge._implementation.logging:[x] GET: https://codeforces.com/contest/1333/problem/D
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/user/.local/share/online-judge-tools/cookie.jar
ERROR:onlinejudge_template.analyzer.combined:input analyzer failed: 
ERROR:onlinejudge_template.analyzer.combined:output analyzer failed: 
Traceback (most recent call last):
  File "/home/user/.local/lib/python3.6/site-packages/mako/lookup.py", line 249, in get_template
    return self._check(uri, self._collection[uri])
KeyError: 'template.cpp'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user/.local/bin/oj-template", line 8, in <module>
    sys.exit(main())
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/main.py", line 39, in main
    code = onlinejudge_template.generator.run(analyzed, template_file=parsed.template)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/generator/__init__.py", line 25, in run
    template = lookup.get_template(template_file)
  File "/home/user/.local/lib/python3.6/site-packages/mako/lookup.py", line 263, in get_template
    "Cant locate template for uri %r" % uri
mako.exceptions.TopLevelLookupException: Cant locate template for uri 'template.cpp'

failure to detect the value of MOD on yukicoder No. 1039

$ oj-template https://yukicoder.me/problems/no/1039
#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;


int64_t solve(int64_t M) {
    // TODO: edit here
}

// generated by online-judge-template-generator v4.1.0 (https://github.com/kmyk/online-judge-template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    int64_t M;
    cin >> M;
    auto ans = solve(M);
    cout << ans << endl;
    return 0;
}

Replace endl (!= std::endl) with '\n' in the generated C++ code

Description

std::endl を使うと TLE になりがち (e.g. Codeforces) です。これは std::endl が改行文字 ('\n') を出力するだけでなく出力の flush をしてしまうことに起因します。
https://en.cppreference.com/w/cpp/io/manip/endl
これを防ぐため、現状の実装では std::endl は使わず、endl という名前のローカル変数を利用しています。


しかしこのトリックは分かりにくいものである (例: https://tsutaj.hatenablog.com/entry/2020/10/24/112331) ため、単純に '\n' を使うようにした方がよい気がする (たぶん)。

Possible implementations and the analysis

選択肢は

  • このままにしておく
    • 分かりにくい
    • ユーザが自分で char endl = '\n' を消してしまうと TLE の危険がある (「よく分からないから勝手に消すぜ!」をするのはそういうことをする態度の方が危険そうではあるが)
  • '\n' に切り替える
    • 分かりやすい
    • ユーザが自分で出力パートを編集したときに間違えて endl を使ってしまうと TLE の危険がある (これはよくない。「よく分かってないユーザでも TLE しない」を達成できないため)
  • char endl = '\n' を書いた上で '\n' を使う
    • これが最も安全な気がする
  • std::endl に切り替える
    • TLE するのでだめ

ということで「char endl = '\n' を書いた上で '\n' を使う」 が最良だろうか。

このあたりをカスタマイズする方法がないのも問題なのだけど、面倒なのでカスタマイズについてはとりあえず後回しでいきたい。

作問用機能

作問を補助する機能の追加はそう難しくないし、あるとよさそう。
ランダムケースの生成に関して、問題を解くときと問題を作るときとで特に差はないためである。作問時なら、入力フォーマット文字列 (N A_1 ... A_N みたいなやつ) や機械可読な形での制約 (Library-Checker の info.toml を発展させる感じ) がかならずあると仮定してよいはずで、完璧な結果を作ることはむしろ非作問時より簡単なはず。

現在できてるのは「問題を URL によって指定し、その入力フォーマット情報 (制約の情報を含まない) からランダムケースの生成器 (のテンプレート) を生成する機能」のみ。
やること:

  • 問題の情報をファイルを使って指定し、その入力フォーマット情報 (制約の情報を含む) からランダムケースの生成器 (ただし一切の修正なしでそのまま使えるもの) を生成する機能
    • 入力フォーマット情報 + 制約の情報をファイルから与えるときの仕様を決める
    • 典型パターンを生成するためのライブラリを用意する (例: yosupo06/library-checker-problems#400 onlinejudge_random/__init__.py)
    • 制約の情報と典型パターンのライブラリとを組み合わせた出力を吐く
  • 問題の情報をファイルを使って指定し、その入力フォーマット情報 (制約の情報を含む) から validator を生成する機能

(この issue は、実装内容についてのみ言えば #36#37 の組み合わせになっている)


関連:

-tで指定するファイルの場所について

oj-template のためのテンプレートは ~/.config/online-judge-tools/template/ の下に ~/.config/online-judge-tools/template/customized.py のように作って oj-template -t customized.py https://... のように指定する。

ファイル名に / が含まれることはないので、 / が含まれている場合、
パスが指定されていると推測しても問題ないと思います。

具体的には一つ上の階層にtempate-ext.cppを作った上で

oj-template https://codeforces.com/contest/1349/problem/A -t ../template-ext.cpp

と実行したいです。

こうすることでcoderのようにオンラインジャッジの
作業フォルダを全部GitHubに上げている場合に、そのフォルダだけで情報を管理できるようになります。

ご検討頂ければと思います。

some types are broken in generated C++ code

入力部分が string N; になってる

$ oj-template https://atcoder.jp/contests/abc162/tasks/abc162_d
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: AtCoderProblem.from_url('https://atcoder.jp/contests/abc162/tasks/abc162_d'): https://atcoder.jp/contests/abc162/tasks/abc162_d
INFO:onlinejudge._implementation.logging:[x] GET: https://atcoder.jp/contests/abc162/tasks/abc162_d
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/user/.local/share/online-judge-tools/cookie.jar
ERROR:onlinejudge_template.analyzer.combined:output analyzer failed: 
#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;


int64_t solve(int64_t N, string S) {
    // TODO: edit here
}

// generated by online-judge-template-generator v4.1.0 (https://github.com/kmyk/online-judge-template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    string N;
    string S;
    cin >> N >> S;
    auto ans = solve(N, S);
    cout << ans << endl;
    return 0;
}

output analyzer fails in simple cases

https://yukicoder.me/problems/no/1029

it seems -1 does something wrong.

$ pip3 show online-judge-template-generator | grep Version
Version: 4.0.2

$ oj-template https://yukicoder.me/problems/no/1029
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/ubuntu/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: YukicoderProblem.from_url('https://yukicoder.me/problems/no/1029'): https://yukicoder.me/problems/no/1029
INFO:onlinejudge._implementation.logging:[x] GET: https://yukicoder.me/problems/no/1029
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/ubuntu/.local/share/online-judge-tools/cookie.jar
ERROR:onlinejudge_template.analyzer.combined:output analyzer failed: 
#include <bits/stdc++.h>
#define REP(i, n) for (int i = 0; (i) < (int)(n); ++ (i))
#define REP3(i, m, n) for (int i = (m); (i) < (int)(n); ++ (i))
#define REP_R(i, n) for (int i = (int)(n) - 1; (i) >= 0; -- (i))
#define REP3R(i, m, n) for (int i = (int)(n) - 1; (i) >= (int)(m); -- (i))
#define ALL(x) ::std::begin(x), ::std::end(x)
using namespace std;


int64_t solve(int N, int64_t K, const vector<string> & S, const vector<int64_t> & C) {
    // TODO: edit here
}

// generated by online-judge-template-generator v4.1.0 (https://github.com/kmyk/online-judge-template-generator)
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    constexpr char endl = '\n';
    int64_t N;
    int64_t K;
    cin >> N;
    vector<int64_t> S(N);
    vector<int64_t> C(N);
    cin >> K;
    REP (i, N) {
        cin >> S[i] >> C[i];
    }
    auto ans = solve(N, K, S, C);
    cout << ans << endl;
    return 0;
}

TODO

主機能:

  • 主にサンプルを用いた単純な型の認識
  • パターンマッチによる YES / NO 文字列の解析
  • パターンマッチによる MOD の解析
  • サンプルを用いた出力フォーマットの推論
  • 自然言語解析による変数の制約の解析
  • 自然言語解析による変数の意味 (グラフかどうかなど) の解析
  • 自然言語解析による入力フォーマットの解析

その他:

  • PyPI への登録
  • 品質が安定してきたら宣伝をする
  • デフォルトのテンプレートを増やす
  • 外部向けインターフェースの安定化
  • テストを書く
  • ドキュメントを書く
  • 中間表現の仕様の確定 https://github.com/kmyk/online-judge-tools/issues/696

制約の情報の解析と利用

「入力される変数 x は 0 <= x < MOD を満たすので modint<MOD> 型である」とか「入力される変数 n と列 a_1 ... a_{n-1} と列 b_1 ... b_{n-1} は木を表現している」とか「入力される変数 s は文字 A B のみからなる文字列である」とかの情報を取りたい。これがあると生成結果の品質が向上する。生成された generate.py みたいなのをまったくいじらなくてよくなるとかなりうれしい。

制約の解析はしんどい。場合によってはたぶん古典的な自然言語解析が必要。
手で個別に注釈を与える (interactive にユーザに聞く or ファイルにまとめて書いてもらってそれを読み込む) ことも検討した方がよさそう。

入出力解析

この issue の主目的: 解析器の設計や解析結果のフォーマットについての正解を探す

設計方針について

入出力フォーマット解析について。
まず <pre>N a_1 ... a_N</pre> みたいなやつが与えられていることを仮定する場合 (主に AtCoder) は、基本的にコンパイラに寄せていくのがよいと考えています。

  1. HTML 解析 (HTML parser + XPath/CSS selectorss)
  2. 字句解析 (lex)
  3. 構文解析 (yacc? PEG?)
  4. 意味解析 (ad-hoc)
  5. コード生成 (template engine (mako?) + ad-hoc)

(2.) と (3.) を lex と yacc でやることなどの利点は、処理内容をコードに埋め込むのでなく、BNF などの形で明確に定義できることです。この戦略は結果の解釈性が高く保守性に優れるのでうれしい。ただし失敗時のフォールバックとして完全 ad-hoc 解析器を用意する可能性はある。
(4.) の意味解析はつまり変数の型の決定をする。別枠で持ってきたサンプルと突合するなど。
(5.) はできるだけ計算能力の高い template engine を採用するのが望ましい。本体にプルリクを出さなくても好きな言語に対応できるようにしたいため。

<pre>N a_1 ... a_N</pre> みたいなやつが与えられていることを仮定しない場合 (主に Codeforces + AtCoder の出力フォーマット) は難しい。選択肢はいくつか。

  1. 自然言語解析 (ad-hoc パターンマッチごり押し無理矢理)
  2. サンプルから入力フォーマットを復元
  3. ユーザに入力フォーマットを入力してもらう (Rust や Python で前例あり )

その他の部分 (制約、グラフ判定、MOD、YES/NO、リアクティブ判定) は自然言語解析するしかなさそう。

解析結果のフォーマットについて

解析結果として得られる情報は以下になります:

  • 入力
    • どのような変数が存在するか
    • どのような定数 (MOD) が存在するか
    • 変数はどのような順で入力されるか
    • 変数の制約 (10^9 以下、0 以上 MOD 未満) や意味 (グラフである等) はどのようになっているか
  • 出力
    • どのような変数が存在するか
    • どのような定数 (YES/NO) が存在するか
    • 変数はどのような順で出力すればよいか
  • その他
    • 時間制限
    • メモリ制限
    • 許容誤差
    • リアクティブかどうか

議論が必要なのは「どのような変数が存在するか」「変数はどのような順で入力/出力されるか」部分の中間形式でしょう。
論点はいくつか。

  1. 「どのような変数が存在するか」の情報と「変数はどのような順で入力/出力されるか」の情報を分けるか分けないか
  2. 「変数はどのような順で入力/出力されるか」の情報をどう表現するか
    • パターンマッチにするか (TwoDimensionalPattern("a", "h", "w") みたいなのを並べる)
    • 構造的にする (REP(y, "h", REP(x, "w", input("a[y][x]"))) のような感じに)
  3. 変数についてどれくらい解釈を済ませるか (たとえば a_1 a_3 ... a_{2n-1} という指定がされていたときどうするか)
    • a_0 a_1 ... a_{n-1} に正規化しない
    • a_0 a_1 ... a_{n-1} に正規化する (+ 元の情報をどこかに残す / 残さない)
  4. 改行や空白の情報を保つか
    • 改行は保たれていてほしい。いくつかの言語 (主に Python) では、入力中の改行の位置がかなり重要になるため
    • 空白は暗黙に挿入されるとしてよさそう

現状は「変数の宣言の情報と入力順の情報は分離」「入力は構造的に」「できるだけ正規化する」「改行は保ち、空白は忘れる」がよいかなと思っています。具体的には JSON で以下のようなものを考えています。

{
    "input": {
        "vars": [
            { "name": "n", "type": "int", "raw": ["n"] },
            { "name": "a", "type": "int", "dimension": ["n"], "raw": ["a_1", "a_3", "...", "a_{2n-1}"] },
        ],
        "format": [
            { "type": "input", "dest": ["n"] },
            { "type": "newline" },
            { "type": "loop", "variable": "i", "body": [
                { "type": "input", "dest": ["a", "i"] },
            ]},
            { "type": "newline" },
        ],
    },
    ...  // 同様
}

他にも微妙なとこあるけどひとまずは置いておく。

コマンドラインインターフェースの設計について

入出力解析+コード生成はそれ単体で完結したひとまとまりの機能なので、独立したコマンドを与えておくべきだろう。
これはできるだけ設定ファイルに依存せず、template file ひとつで完結するようにするのがよさそう。
理由はふたつです。

  1. template はライブラリの一部なので GitHub とかに公開されてほしい。たぶんされます。しかしこのとき設定ファイルがないと動かないようでは、公開されても使えないので意味がない。
  2. どうせ結局外部からコマンドを直で叩かれる (あまり推奨したくないけど) のは見えていて、このとき設定ファイルに依存してるとその外部コマンドの可搬性が無になる。

たぶん具体的には以下のようになります。

$ oj-template [-f path/to/template.file] URL > output.file

@kyuridenamida 設計方針とフォーマットとそれぞれ意見ください
私も一度は PoC レベルのものは書いたのでやばい見落としはないはずだけど、実際に保守をした経験がないと分からないような落とし穴はあるはずなので

Improve oj-prepare command

TL;DR: いまの oj-prepare は表現力が足りてないので作り直そうぜ

Description

oj-prepare is a simple script to call oj d and oj-template.
However, this is too simple and poor. We want to use more features, for example:

  • More flexible directory structures
  • Watch directories and run incremental build/test
  • Add some hooks after downloading samples
  • Add some hooks before submitting code
    • e.g. oj-bundle, linters like pylint

Possible implementations

  • Use the current oj-prepare and add more features
  • Use icpc-jag/rime
    • Rime is a famous contest-preparing tool. Solving problems is very similar to preparing problems (e.g. generating test cases, writing naive solutions, etc.).
    • Rime 3 seems under developing now. icpc-jag/rime#71
    • nya3jp/rules_contest
  • Use Bazel
    • Bazel is a modern build tool. Build tools have similar functionalities to oj-prepare (e.g. flexible directory structures, incremental build/test, etc.). In fact, it seems Rime 3 tries to use Bazel.
    • Starlark language is a nice option even if you don't use Bazel.

Other notes

  • Will you try to create a pull request?
    • No. I have no time for this issue now.
  • If someone make a nice replacement of oj-prepare, I'll deprecate the current one.

external formatters

Description

We would like to make external formatters like clang-format or yapf for generated codes.
This is beneficial because:

  1. this allows users configure styles in detail (e.g. indent width, char* s or char *s, etc.) and easily.
  2. this frees developers from worrying styles of generated code.

Possible implementations and the analysis (optional)

The main problem is how to specify formatters for templates.

  1. use side-effect functions in mako template
  2. read magic comment in generated code
  3. configure in oj-prepare side

It seems the (1.) is the best.

oj-template crashes on yukicoder No. 1078

Description

https://yukicoder.me/problems/no/1078

Error log

$ oj-template https://yukicoder.me/problems/no/1078
INFO:onlinejudge._implementation.logging:[x] problem recognized: YukicoderProblem.from_url('https://yukicoder.me/problems/no/1078'): https://yukicoder.me/problems/no/1078
INFO:onlinejudge._implementation.logging:[x] load cookie from: /home/user/.local/share/online-judge-tools/cookie.jar
INFO:onlinejudge._implementation.logging:[x] problem recognized: YukicoderProblem.from_url('https://yukicoder.me/problems/no/1078'): https://yukicoder.me/problems/no/1078
INFO:onlinejudge._implementation.logging:[x] GET: https://yukicoder.me/problems/no/1078
INFO:onlinejudge._implementation.logging:[x] 200 OK
INFO:onlinejudge._implementation.logging:[x] save cookie to: /home/user/.local/share/online-judge-tools/cookie.jar
Traceback (most recent call last):
  File "/home/user/.local/bin/oj-template", line 8, in <module>
    sys.exit(main())
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/main.py", line 41, in main
    resources = onlinejudge_template.analyzer.combined.prepare_from_html(html, url=url, sample_cases=sample_cases)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/combined.py", line 29, in prepare_from_html
    output_format_string = onlinejudge_template.analyzer.html.parse_output_format_string(html, url=url)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/html.py", line 94, in parse_output_format_string
    return parse_generic_format_string(html, kind='out', url=url)
  File "/home/user/.local/lib/python3.6/site-packages/onlinejudge_template/analyzer/html.py", line 70, in parse_generic_format_string
    return pre.string.strip() + '\n'
AttributeError: 'NoneType' object has no attribute 'strip'

generator.py の C++ 版を書く

僕は雑魚すぎてPython全然書けないんですよね...
多分少なからず需要はあると思います

— こるとん (@kyort0n) April 9, 2020

ところで C++ 版といってもいくつかの選択肢がある (まあ全部やれば済むという話はある)

  1. C++ の標準ライブラリの random
    • cons: 標準的で分かりやすい
    • cons: include が不要なので楽
  2. testlib.h を使う
    • https://github.com/MikeMirzayanov/testlib
    • pros: 作問やったことある人にとっては楽
    • cons: 作問やったことない人にとってはしんどい (どうせ Python の generator.py はすでにあるし、作問してる勢にとっての使いやすさを優先したさはある)
    • cons: 複数ファイルを生成する形式なので oj generate-input subcommand との相性は悪い
    • pros: 複数ファイルを生成する形式なのでファイル名を指定して生成ができる
  3. Library Checker の random.h を勝手に使う

multiple test cases

  • TODO: Collecting sample problems whose format are multiple test cases. Please post URLs to this issue. / 複数テストケースの問題の例を収集する。見つけたら URL をこの issue のコメント欄に書いていく

Now there is no support for multiple test cases.
We can detect multiple test cases by grepping the problem statement with something like multiple test cases.

サンプルの取得に失敗した場合に、サンプルだけでなくテンプレート類も作られません。

Summary / 概要

@kimiyuki_u
こんにちは。oj-prepare を試しています。
サンプルの取得に失敗した場合?(onlinejudge_prepare.main:failed to prepare the problem)に、サンプルだけでなくテンプレート類も作られません。

私が欲しいものは、自動入出力コードなんて要らないからとにかくフォルダができて

— maspy (@maspy_stars) June 12, 2021

Steps to reproduce / 再現方法

  1. サンプルの取得に失敗するような問題に対して oj-prepare を実行

environments:

  • version: 不明

Expected behavior / 期待される挙動

テンプレート類が (解析失敗時のデフォルトの形で) 作られる。

Actual behavior / 実際の挙動

テンプレート類がまったく作られない

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.