Skip to content

jma127/pcu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PCU: Programming Contest Utility

Comprehensive suite for competitive programming

https://github.com/jma127/pcu

PCU is licensed under the BSD 3-clause license (see LICENSE file).

Installation

All installations require Python 3.6+ with setuptools.

Pip

The simplest method:

pip3 install pcu

Source

Almost as simple:

git clone https://github.com/jma127/pcu.git
cd pcu
python3 setup.py install

Venv Install

If you'd like to keep dependencies separate from your system python, then you may use the venv_install.py script:

git clone https://github.com/jma127/pcu.git
cd pcu
python3 venv_install.py

Usage

After installing PCU with the tool above, you may run the tools from whichever directory you wish to work in. The basic format for the pcu tool is:

$ pcu command problem

The command field is the utility you would like to use. See the Available Tools section for more information. The problem field should be the name of the problem you're currently working on.

Here is an example to get you started. Here (and in the rest of this README), we are trying to solve the particularly challenging add_two_numbers problem, where the program should read two numbers from stdin and write their sum to stdout:

# initialize the problem
# (by default, using the ``cpp`` environment)
# this also creates the source file add_two_numbers.cpp using a template
pcu make add_two_numbers

# add the sample input and output
pcu setin add_two_numbers sample < sample_input.txt
pcu setans add_two_numbers sample < sample_expected_output.txt

# then, edit your source file however you like
vim add_two_numbers.cpp

# run your program (against the sample input, since you added it above)
pcu run add_two_numbers

Available Tools

Initialization and Source File Generation

The command for initializing a problem is pcu make <problem>. By default, this will generate a code skeleton according to predefined templates in your current working directory. The name of the source file is specified by the current environment's source_file setting.

To make the source file for the add_two_numbers problem in the default environment:

pcu make add_two_numbers

To make the source file for the add_two_numbers problem in the Java environment:

pcu make -e java add_two_numbers

If you already have the source file, you can use the -S flag (short for --nosrc) to skip creating the source file (otherwise, PCU will overwrite your precious code).

If you've already initialized the problem and just want to generate a new source file, you can use the -C flag (short for --noclean) to preserve the environment and just generate the source file.

Test Case Management

You can use PCU to manage your custom test cases for a problem. This is particularly useful when combined with pcu run (see below). In PCU, each test case has a unique identifier (set by the user) and may have an input file and an expected output (answer) file.

Adding and Editing Test Cases

The two commands for adding and editing test data are:

  • pcu setin <problem> <testcase>
  • pcu setans <problem> <testcase>.

Let's say we are still working on the problem add_two_numbers, and we are trying to add the sample input and output (which we want to call sample_test). To add the sample input, run:

pcu setin add_two_numbers sample_test
# Now you will be prompted to enter the input.

To add the sample output, run:

pcu setans add_two_numbers sample_test
# Now you will be prompted to enter the expected output.

Of course, both these commands work with stdin redirection:

pcu setin add_two_numbers sample_test < sample_input.txt
pcu setans add_two_numbers sample_test < sample_expected_output.txt

Viewing Test Cases

The commands for viewing test cases are:

  • Viewing list of test cases: pcu info <problem>
  • Get a specific test case's input: pcu getin <problem> <testcase>
  • Get a specific test case's expected output: pcu getin <problem> <testcase>

Example with our add_two_numbers problem:

# Will show us what test cases exist for "add_two_numbers"
pcu info add_two_numbers

pcu getin add_two_numbers sample_test > sample_in.txt
pcu getans add_two_numbers sample_test > sample_ans.txt

Deleting Test Cases

The command for deleting test cases is pcu delcases <problem> <testcase>. Example:

pcu delcases add_two_numbers sample_test

You may specify more than one test case:

pcu delcases add_two_numbers sample_test another_test

Or omit the testcase argument entirely to delete all testcases:

pcu delcases add_two_numbers

Compiling and Running

After you have created the source file, added some test cases, and written up your solution, you'd naturally like to run your code. The command for this is pcu run <problem>. Example:

pcu run add_two_numbers

The command compiles your program and, if compiled successfully, runs it against all test cases. To only test against specific test cases, you can specify the test case names after the problem name:

pcu run add_two_numbers sample_test another_test

If all you want to do is compile, use the pcu comp <problem> command. Example:

pcu comp add_two_numbers

You may modify how PCU compiles and runs your program via environment settings.

Viewing Output

pcu run prints out per-test-case results, including the status (e.g. correct, wrong answer, runtime error), diffs between expected and actual output, and stderr output from your program. However, it does not print the full output of the program for each test case. The commands for getting the output for a specific test case is pcu getout <problem> <testcase> (similarly, to get stderr, run pcu geterr <problem> <testcase>). Example:

pcu getout add_two_numbers sample_test > my_sample_out.txt
pcu geterr add_two_numbers sample_test > my_sample_stderr.txt

Test Case Generation

If you would like to programmatically generate test data for problems, you may use the testgen command. This module uses a user-specified executable (such as a script or a binary) to create testcases. The command for test case generation is pcu testgen <problem> <generator_executable>. The optional argument -n specifies the number of tests that should be generated, and the optional argument -p specifies the prefix for the generated test case names.

To generate 50 test cases for add_two_numbers with the executable gen_test.py:

$ pcu testgen -n 50 add_two_numbers gen_test.py

Make sure that your generator is actually executable (e.g. with chmod 755 in Unix).

Generator Executable Specification

Generator executables are passed two command-line arguments:

  • seq_num: the number of the current test case to be generated. This argument is not very useful unless you're trying to generate test cases with different characteristics (e.g. 10 "small" cases and 10 "large" cases).
  • seed: a seed (different for each test case) that can be used for randomly generating test data. Guaranteed to be nonnegative and to fit within a 32-bit signed integer.

The generator executable should then output the test case input data to stdout, and the expected output (answer) to stderr. Below is an example of a test generator for add_two_numbers:

#!/usr/bin/env python3
import random, sys
random.seed(sys.argv[2]) # the second argument is the random seed
a, b = random.randint(0, 1000000), random.randint(0, 1000000)
print(a, b)
print(a + b, file=sys.stderr)

Help

You may run pcu -h to get a list of commands with descriptions, and pcu <command> -h to get help for any individual command.

Settings

PCU is configurable via the following (case-sensitive) settings:

  • user: your name. You may use os_username to tell PCU to use your system username.
  • default_env: the default environment.
  • datetime_format: a strftime-compatible format string to use in PCU-generated timestamps.
  • max_lines_output: maximum number of output/diff lines to show for each testcase in pcu run.
  • max_lines_error: maximum number of stderr lines to show for each testcase in pcu run.
  • envs: the environments available to PCU. Specified as a YAML mapping of environment name to environment settings.

Default values for these settings are in pcu/static/default_settings.yaml. You may override defaults by specifying your own settings in ~/.pcu/settings.yaml. YAML references can be googled (here is a basic one).

Environment

An environment is simply a coherent group of settings for a specific language, contest, etc. While the settings above are global settings, the following are per-environment settings:

  • template_file: name of the environment's template file. This is required to use pcu make. See the Templates section for more information.
  • compile_timelimit_msec: number of milliseconds the compiler gets.
  • run_timelimit_msec: number of milliseconds for each test case before a judgement of "Time Limit Exceeded".
  • format_strictness: either strict or lax.
    • strict tells pcu run to check for an exact match between expected and actual output.
    • lax tells pcu run to ignore whitespace errors when checking output.
  • aliases: a list of alternative names for this environment.

For the following per-environment settings, you may use ${PCU_PROBLEM_NAME} to refer to the current problem's name:

  • source_file: name of the source file (e.g. output of pcu make).

For the following per-environment settings, in addition to ${PCU_PROBLEM_NAME}, you may use ${PCU_SOURCE_FILE} to refer to the source file name, and ${PCU_SOURCE_FILE_NOEXT} to refer to the source file name without the extension:

  • compile_command: command to compile the program. Note that this is passed as raw shell input, and you are solely responsible for any security implications.
  • run_command: command to run the program. Same caveat as above.
  • input_file: file where the program will expect its input data. PCU_STDIN is a special value meaning that the program reads from stdin.
  • output_file: file where PCU will expect the program to output its results. PCU_STDOUT is a special value meaning that the program writes to stdout.

Templates

pcu make uses templates to generate source files. A template looks very much like a source file, except that pcu make will substitute all parameter names with their respective values. The following are valid template parameters:

  • ${PCU_USER}: the user setting.
  • ${PCU_DATETIME}: the current date and time (formatted via the datetime_format setting)
  • ${PCU_PROBLEM_NAME}: the current problem's name.
  • ${PCU_ENV_NAME}: the current environment's name.
  • ${PCU_COMPILE_TIMELIMIT_MSEC}: the compile_timelimit_msec environment setting.
  • ${PCU_RUN_TIMELIMIT_MSEC}: the run_timelimit_msec environment setting.
  • ${PCU_FORMAT_STRICTNESS}: the format_strictness environment setting.
  • ${PCU_SOURCE_FILE}: the current problem's source file name.
  • ${PCU_SOURCE_FILE_NOEXT}: the above, without the extension.
  • ${PCU_COMPILE_COMMAND}: the shell command used to compile the program.
  • ${PCU_RUN_TIMELIMIT_MSEC}: the shell command used to run the program.
  • ${PCU_INPUT_FILE}: the current problem's input file name.
  • ${PCU_OUTPUT_FILE}: the current problem's output file name.

Templates are per-environment, and PCU uses the environment's template_file setting to search for the template in ~/.pcu/templates/. If not found, PCU will look for it in pcu/static/default_templates/.