Automatiser la soumission d'AtCoder (Python)

introduction

J'ai acheté un MacBook. Il s'agit d'un modèle de SSD Air 2020 i7 16GBRAM 512GB. Bien sûr, j'étais satisfait des performances parce que la référence qui dépasse le double du Windows (physique) lourd que j'ai utilisé jusqu'à présent, mais la chose la plus attrayante à propos de Mac est la conception à l'intérieur et à l'extérieur de l'écran et le rendu des polices. .. L'interface utilisateur est également magnifique et j'en suis très satisfait. Comme c'est un gros problème, j'ai décidé d'automatiser la soumission d'AtCoder, dont je suis accro récemment, tout en construisant l'environnement. Le langage de soumission est Python, mais il en va de même pour les autres langages. ** PostScript 20/5/1: [À propos du changement de spécification d'AtCoder](Changement de spécification #AtCoder) **

Préparation

Les choses nécessaires

Si vous ne l'avez pas déjà fait, mettez ce qui suit à l'avance. À propos, l'éditeur est utilisé à la fois pour VS Code pour le concours et Atom pour l'éditeur habituel, veuillez donc lire ci-dessous. Hyper Le terminal Mac est bien meilleur que Windows, mais il reste un peu maladroit. Après avoir recherché diverses choses, le terminal appelé Hyper est très beau. Il semble qu'il y ait aussi un thème d'habillage Pokemon chez un tiers et c'est mignon. Dans ce qui suit, la ligne précédée du signe «» signifie que vous pouvez entrer la commande suivante (sans «») dans le terminal et l'exécuter avec Retour (Entrée). image.png Pendant le concours, j'ai décidé de travailler depuis le terminal VS Code.

Homebrew C'est un célèbre système de gestion de paquets. Copiez la commande collée sur la Page officielle, collez-la dans le terminal et exécutez-la. Il y a un endroit où vous devez appuyer sur la touche RETOUR en chemin.

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

Immédiatement après cela, vous serez invité à entrer votre mot de passe. Terminal je ne sais rien, je suis resté coincé ici. Si j'ai entré mon mot de passe et que je pensais ne rien voir, il était simplement masqué pour des raisons de sécurité ... Entrez votre mot de passe Mac pour continuer.

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

Python Téléchargez et configurez le programme d'installation depuis Python Official. Ou utilisez une infusion.

$ brew install python3

Node.js Téléchargez également le programme d'installation depuis Node.js Official. Il est plus rapide d'utiliser le programme d'installation.

outil

J'ajouterai d'autres outils nécessaires. Utilisez des outils de juge en ligne pour les tests. Atcoder-cli est principalement utilisé pour la soumission, la création de répertoires et l'acquisition de cas de test. le sélénium est nécessaire pour l'exécution du juge.

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

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

$ pip3 install selenium

Vous n'en avez peut-être pas besoin, mais je souhaite utiliser l'arborescence pour comprendre la structure des répertoires, alors installez-la.

$ brew install tree

Je veux utiliser la commande code de VSCode, alors vérifiez la version ( -v) et installez-la si elle n'est pas installée. Ouvrez la palette de commandes VS Code avec + Shift + P et tapez shell etc. pour exécuter" Shell Command: Install'code 'command in PATH command ".

$ code -v   # check

Réglage

Tout d'abord, il n'était pas pratique de se déplacer vers le terminal ouvert dans Finder, alors reportez-vous à cet article (Maru Pakuri ) J'ai écrit le scénario. Utilisez un éditeur de texte pour enregistrer le contenu suivant directement sous le répertoire personnel (/ Users / _username_ =~) avec le paramètre de langue 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

Ensuite, placez .zshrc qui gère les paramètres tels que les alias directement sous le répertoire personnel. Si vous ne l'avez pas encore, définissez le paramètre de langue sur ShellScript et créez le nom de fichier .zshrc. (Comme il s'agit d'un fichier caché dans le Finder, il ne peut pas être vu s'il est caché; la commutation est Ctrl + Shift + .) Ce qui suit est un exemple de l'alias que j'ai ajouté. cdf est un raccourci pour la commande pour se déplacer vers le terminal vers le répertoire ouvert dans Finder mentionné ci-dessus, ʻatc est pour se déplacer vers l'emplacement où le répertoire est placé, mais à part ça, je l'écrirai ci-dessous. (Cd` est la commande pour déplacer le répertoire courant du terminal) Personnellement, j'ai décidé de créer le répertoire à l'emplacement où se trouve le référentiel local de GitHub.

.zshrc


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

# cd
alias cdf='cd $(osascript ~/xxx.sh)'  #Le nom du fichier que vous venez d'écrire
alias atc='cd /Users/xxx...'  #Où vous souhaitez créer un répertoire
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

J'ai défini un raccourci pour utiliser le terminal confortablement avec VS Code. Utilisez + Shift + P pour afficher la palette de commandes, tapez Clavier, etc., et sélectionnez" Paramètres de base: Ouvrir le fichier de raccourcis clavier (JSON) / Préférences: Ouvrir le fichier de raccourcis clavier (JSON) ". Ajoutez-en deux à keybinding.json. Shift + l semble être inutilisé, alors je l'ai attribué. De cette façon, vous pouvez vous déplacer entre le terminal et l'éditeur avec juste Shift + l.

keybinding.json


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

Ensuite, connectez-vous à AtCoder.

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

Définissez un répertoire à créer en même temps pour tous les numéros du concours.

$ acc config default-task-choice all

Obtenez l'emplacement du répertoire de configuration et déplacez-le. Pour transmettre le résultat de ʻacc à cd, utilisez des guillemets `` `` arrière au lieu de`` guillemets simples. Créez un dossier et créez le modèlemain.py et le fichier de configuration du modèle template.json` dedans.

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

Ouvrez template.json et écrivez. Vous pouvez maintenant ouvrir main.py en même temps que la création du répertoire et de la cible main.py lors de la soumission.

$ open -a Atom template.json

template.json


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

Ouvrez main.py et écrivez. Écrivez «Shebung» sur la première ligne comme indiqué ci-dessous (obligatoire). Puisqu'il s'agit d'un modèle, vous souhaiterez peut-être écrire du code fréquemment utilisé sur la deuxième ligne et les suivantes.

$ open -a Atom main.py

main.py


#!/usr/bin/env python3

Définissez le modèle sur 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

En fait utiliser

Créer un répertoire

Allez à l'emplacement où vous voulez créer le répertoire avec ʻatc, et créez un nouveau répertoire avec ʻacc new [Nom du concours] . Plus précisément, il s'agit du nom de la partie pertinente de l'URL d'AtCoder. Si vous voyez l'arborescence suivante, cela signifie qu'il réussit.

$ 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

Dans le précédent .zshrc, écrivez ce qui suit pour déplacer automatiquement le répertoire actuel vers le dossier A problem. Vous n'avez plus besoin de changer de répertoire lorsque vous soumettez une question. (Lorsque vous travaillez de manière cohérente de la création du répertoire à la soumission dans le même terminal)

.zshrc(only_one_part)


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

tester

Ouvrons et résolvons le problème A. Après avoir exécuté sta, écrivez le programme dans ʻa / main.py qui s'ouvre tel quel. Allez simplement au terminal avec le raccourci que vous avez défini précédemment, assurez-vous que vous êtes dans le répertoire en question (ʻa), et exécutez ʻoj t -c "python3 main.py" -d. / Tests / . Comme il semble long, il est assigné à test dans l'alias de .zshrc`. Il a été jugé correctement comme «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

Il semble que vous ne saurez pas si vous ne faites que des pros de la compétition, mais à l'origine, lorsque ʻinput () est exécuté, l'entrée standard du terminal sera en état d'attente d'entrée. Donc, si vous voulez l'exécuter dans n'importe quel cas autre que l'exemple de cas, vous pouvez généralement faire python3 main.pyet taper l'entrée standard ligne par ligne. (Qu'en est-il de ʻopen (0)...)

Soumission

Tant que vous êtes dans le répertoire correspondant, vous pouvez le faire avec juste ʻacc s. Il vous sera simplement demandé de saisir un code de vérification. Apparemment, il semble y avoir un total de 4 caractères qui combinent les 3 premières lettres du nom du concours et le numéro de la question («[Nom du concours; 3] [problème]»; ex.abca). Je n'ai pas le temps de le faire, j'ai donc préparé une fonction sd. sdse déplace automatiquement vers le répertoire suivant après la soumission. Dans.zshrc, il y a une autre commande ( sf) à soumettre uniquement lorsque le résultat de test est [AC] (= la valeur de retour est 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'

Le navigateur s'ouvrira automatiquement à mesure que le processus de soumission progresse. J'ai également aliasé le passage à d'autres problèmes. Cela fonctionne automatiquement, mais si vous passez au problème précédent / précédent, vous pouvez déplacer le répertoire actuel et utiliser le fichier VS Code avec juste ʻ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' # ...

C'est parfait! !!

Bonus (là où il est bloqué)

Lorsque vous éditez .zshrc par essais et erreurs et que vous voulez le refléter immédiatement (redémarrez le terminal pour le refléter normalement)

$ source ~/.zshrc

Lorsque la fonction ne peut pas être utilisée pour une raison quelconque

.zshrc


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

Dans le script shell, fonction peut être omis lors de la définition d'une fonction, mais si vous voulez définir un alias avec le même nom, vous obtiendrez l'erreur suivante à moins que vous ne le déclariez explicitement.

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

À propos des modifications des spécifications d'AtCoder (note supplémentaire)

Je pensais que je ne pourrais pas le soumettre à partir du 1er mai, mais cela semble être un problème avec «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

Vous êtes fou de la ligne 728. GitHub avait également une pull request. Je pense que cela sera bientôt corrigé, mais je vais le réparer pour le moment.

# 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

Cliquez ici pour les modifications du code (https://github.com/kmyk/online-judge-tools/pull/739/commits/577b1d9d9a505cea7835ac1c0a98ef9377b8b919). Le reste est réécrit comme suit.

Les références

N'oubliez pas d'envoyer une étoile sur GitHub!

Avertissement

Bien que cela ne soit pas explicitement interdit par les conditions d'utilisation d'AtCoder, nous ne prenons pas le cas de test une seule fois car il ne peut pas submerger le serveur et causer des inconvénients. Utilisez dans les limites du bon sens.

en conclusion

J'ai cherché des commandes Unix sans les connaître du tout!

Recommended Posts

Automatiser la soumission d'AtCoder (Python)
atCoder 173 Python
AtCoder ABC 174 Python
AtCoder ABC 175 Python
AtCoder # 36 quotidien avec Python
AtCoder # 2 tous les jours avec Python
Daily AtCoder # 32 en Python
Daily AtCoder # 6 en Python
Daily AtCoder # 18 en Python
Daily AtCoder # 53 en Python
Daily AtCoder # 33 en Python
AtCoder # 7 tous les jours avec Python
AtCoder # 24 tous les jours avec Python
Daily AtCoder # 37 en Python
Résolvez AtCoder 167 avec python
AtCoder # 8 tous les jours avec Python
Daily AtCoder # 42 en Python
AtCoder # 21 quotidien avec Python
Daily AtCoder # 17 avec Python
Daily AtCoder # 38 en Python
Daily AtCoder # 54 en Python
Daily AtCoder # 11 en Python
Daily AtCoder # 15 en Python
Daily AtCoder # 47 avec Python
AtCoder # 45 quotidien avec Python
AtCoder: Python: Automatisez autant que possible les tests d'échantillons.
AtCoder # 30 tous les jours en Python
AtCoder # 40 quotidien avec Python
AtCoder # 10 quotidien avec Python
AtCoder # 5 tous les jours avec Python
Daily AtCoder # 28 en Python
AtCoder # 39 quotidien avec Python
Daily AtCoder # 20 en Python
Daily AtCoder # 19 en Python
Daily AtCoder # 52 en Python
Daily AtCoder # 3 en Python
Daily AtCoder # 14 avec Python
Daily AtCoder # 50 avec Python
Daily AtCoder # 26 avec Python
AtCoder quotidien # 4 avec Python
Daily AtCoder # 43 en Python
Daily AtCoder # 29 en Python
Tous les jours avec Python AtCoder # 22
Daily AtCoder # 49 en Python
Daily AtCoder # 27 en Python
AtCoder # 1 tous les jours avec Python
Daily AtCoder # 25 avec Python
Daily AtCoder # 16 en Python
Daily AtCoder # 12 en Python
Technologie de golf Python (AtCoder)
Daily AtCoder # 48 en Python
Daily AtCoder # 23 en Python
Daily AtCoder # 34 en Python
AtCoder # 51 quotidien avec Python
Daily AtCoder # 31 en Python
Daily AtCoder # 46 en Python
AtCoder # 35 quotidien avec Python
AtCoder # 9 tous les jours avec Python
Daily AtCoder # 44 avec Python