/oj.el

Competitive programming tools client for AtCoder, Codeforces

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

https://raw.githubusercontent.com/conao3/files/master/blob/headers/png/oj.el.png https://img.shields.io/github/license/conao3/oj.el.svg?style=flat-square https://img.shields.io/github/tag/conao3/oj.el.svg?style=flat-square https://github.com/conao3/oj.el/workflows/Main%20workflow/badge.svg https://img.shields.io/codacy/grade/62a36f4f04524d5e8c758440e8071c45.svg?logo=codacy&style=flat-square https://img.shields.io/badge/patreon-become%20a%20patron-orange.svg?logo=patreon&style=flat-square https://img.shields.io/badge/twitter-@conao__3-blue.svg?logo=twitter&style=flat-square https://img.shields.io/badge/chat-on_slack-blue.svg?logo=slack&style=flat-square

Table of Contents

Description

https://raw.githubusercontent.com/conao3/files/master/blob/oj.el/oj.gif

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 (\"/\").")

Install

(leaf oj
  :ensure t
  :custom ((oj-default-online-judge . 'codeforces)))

Usage

oj-install-package

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.

oj-prepare

M-x oj-prepare is first step to use this package.

This command accept below format.

Edit your code

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;
}            

oj-test

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.

oj-submit

M-x oj-submit submit your code to online judge. (The first time, you need M-x oj-login per online judges.)

Customize

Variables

oj-shell-program
A path to shell executable used *oj* buffer. (default shell-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. (default nil)
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. (default nil)
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. (default nil)
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
    

Template file

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"

Information

Community

All feedback and suggestions are welcome!

You can use github issues, but you can also use Slack if you want a more casual conversation.

Contribution

We welcome PR!

Require tools for testing

  • cask
    • install via brew
      brew install cask
              
    • manual install
      cd ~/
      hub clone cask/cask
      export PATH="$HOME/.cask/bin:$PATH"
              

Running test

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

Migration

License

General Public License Version 3 (GPLv3)
Copyright (c) Naoya Yamashita - https://conao3.com
https://github.com/conao3/oj.el/blob/master/LICENSE

Author

Contributors