Utilisez make pour faciliter la saisie standard de l'exemple C ++ / Java / Python de la concurrence pro (AtCorder) Makefile publié

introduction

Récemment, la programmation compétitive est devenue populaire parmi les étudiants programmeurs et les programmeurs actifs (expérience). Je ne participe pas à des concours, mais je résous souvent des problèmes de compétition professionnelle comme un coup d'essai lors de l'apprentissage d'une nouvelle langue. C'est assez intéressant.

Le problème est généralement ** un exemple d'entrée est fourni, mais n'est-il pas compliqué ** de le saisir en standard? Je souhaite l'automatiser si possible. ** Si vous l'automatisez, vous pouvez vous attendre à des essais et des erreurs plus efficaces et à un score plus élevé **! Il existe de nombreuses façons de l'automatiser, mais cet article vous montrera comment utiliser la commande make. Makefile est pour C ++, Java, Python comme exemple. Si vous fournissez des exemples de langages de compilation, de langages Java et de langages de script, l'utilisateur les réécrira en fonction de la langue. Il y a une âme.

Le Makefile et la structure des répertoires de cet article ont été téléchargés sur github. Veuillez utiliser quand c'est bon. https://github.com/aoi-stoic/AtcorderTemplate

Lecteur supposé

Lecteurs inattendus

Environnement de vérification

OS

$ cat /etc/os-release | head -n 2
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"

J'utilise ubuntu. Les autres systèmes d'exploitation et distributions sont omis, veuillez donc les lire comme il convient.

C++

gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu2)

Java

$ echo `javac -version` `java -version`
javac 1.8.0_265
openjdk version "1.8.0_265"
OpenJDK Runtime Environment (build 1.8.0_265-8u265-b01-0ubuntu2~20.04-b01)
OpenJDK 64-Bit Server VM (build 25.265-b01, mixed mode)

Java convient car je l'ai à peine écrit. Si vous contestez le concours avec Java, veuillez choisir la version qui convient au concours.

Python3

$ python3 --version
Python 3.8.2

Choses qui ne sont pas utilisées comme l'environnement virtuel

Comment utiliser

Pseudo-concours ABCXXX Un problème "Recevoir quatre entrées standard et sortir la somme en standard" est utilisé comme thème pour présenter une construction de répertoire de travail et faire un exemple d'exécution de commande. Résolvez en C ++.

Un exemple d'entrée de problème et un exemple de sortie sont les suivants ** Exemple d'entrée 1 ** 1 1 1 1 ** Exemple de sortie 1 ** 4

** Exemple d'entrée 2 ** 1 2 3 4 ** Exemple de sortie 2 ** 10

** Exemple d'entrée 3 ** 1000 100 10 1 ** Exemple de sortie 3 ** 1111

0. Préparation

faire l'installation de la commande

sudo apt isntall make

Construire un répertoire de travail

#Créer et déplacer un répertoire de travail
mkdir ABCXXX && cd ABCXXX   
#Clone du répertoire de modèles (--depth=Cloner avec 1 pour un historique minimal)
git clone --depth=1  https://github.com/aoi-stoic/AtcorderTemplate.git
#Modèle Atcorder pour un problème/Copier le modèle Cpp&Bouge toi
cp AtcorderTemplate/TemplateCpp/ problemA -r && cd problemA

À ce stade, le contenu du répertoire problemmA ressemble à ceci Si vous souhaitez reproduire cette configuration, vous pouvez la générer manuellement sans clonage à partir de git et copier uniquement le Makefile de cet article.

$ tree 
.
├── main.cpp  #Fichier source pour la réponse
├── Makefile  # C++Pour Makefile
└── Testfiles #Répertoire des fichiers de test
    ├── test1.test  #Fichier de test de l'exemple d'entrée 1
    ├── test2.test
    ├── test3.test
    └── test4.test

1. Copiez et collez l'exemple d'entrée

Copiez l'exemple d'entrée dans chaque fichier de test. Le résultat est: Puisqu'il n'y a que 1 à 3 exemples d'entrée d'ABCXXX Un problème, test4.test est un fichier vide.

$ cat Testfiles/test1.test
1 1
1 1
$ cat Testfiles/test2.test
1 2
3 4
$ cat Testfiles/test3.test
1000 100
10 1
$ cat Testfiles/test4.test

2. Codage

Comme d'habitude, j'ai écrit le code de réponse dans main.cpp.

// main.cpp
#include <iostream>

int main(){
    int a, b, c, d;
    std::cin >> a >> b >> c >> d;
    std::cout << a + b + c + d << std::endl;
}

3. Exécutez la commande make

Lorsque vous exécutez la commande make dans le répertoire problemA, Après la compilation, il sera exécuté automatiquement pour chaque exemple d'entrée. Puisque test4.test est vide, l'exemple d'entrée 4 ne sera pas exécuté.

$ make 
g++ -std=c++11 -Wall main.cpp -o main.out
----------------------
exec Testfiles/test1.test
input:
1 1
1 1

output:
4
----------------------
exec Testfiles/test2.test
input:
1 2
3 4

output:
10
----------------------
exec Testfiles/test3.test
input:
1000 100
10 1

output:
1111

4. Soumission ou correction

Assurez-vous que la correspondance entre les exemples d'entrée et de sortie est correcte et soumettez-la lorsque vous êtes certain que le code est correct. Si vous souhaitez passer au problème B suivant, copiez le répertoire TemplateCpp pour créer le problèmeB et travaillez également dans ce répertoire.

faire cible

Les cibles suivantes sont préparées pour le Makefile publié cette fois. Comme python n'a pas de travail de compilation, il n'a pas de cibles telles que build et clean.

cible commander Aperçu
(Aucun) make Exécuter make test
build make build Compiler uniquement
run make run Compilez et exécutez selon vos besoins.
La saisie standard se fait manuellement.
test make test Compilez et exécutez selon vos besoins.
Entrez le contenu du fichier de test par défaut.
clean make clean Supprimez le produit compilé.
clean_test make clean_test Videz le contenu du fichier de test.
Il est utilisé lors de la copie du répertoire de la question A et de sa réutilisation pour la réponse à la question B.

Makefile

Makefile pour C ++

COMP = g++ -std=c++11 -Wall
SRC = main.cpp
BIN = main.out
TESTDIR = Testfiles
#Désactiver les règles implicites,Désactiver la sortie lors du déplacement de répertoires
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory

#Test cible sans exécution d'argument (cible)
all: test

$(BIN): $(SRC)
	$(COMP) $(SRC) -o $(BIN)

#make run est une exécution manuelle de l'entrée standard
.phony:run
run: $(BIN)
	./$(BIN)

# make test
#Exécuter pour saisir le contenu du fichier de test dans TESTDIR en standard (ignorer les fichiers vides)
.phony:test
test: $(BIN)
	@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
	do \
		if [ -s $$testfile ]; then \
			echo ---------------------- ;\
			echo "exec $$testfile " ;\
			echo "input: "; \
			cat $$testfile ; \
			echo "" ;\
			echo "output: " ;\
			cat $$testfile | ./$(BIN) ;\
		fi \
	done

.phony:clean
clean:
	-rm $(BIN)

#Vider tous les fichiers de test
.phony:clean_test
clean_test:
	@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
	do \
		: > $$testfile ;\
	done

Makefile pour Java

J'ai à peine écrit Java.

COMP = javac
EXEC = java
SRC = Main.java
CLASS = Main.class
# Main.class -> Main
APP = $(basename $(CLASS) .class)
TESTDIR = Testfiles
#Désactiver les règles implicites,Désactiver la sortie lors du déplacement de répertoires
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#
#Test cible sans exécution d'argument (cible)
all: test

$(CLASS): $(SRC)
	$(COMP) $(SRC)

#make run est une exécution manuelle de l'entrée standard
run: $(CLASS)
	$(EXEC) $(APP)

# make test
#Exécuter pour saisir le contenu du fichier de test dans TESTDIR en standard (ignorer les fichiers vides)
test: $(CLASS)
	@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
	do \
		if [ -s $$testfile ]; \
			then \
			echo ---------------------- ;\
			echo "exec $$testfile" ;\
			echo "input: " ; \
			cat $$testfile ; \
			echo "" ;\
			echo "output: " ;\
			cat $$testfile | $(EXEC) $(APP) ;\
		fi \
	done \

.phony:clean
clean:
	-rm $(CLASS)

#Vider tous les fichiers de test
.phony:clean_test
clean_test:
	@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
	do \
		: > $$testfile ;\
	done

Makefile pour Python

En termes de Makefile, le langage de script Makefile semble étrange.

SRC = main.py
EXEC = python3
TESTDIR = Testfiles
#Désactiver les règles implicites,Désactiver la sortie lors du déplacement de répertoires
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory

#Test cible sans exécution d'argument (cible)
all: test

#make run est une exécution manuelle de l'entrée standard
.phony:run
run: 
	$(EXEC) $(SRC)

# make test
#Exécuter pour saisir le contenu du fichier de test dans TESTDIR en standard (ignorer les fichiers vides)
.phony:test
test: 
	@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
	do \
		if [ -s $$testfile ]; then \
			echo ---------------------- ;\
			echo "exec $$testfile " ;\
			echo "input: "; \
			cat $$testfile ; \
			echo "" ;\
			echo "output: " ;\
			cat $$testfile | $(EXEC) $(SRC) ;\
		fi \
	done

#Vider tous les fichiers de test
.phony:clean_test
clean_test:
	@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
	do \
		: > $$testfile ;\
	done

De côté

pipeline

Vous pouvez utiliser le pipeline (|) pour relier la sortie d'une commande à l'entrée de la commande suivante.

$ cat Testfiles/test1.test
1 1
1 1
$ cat Testfiles/test1.test | ./main.out  #Sortir la commande cat./main.entrée de sortie
4

Vous pouvez l'utiliser pour créer un script sur l'entrée standard d'un fichier exécutable. make test Profite de cette fonctionnalité.

Comment vider le contenu d'un fichier existant

Lors de la création d'un nouveau fichier vide

touch empty_file

Cela suffit, mais cette méthode ne fonctionne pas pour les fichiers existants. La méthode "supprimer et toucher" comme indiqué ci-dessous n'est pas mon passe-temps


rm empty_file & touch empty_file  #Cela ne convient pas à mon goût

J'utilise souvent les deux types suivants.


#Commande de ne rien faire(:)Rediriger le résultat de
: > empty_file
# /dev/cp nul
cp /dev/null empty_file

Il semble y avoir diverses autres méthodes.

Un script shell n'est-il pas suffisant pour cette échelle?

exactement. Cependant, compte tenu de la définition de raccourcis pour les commandes d'exécution dans l'éditeur, je pense qu'il est préférable de définir des raccourcis pour la commande make plus polyvalente que pour l'exécution de scripts shell.

N'est-il pas plus facile de voir si vous coloriez la sortie de l'écho?

exactement. Veuillez colorier en fonction de l'environnement.

Certaines distributions ubuntu utilisent dash au lieu de bash pour exécuter des scripts shell. Il existe quelques différences dans le comportement de certaines commandes entre bash et dash. Par exemple, dans bash vous pouvez utiliser un code d'échappement pour colorer la sortie de echo comme ```echo -e "\ 033 [31m GREEN \ 033 [m" `` `, mais dans dash vous n'avez pas besoin de l'option -e. N'analyse pas les options. Je n'ai pas colorié la sortie d'écho cette fois car on s'attendait à ce que cette différence soit un problème lors de la publication cette fois.

Recommended Posts

Utilisez make pour faciliter la saisie standard de l'exemple C ++ / Java / Python de la concurrence pro (AtCorder) Makefile publié
[Java] Entrez dans le stdin du processus
Histoire de paiza.jp [solution d'entrée standard Java]
[Java] [Maven3] Résumé de l'utilisation de Maven3