Competitive programming tools(oj, oj-template) client for AtCoder, Codeforces, and more!
Now support below online judges and feature.
(defvar oj-online-judges
'((aoj . ((name . "Aizu Online Judge") (url . "https://onlinejudge.u-aizu.ac.jp/")))
(aoj2 . ((name . "Aizu Online Judge (Beta)") (url . "https://onlinejudge.u-aizu.ac.jp/courses/")))
(anrchy-golf . ((name . "Anarchy Golf") (url . "http://golf.shinh.org/p.rb?")))
(atcoder . ((name . "AtCoder") (url . "https://atcoder.jp/contests/")))
(codeforces . ((name . "Codeforces") (url . "https://codeforces.com/contests/")))
(cs-academy . ((name . "CS Academy") (url . "https://csacademy.com/contests/")))
(facebook . ((name . "Facebook Hacker Cup") (url . "https://www.facebook.com/hackercup/")))
(hackerrank . ((name . "HackerRank") (url . "https://www.hackerrank.com/challenges/")))
(hackerrank-contest . ((name . "HackerRank Contest") (url . "https://www.hackerrank.com/contests/")))
(kattis . ((name . "Kattis") (url . "https://open.kattis.com/problems/")))
(poj . ((name . "PKU JudgeOnline") (url . "http://poj.org/problem?id=")))
(topcoder . ((name . "Topcoder") (url . "https://www.topcoder.com/challenges/")))
(toph . ((name . "Toph (Problem Archive)") (url . "https://toph.co/p/")))
(codechef . ((name . "CodeChef") (url . "https://www.codechef.com/problems/")))
(soj . ((name . "Sphere online judge") (url . "https://www.spoj.com/problems/")))
(yukicoder . ((name . "yukicoder") (url . "https://yukicoder.me/problems/no/")))
(yukicoder-contest . ((name . "yukicoder Contest") (url . "https://yukicoder.me/contests/")))
(library-checker . ((name . "Library Checker") (url . "https://judge.yosupo.jp/problem/"))))
"Supported online judges.
- Download sample cases
(aoj-arena aoj anrchy-golf atcoder codeforces
cs-academy facebook hackerrank kattis poj toph
codechef soj yukicoder library-checker)
- Download system cases
(aoj yukicoder)
- Submit solution source code
(atcoder codeforces topcoder hackerrank toph)
NOTE: online-judge symbol MUST NOT include slash (\"/\").")
(leaf oj
:ensure t
:custom ((oj-default-online-judge . 'codeforces)))
This package requires oj, oj-template, selenium.
You can install these tools via M-x oj-install-packages
.
(defun oj-install-packages ()
"Install `oj', `oj-template', `selenium' pip package via `pip3'."
(interactive)
(unless (yes-or-no-p "Install `oj', `oj-template', `selenium' via pip3?")
(error "Abort install"))
(dolist (elm '(("oj" . "online-judge-tools")
("oj-template" . "online-judge-template-generator")
("selenium" . "selenium")))
(unless (executable-find (car elm))
(unless (executable-find "python3")
(error "Missing `python3'. Please ensure Emacs's PATH and the installing"))
(unless (executable-find "pip3")
(error "Missing `pip3'. Please ensure Emacs's PATH and the installing"))
(oj--exec-script (format "pip3 install %s" (cdr elm))))))
But if you want to install via this funciton, you can install them by your command-line shell.
pip3 install online-judge-tools
pip3 install online-judge-template-generator
pip3 install selenium
And then, make sure that the Emacs’s PATH
is set up properly.
M-! which oj
returns some path to oj
executable, your Emacs can use it.
If you get no output, please see Q&A or consider to use exec-path-from-shell.
M-x oj-prepare
is first step to use this package.
This command accept below format.
- Problem URL: https://codeforces.com/contest/1349/problem/A
- Contest URL: https://codeforces.com/contest/1349/
- Problem shortcode (for
oj-defualt-online-judge
): 1349/A - Contest shortcode (for
oj-default-online-judge
): 1349
Template files are generated in oj-home-dir
, open file and edit it.
$ tree codeforces/
codeforces/
└── 1349
├── A
│ ├── a.out
│ ├── geckodriver.log
│ ├── generate.py
│ ├── main.cpp
│ ├── main.py
│ └── test
│ ├── sample-1.in
│ ├── sample-1.out
│ ├── sample-2.in
│ ├── sample-2.out
│ ├── sample-3.in
│ └── sample-3.out
...
└── F2
├── generate.py
├── main.cpp
├── main.py
└── test
├── sample-1.in
├── sample-1.out
├── sample-2.in
├── sample-2.out
├── sample-3.in
└── sample-3.out
$ cat codeforces/1349/A/main.cpp
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define v vector
#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 rrep(i, n) for (int i = (int)(n)-1; i >= 0; --i)
#define rrep3(i, m, n) for (int i = (int)(n)-1; i >= (m); --i)
#define all(x) x.begin(), x.end()
#define rall(x) x.end(x), x.begin()
#define endl '\n'
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll solve(int ebd, const vector<ll> & zdf) {
// TODO: edit here
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int ebd;
cin >> ebd;
vector<ll> zdf(ebd);
rep (i, ebd) {
cin >> zdf[i];
}
auto ans = solve(ebd, zdf);
cout << ans << endl;
return 0;
}
M-x oj-test
do compile
and test
your code.
If your code pass testcases, get below output in *oj*
buffer.
[*] 3 cases found
[!] GNU time is not available: time
[*] sample-1
[x] time: 0.001666 sec
[+] AC
[*] sample-2
[x] time: 0.002213 sec
[+] AC
[*] sample-3
[x] time: 0.001923 sec
[+] AC
[x] slowest: 0.002213 sec (for sample-2)
[+] test success: 3 cases
Compiler command is automatically detected using the quickrun
package. You may use quickrun-add-command
to add or override
commands.
M-x oj-submit
submit your code to online judge.
(The first time, you need M-x oj-login
per online judges.)
- oj-shell-program
- A path to shell executable used
*oj*
buffer. (defaultshell-file-name
(bash
or some customized shell)) - oj-home-dir
- A path for generate files. (default
"~/.emacs.d/oj/"
) - oj-default-online-judge
- A online-judge used for guessing. (default
'codeforces
) - oj-compiler-c
- Compiler name to submit for C/C++. (default
gcc
)If you want to also use Clang local, please add your init.el below.
(quickrun-set-default "c" "c/clang") (quickrun-set-default "c++" "c++/clang++")
- oj-compiler-python
- Compiler name to submit for Python. (default
cpython
) - oj-login-args
- Args for
oj login
. (defaultnil
)usage: oj login [-h] [-u USERNAME] [-p PASSWORD] [--check] [--use-browser {always,auto,never}] url positional arguments: url optional arguments: -h, --help show this help message and exit -u USERNAME, --username USERNAME -p PASSWORD, --password PASSWORD --check check whether you are logged in or not --use-browser {always,auto,never} specify whether it uses a GUI web browser to login or not (default: auto)
- oj-prepare-args
- Args for
oj-prepare
. (defaultnil
)Args for `oj-prepare'. usage: oj-prepare [-h] [-v] [-c COOKIE] [--config-file CONFIG_FILE] url positional arguments: url optional arguments: -h, --help show this help message and exit -v, --verbose -c COOKIE, --cookie COOKIE --config-file CONFIG_FILE default: ~/.config/online-judge-tools/prepare.config.toml
- oj-test-args
- Args for
oj test
. (defaultnil
)Args for `oj-test'. Note that the runtime command (`-c') is detected automatically. usage: oj test [-h] [-c COMMAND] [-f FORMAT] [-d DIRECTORY] [-m {simple,side-by-side}] [-S] [--no-rstrip] [--rstrip] [-s] [-e ERROR] [-t TLE] [--mle MLE] [-i] [-j N] [--print-memory] [--gnu-time GNU_TIME] [--no-ignore-backup] [--ignore-backup] [--json] [--judge-command JUDGE] [test [test ...]] positional arguments: test paths of test cases. (if empty: globbed from --format) optional arguments: -h, --help show this help message and exit -c COMMAND, --command COMMAND your solution to be tested. (default: "./a.out") -f FORMAT, --format FORMAT a format string to recognize the relationship of test cases. (default: "%s.%e") -d DIRECTORY, --directory DIRECTORY a directory name for test cases (default: test/) -m {simple,side-by-side}, --display-mode {simple,side-by-side} mode to display an output with the correct answer (default: simple) -S, --side-by-side display an output and the correct answer with side byside mode (equivalent to --display-mode side-by-side) --no-rstrip --rstrip rstrip output before compare (default) -s, --silent don't report output and correct answer even if not AC (for --mode all) -e ERROR, --error ERROR check as floating point number: correct if its absolute or relative error doesn't exceed it -t TLE, --tle TLE set the time limit (in second) (default: inf) --mle MLE set the memory limit (in megabyte) (default: inf) -i, --print-input print input cases if not AC -j N, --jobs N specifies the number of jobs to run simultaneously (default: no parallelization) --print-memory print the amount of memory which your program used, even if it is small enough --gnu-time GNU_TIME used to measure memory consumption (default: "time") --no-ignore-backup --ignore-backup ignore backup files and hidden files (i.e. files like "*~", "\#*\#" and ".*") (default) --json --judge-command JUDGE specify judge command instead of default diff judge. See https://online-judge-tools.readthedocs.io/en/ master/introduction.en.html #test-for-special-forms-of-problem for details format string for --format: %s name %e extension: "in" or "out" (both %s and %e are required.) tips: You can do similar things with shell: e.g. `for f in test/*.in ; do echo $f ; diff <(./a.out < $f) ${f/.in/.out} ; done`
- oj-submit-args
- Args for
oj submit
. (default'("-y")
)Args for `oj-submit'. usage: oj submit [-h] [-l LANGUAGE] [--no-guess] [-g] [--no-guess-latest] [--guess-cxx-latest] [--guess-cxx-compiler {gcc,clang,all}] [--guess-python-version {2,3,auto,all}] [--guess-python-interpreter {cpython,pypy,all}] [--format-dos2unix] [--format-rstrip] [-G] [--no-open] [--open] [-w SECOND] [-y] [url] file positional arguments: url the URL of the problem to submit. if not given, guessed from history of download command. file optional arguments: -h, --help show this help message and exit -l LANGUAGE, --language LANGUAGE narrow down language choices if ambiguous --no-guess -g, --guess guess the language for your file (default) --no-guess-latest --guess-cxx-latest use the lasest version for C++ (default) --guess-cxx-compiler {gcc,clang,all} use the specified C++ compiler if both of GCC and Clang are available (default: gcc) --guess-python-version {2,3,auto,all} default: auto --guess-python-interpreter {cpython,pypy,all} use the specified Python interpreter if both of CPython and PyPy are available (default: cpython) --format-dos2unix replace CRLF with LF for given file --format-rstrip remove trailing newlines from given file -G, --golf now equivalent to --format-dos2unix --format-rstrip --no-open --open open the result page after submission (default) -w SECOND, --wait SECOND sleep before submitting -y, --yes don't confirm
In oj, you can use template file for auto generate source code.
If you want use your customize template, you save like below file
as ~/.config/online-judge-tools/template/template-ext.cpp
.
<%!
import onlinejudge_template.generator.cplusplus as cplusplus
import onlinejudge_template.generator.about as about
%>\
<%
data['config']['rep_macro'] = 'rep'
data['config']['using_namespace_std'] = True
data['config']['long_long_int'] = 'll'
%>\
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <utility>
#include <tuple>
#include <cstdint>
#include <cstdio>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <deque>
#include <unordered_map>
#include <unordered_set>
#include <bitset>
#include <cctype>
using namespace std;
#define ll long long
#define ld long double
#define v vector
#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 rrep(i, n) for (int i = (int)(n)-1; i >= 0; --i)
#define rrep3(i, m, n) for (int i = (int)(n)-1; i >= (m); --i)
#define all(x) x.begin(), x.end()
#define rall(x) x.end(x), x.begin()
#define endl '\n'
${cplusplus.declare_constants(data)}
ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
${cplusplus.return_type(data)} solve(${cplusplus.formal_arguments(data)}) {
// TODO: edit here
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
${cplusplus.read_input(data)}
auto ${cplusplus.return_value(data)} = solve(${cplusplus.actual_arguments(data)});
${cplusplus.write_output(data)}
return 0;
}
And save below config toml as ~/.config/online-judge-tools/prepare.config.toml
.
[templates]
"main.py" = "main.py"
"main.cpp" = "template-ext.cpp"
"generate.py" = "generate.py"
All feedback and suggestions are welcome!
You can use github issues, but you can also use Slack if you want a more casual conversation.
We welcome PR!
- cask
- install via brew
brew install cask
- manual install
cd ~/ hub clone cask/cask export PATH="$HOME/.cask/bin:$PATH"
- install via brew
Below operation flow is recommended.
make # Install git-hooks in local .git
git branch [feature-branch] # Create branch named [feature-branch]
git checkout [feature-branch] # Checkout branch named [feature-branch]
# <edit loop>
emacs oj.el # Edit something you want
make test # Test oj via multi version Emacs
git commit -am "brabra" # Commit (auto-run test before commit)
# </edit loop>
hub fork # Create fork at GitHub
git push [user] [feature-branch] # Push feature-branch to your fork
hub pull-request # Create pull-request
General Public License Version 3 (GPLv3) Copyright (c) Naoya Yamashita - https://conao3.com https://github.com/conao3/oj.el/blob/master/LICENSE
- Naoya Yamashita (conao3)
- zk-phi (zk-phi)