Automate AtCoder submission (Python)

Introduction

I bought a MacBook. It is a model of Air 2020 i7 16GBRAM 512GB SSD. Of course I was happy with the performance because the benchmark that exceeds twice the heavy (physical) Windows that I have used so far comes out, but the most attractive thing about Mac is the design inside and outside the screen and font rendering. .. The UI is also beautiful and I am very satisfied. Since it's a big deal, I decided to automate the submission of AtCoder, which I'm addicted to recently, while building the environment. The submission language is Python, but the same is true for other languages. ** 20/5/1 postscript: [About AtCoder specification change](#AtCoder specification change) **

Preparation

Things necessary

If you haven't already, put the following in advance. By the way, the editor is used for both VS Code for the contest and Atom for the usual editor, so please read as appropriate below. Hyper The Mac terminal is a lot better than Windows, but it's still a bit clunky. After searching for various things, the terminal called Hyper is very beautiful. It seems that there is also a Pokemon dress-up theme at a third party and it is cute. In the following, the line prefixed with the $ symbol means that you can enter the command that follows it (without $) in the terminal and execute it with Return (Enter). image.png During the contest, I decided to work from the VS Code terminal.

Homebrew A well-known package management system. Copy the command pasted on the Official Page, paste it into the terminal, and execute it. There is a place where you have to press the RETURN key on the way.

==> The Xcode Command Line Tools will be installed.
Press RETURN to continue or any other key to abort

Immediately after that, you will be prompted to enter the password. Terminal I don't know anything, I got stuck here. If I entered my password and thought nothing was displayed, it was just hidden for security ... Enter your Mac password to proceed.

==> /usr/bin/sudo /bin/...
  Password:
 ==> Installation successful!

Python Download and set up the installer from Python Official. Or use brew.

$ brew install python3

Node.js Also download the installer from Node.js Official. It is faster to use the installer.

tool

I will add other necessary tools. Use online-judge-tools for testing. Atcoder-cli is mainly used for submission, directory creation, and test case acquisition. selenium is required for judge execution.

$ pip3 install online-judge-tools
$ oj --version    # check

$ npm install -g atcoder-cli
$ acc -v          # check
$ acc check-oj    # check

$ pip3 install selenium

You may not need it, but I want to use the tree view to understand the directory structure, so install it.

$ brew install tree

I want to use VSCode's code command, so check the version ( -v) and install it if it is not installed. Open the VS Code command palette with + Shift + P and type in shell etc. to execute" Shell Command: Install'code' command in PATH command ".

$ code -v   # check

Setting

First of all, it was inconvenient to move to the terminal opened in Finder, so refer to this article (Maru Pakuri ) I wrote the script. Use a text editor to save the following contents directly under your home directory (/ Users / _username_ =~) with the language setting ShellScript / extension .sh.

Finderset.sh



#!/usr/bin/osascript

tell application "Finder"
    if exists Finder window 1 then
        set currentDir to target of Finder window 1 as Unicode text
        set posixPath to get POSIX path of currentDir
    end if
end tell

Next, place .zshrc that manages settings such as aliases directly under your home directory. If you don't have it yet, set the language setting to ShellScript and create the file name .zshrc. (Since it is a hidden file in Finder, it cannot be seen if it is hidden; switching is Ctrl + Shift + .) The following is an example of the alias I added. cdf is a shortcut for the command to move to the terminal open in the Finder mentioned above, and ʻatc is the move to the location where the directory is placed, but other than that, I will write it below. (Cd` is the command to move the current directory of the terminal) Personally, I decided to create the directory in the location where the local repository of GitHub is located.

.zshrc


# vscode
alias vs='code -r main.py'

# cd
alias cdf='cd $(osascript ~/xxx.sh)'  #The name of the file you just wrote
alias atc='cd /Users/xxx...'  #Where you want to create a directory
alias a='cd ../a ; vs'
alias b='cd ../b ; vs'
alias c='cd ../c ; vs'
alias d='cd ../d ; vs'

# test
alias test='oj t -c "python3 main.py" -d ./tests/'
alias py='python3 main.py'

# start
sta () {
  atc
  acc new $1
  code -r $1
  source cd $1/a
  vs
}

# submit
sd () {
  problem=`pwd | xargs basename`
  contest=`echo $(basename $(pwd | xargs dirname)) | tr '[:upper:]' '[:lower:]'`
  echo "${contest:0:3}$problem" | acc s
  source cd ../`echo $(printf "\x$(printf "%x" $(($(printf "%d" \'$problem)+1)))")`
  vs
}
alias sf='if test ; then sd ; fi'
スクリーンショット 2020-04-28 19.03.35.png

I have set a shortcut to use the terminal comfortably in VS Code. Use + Shift + P to bring up the command palette, type in Keyboard, etc., and select" Basic Settings: Open Keyboard Shortcuts file (JSON) / Preferences: Open Keyboard Shortcuts file (JSON) ". Add two to keybinding.json. Shift + l seems to be unused, so I assigned it. This way you can move between the terminal and the editor with just Shift + l.

keybinding.json


[
    { "key": "shift+l", 
    "command": "workbench.action.terminal.focus" },
    { "key": "shift+l", 
    "command": "workbench.action.focusActiveEditorGroup", "when":"terminalFocus" },
]

Next, log in to AtCoder.

$ acc login
$ oj login https://atcoder.jp/

Set the directory to be created at the same time for all issues in the contest.

$ acc config default-task-choice all

Get the location of the config directory and move it. To pass the result of ʻacctocd, use ``` `` backticks instead of 'single quotes. Create a folder and create the templatemain.py and the template configuration file template.json` in it.

$ cd `acc config-dir`
$ mkdir py
$ cd py
$ touch main.py template.json

Open template.json and write. Now you can open main.py at the same time you create the directory and target main.py when submitting.

$ open -a Atom template.json

template.json


{
  "task":{
    "program": ["main.py"],
    "submit": "main.py"
  }
}

Open main.py and write. Write Shebung on the first line as shown below (required). Since it is a template, you may want to write frequently used code after the second line.

$ open -a Atom main.py

main.py


#!/usr/bin/env python3

Set the template to py.

$ acc config default-template py
$ acc templates   # check
search template directories in /Users/../Library/Preferences/atcoder-cli-nodejs
[NAME]  SUBMIT-PROGRAM
[py]    main.py

Actually use

Directory creation

Go to the location where you want to create the directory with ʻatc and create a new directory with ʻacc new [Contest Name]. Specifically, it is the name of the relevant part of the AtCoder URL. If you can see the following tree, it is successful.

$ atc
$ acc new ABC164    # name of contest 
$ tree
.
├── a
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
...
│       └── sample-3.out
├── b
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       └── sample-2.out
├── c
│   ├── main.py
│   └── tests
│       ├── sample-1.in
...
│       └── sample-3.out
├── contest.acc.json
├── d
│   ├── main.py
│   └── tests
│       ├── sample-1.in
│       ├── sample-1.out
│       ├── sample-2.in
│       ├── sample-2.out
...

12 directories, 43 files

In the previous .zshrc, write the following and automatically move the current directory to the folder in question A. Now you don't have to change directories when submitting A questions. (When working consistently from directory creation to submission in the same terminal)

.zshrc(only_one_part)


sta () {
  atc
  acc new $1
  code -r $1
  source cd $1/a
  vs
}

test

Let's actually open and solve problem A. After executing sta, write the program in ʻa / main.py that opens as it is. Go to the terminal with the shortcut you set earlier, make sure you are in the directory in question (ʻa), and run ʻoj t -c "python3 main.py" -d ./tests/. Since it seems to be long, it is assigned to test in the alias of .zshrc. It was judged properly as ʻAC.

$ pwd     # check current directory (not necessary)
/Users/.../abc164/a

$ test
[*] 3 cases found
time: illegal option -- f
usage: time [-lp] command.
[!] GNU time is not available: time

[*] sample-1
[x] time: 0.022793 sec
[+] AC

...

[x] slowest: 0.022793 sec  (for sample-1)
[+] test success: 3 cases
スクリーンショット 2020-04-29 11.18.21.png

It seems that you will not know if you are only doing competition pros, but when ʻinput ()is executed, the standard input of the terminal will be in the input standby state. So, if you want to execute it in any case other than the sample case, you can usually dopython3 main.py and type in the standard input line by line. (What about ʻopen (0) ...)

Submission

As long as you are in the corresponding directory, you can do it with just ʻacc s. You will just be asked to enter a verification code. Apparently, it seems to be a total of 4 letters that combine the first 3 letters of the contest name and the question number ([ContestName; 3] [problem]; ex.abca). I don't have time to do it, so I have prepared a sdfunction.sdautomatically moves to the next directory after submission. In.zshrc, there is another command (sf) to be submitted only when the result of test is [AC] (= return value is 0`).

.zshrc(only_one_part)


# submit
sd () {
  problem=`pwd | xargs basename`
  contest=`echo $(basename $(pwd | xargs dirname)) | tr '[:upper:]' '[:lower:]'`
  echo "${contest:0:3}$problem" | acc s
  source cd ../`echo $(printf "\x$(printf "%x" $(($(printf "%d" \'$problem)+1)))")`
  vs
}
alias sf='if test ; then sd ; fi'

The browser will open automatically as the submission process progresses. I've also aliased the move to other issues. It works automatically, but if you want to move to the previous / previous problem, you can move the current directory and operate the VS Code file with just ʻa, b, c` ....

.zshrc(only_one_part)


alias a='cd ../a ; vs'
alias b='cd ../b ; vs'
alias c='cd ../c ; vs'
alias d='cd ../d ; vs' # ...

This is perfect! !!

Bonus (where it gets stuck)

When you are editing .zshrc by trial and error and want to reflect it immediately (restart the terminal to reflect it normally)

$ source ~/.zshrc

When the function cannot be used for some reason

.zshrc


function func () {
  # do_something
}
alias func=func

In the shell script, function can be omitted when defining the function, but if you want to define an alias with the same name, you will get the following error unless you explicitly declare it.

$ source ~/.zshrc
/Users/xxx/.zshrc:19: defining function based on alias `func'
/Users/xxx/.zshrc:19: parse error near `()'

AtCoder specification change (additional note)

I thought I couldn't submit it from May 1st, but it seems to be a problem of ʻoj`.

$ oj -v s [URL] main.py
...
  File "/Users/kazuhiroserizawa/.pyenv/versions/3.8.0/lib/python3.8/site-packages/onlinejudge/service/atcoder.py", line 728, in _parse_available_languages
    languages += [Language(option.attrs['value'], option.string)]
KeyError: 'value'

[ERROR] 'value'
スクリーンショット 2020-05-01 13.16.19.png

You're crazy from line 728. There was also a pull request on GitHub. I think it will be fixed soon, but I'll fix it for the time being.

# Install-Location
$ pip show online-judge-tools
...
Location: /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages
...
# Open
$ cd /Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages
$ open -a Atom onlinejudge/service/AtCoder.py

The code modification is here. The rest is rewritten as follows.

References

Don't forget to send a star to GitHub!

Disclaimer

Although it is not explicitly prohibited by AtCoder's terms of service, we can not inconvenience you by overloading the server, so we only get test cases once. Use within the bounds of common sense.

in conclusion

I searched for Unix-like commands without knowing them at all!

Recommended Posts

Automate AtCoder submission (Python)
atCoder 173 Python
AtCoder ABC 174 Python
AtCoder ABC187 Python
AtCoder ABC188 Python
AtCoder ABC 175 Python
Daily AtCoder # 36 in Python
Daily AtCoder # 2 in Python
Daily AtCoder # 32 in Python
Daily AtCoder # 6 in Python
Daily AtCoder # 18 in Python
Daily AtCoder # 53 in Python
Daily AtCoder # 33 in Python
Daily AtCoder # 7 in Python
Daily AtCoder # 24 in Python
Daily AtCoder # 37 in Python
Solve AtCoder 167 with python
Daily AtCoder # 8 in Python
Daily AtCoder # 42 in Python
Daily AtCoder # 21 in Python
Daily AtCoder # 17 in Python
Daily AtCoder # 38 in Python
Daily AtCoder # 54 in Python
Daily AtCoder # 11 in Python
Daily AtCoder # 15 in Python
Daily AtCoder # 47 in Python
Daily AtCoder # 45 in Python
AtCoder: Python: Automate sample testing as much as possible.
Daily AtCoder # 30 in Python
Daily AtCoder # 40 in Python
Daily AtCoder # 10 in Python
Daily AtCoder # 5 in Python
Daily AtCoder # 28 in Python
Daily AtCoder # 39 in Python
Daily AtCoder # 20 in Python
Daily AtCoder # 19 in Python
Daily AtCoder # 52 in Python
Daily AtCoder # 3 in Python
Daily AtCoder # 14 in Python
Daily AtCoder # 50 in Python
Daily AtCoder # 26 in Python
Daily AtCoder # 4 in Python
Daily AtCoder # 43 in Python
Daily AtCoder # 29 in Python
Daily AtCoder # 22 in Python
Daily AtCoder # 49 in Python
Daily AtCoder # 27 in Python
Daily AtCoder # 1 in Python
Daily AtCoder # 25 in Python
Daily AtCoder # 16 in Python
Daily AtCoder # 12 in Python
Python Golf Tech (AtCoder)
Daily AtCoder # 48 in Python
Daily AtCoder # 23 in Python
Daily AtCoder # 34 in Python
Daily AtCoder # 51 in Python
Daily AtCoder # 31 in Python
Daily AtCoder # 46 in Python
Daily AtCoder # 35 in Python
Daily AtCoder # 9 in Python
Daily AtCoder # 44 in Python