Recently, competitive programming has become popular among student programmers and active programmers (experience). I don't participate in contests, but I often solve competition pro problems as a test shot when learning a new language. It's quite interesting.
The problem is usually ** input examples are provided, but isn't it a hassle ** to input them as standard? I want to automate it if possible. ** If you automate it, you can expect more efficient trial and error and higher score **! There are many ways to automate it, but this article will show you how to use the make command. Makefile is for C ++, Java, Python as a sample. If you provide samples of compilation languages, Java-based languages, and scripting languages, the user will rewrite them according to the language. There is a soul.
I uploaded the Makefile and directory structure of this article to github. Please use when it is good. https://github.com/aoi-stoic/AtcorderTemplate
--Those who have used the make command --Linux / Mac users --Those who input standard input for each input example → Those who think "It would be easier if it could be done automatically"
--Windows users (because I don't use windows) --Those who can write Makefile by themselves --Those who can already automate "standard input" by another method
OS
$ cat /etc/os-release | head -n 2
NAME="Ubuntu"
VERSION="20.04.1 LTS (Focal Fossa)"
I'm using ubuntu. Other OSs and distributions are omitted, so please read as appropriate.
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 is suitable because I have hardly written it. If you are challenging the contest in Java, please choose the version that matches the contest.
Python3
$ python3 --version
Python 3.8.2
Things that are not used such as virtual environment
Pseudo-contest ABCXXX A problem "Receive four standard inputs and output the sum as standard" is used as a theme to present a working directory construction and make command execution example. Solve in C ++.
A problem input and output examples are as follows ** Input example 1 ** 1 1 1 1 ** Output example 1 ** 4
** Input example 2 ** 1 2 3 4 ** Output example 2 ** 10
** Input example 3 ** 1000 100 10 1 ** Output example 3 ** 1111
make command install
sudo apt isntall make
Building a working directory
#Create & move working directory
mkdir ABCXXX && cd ABCXXX
#Template directory clone (--depth=Clone with 1 for minimal history)
git clone --depth=1 https://github.com/aoi-stoic/AtcorderTemplate.git
#Atcorder Template for A problem/Copy Template Cpp&Move
cp AtcorderTemplate/TemplateCpp/ problemA -r && cd problemA
At this point, the contents of the problemmA directory looks like this If you want to reproduce this configuration, you can build it manually without cloning from git, and just copy the Makefile from this article.
$ tree
.
├── main.cpp #Source file for answer
├── Makefile # C++Makefile for
└── Testfiles #Test file directory
├── test1.test #Test file of input example 1
├── test2.test
├── test3.test
└── test4.test
Copy and paste the input example into each test file. The result is: Since there are only 1 to 3 input examples of ABCXXX A problem, test4.test is an empty file.
$ 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
As usual, I wrote the answer code in 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;
}
When I run the make command in the problemA directory, After compiling, it will be executed automatically for each input example. Input example 4 is not executed because test4.test is empty.
$ 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
Make sure that the input and output examples correspond correctly, and submit it when you are confident that the code is correct. If you want to move on to the next B problem, copy the TemplateCpp directory to create problemB and work in that directory as well.
The following targets are prepared in the Makefile posted this time. Since python has no compilation work, it does not have targets such as build and clean.
target | command | Overview |
---|---|---|
(None) | make | Run make test |
build | make build | Compile only |
run | make run | Compile and run as needed. Standard input is done manually. |
test | make test | Compile and run as needed. Enter the contents of the test file as standard. |
clean | make clean | Delete the compiled product. |
clean_test | make clean_test | Empty the contents of the test file. It is used when copying the directory of question A and reusing it for the answer to question B. |
Makefile
COMP = g++ -std=c++11 -Wall
SRC = main.cpp
BIN = main.out
TESTDIR = Testfiles
#Disable implicit rules,Disable output when moving directories
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#Target test with no argument (target) execution
all: test
$(BIN): $(SRC)
$(COMP) $(SRC) -o $(BIN)
#make run is a manual input standard input
.phony:run
run: $(BIN)
./$(BIN)
# make test
#Execute to input the contents of the test file in TESTDIR as standard (ignore empty files)
.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)
#Empty all test files
.phony:clean_test
clean_test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
: > $$testfile ;\
done
I have hardly written Java.
COMP = javac
EXEC = java
SRC = Main.java
CLASS = Main.class
# Main.class -> Main
APP = $(basename $(CLASS) .class)
TESTDIR = Testfiles
#Disable implicit rules,Disable output when moving directories
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#
#Target test with no argument (target) execution
all: test
$(CLASS): $(SRC)
$(COMP) $(SRC)
#make run is a manual input standard input
run: $(CLASS)
$(EXEC) $(APP)
# make test
#Execute to input the contents of the test file in TESTDIR as standard (ignore empty files)
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)
#Empty all test files
.phony:clean_test
clean_test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
: > $$testfile ;\
done
In terms of Makefile, the scripting language Makefile seems strange.
SRC = main.py
EXEC = python3
TESTDIR = Testfiles
#Disable implicit rules,Disable output when moving directories
MAKEFLAGS :=+ --no-builtin-rules --no-print-directory
#Target test with no argument (target) execution
all: test
#make run is a manual input standard input
.phony:run
run:
$(EXEC) $(SRC)
# make test
#Execute to input the contents of the test file in TESTDIR as standard (ignore empty files)
.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
#Empty all test files
.phony:clean_test
clean_test:
@for testfile in $(wildcard $(TESTDIR)/*.test) ; \
do \
: > $$testfile ;\
done
You can use the pipeline (|) to bridge the output of a command to the input of the next command.
$ cat Testfiles/test1.test
1 1
1 1
$ cat Testfiles/test1.test | ./main.out #The output of the cat command./main.I'm using out input
4
You can use it to script the standard input of an executable file.
make test
Is taking advantage of this feature.
When creating a new empty file
touch empty_file
That's enough, but this method doesn't work for existing files. The method of "delete and touch" as shown below is not my hobby
rm empty_file & touch empty_file #This doesn't suit my taste
I often use the following two types.
#Command to do nothing(:)Redirect the result of
: > empty_file
# /dev/cp null
cp /dev/null empty_file
There seem to be various other methods.
exactly. However, considering setting shortcuts for execution commands in the editor, I think it is better to set shortcuts for the more versatile make command than for executing shell scripts.
exactly. Please color according to the environment.
Some ubuntu distributions use dash instead of bash to execute shell scripts. There are some differences in the behavior of some commands between bash and dash. For example, in bash you can use an escape code to color the echo output as ```echo -e "\ 033 [31m GREEN \ 033 [m" `` `, but in dash you don't need the -e option. Does not analyze the options. I didn't color the echo output this time because it was expected that this difference would be a problem when publishing this time.