Skip to main content

A flexible framework for generating randomized test cases with input/output validation, designed for competitive programming and algorithmic testing.

Project description

Contest Helper Framework

A powerful Python framework for competitive programming problem creation, test generation, and package management.

Features

  • Problem Initialization: Quickly scaffold new problem directories with templates
  • Randomized Test Generation: Flexible system for creating diverse test cases
  • Problem Packaging: Combine all components into ready-to-use zip archives
  • Statement Management: Automatically update problem statements with examples
  • Custom Postprocessors: Configure scoring systems with various options

Installation

pip install contest-helper

Command Line Tools

Start a New Problem

ch-start-problem problem_name [--language en|ru] [--checker]

Create Custom Postprocessor

ch-make-postprocessor --max-value 100 [--groups "10,20,30"] [--different] [--by-groups]

Package Problem for Import

ch-combine problem_directory [options]

Update Statement with Examples

ch-statement-preview problem_directory [--lang en|ru]

Core Components

Test Generators

  • Random numbers, strings, lists, dictionaries
  • Configurable ranges and constraints
  • Composition of generators for complex cases

Problem Configuration

  • Time/memory limits
  • Input/output settings
  • Checker configuration
  • Solution validation

File Management

  • Automatic test case processing
  • File categorization (compile/run/post)
  • Sample test detection

Usage Examples

  1. Create a new problem:
ch-start-problem my_problem -l en -c
  1. Generate tests: Edit the generated generator.py to define your test cases

  2. Preview statement:

ch-statement-preview my_problem --lang en
  1. Package for import:
ch-combine my_problem --time-limit 2000 --memory-limit 256000000

Test Generation Examples

👉 Since version 0.6.0, test input/output is now defined through adapters (TextInputAdapter / BinaryInputAdapter, etc.) instead of printer functions.

1. Basic Number Generation

from contest_helper import RandomNumber, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

# Generate 20 random numbers between 1-100
generator = Generator(
    tests_generator=RandomNumber(1, 101),
    tests_count=20,
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

2. String Manipulation Problem

from contest_helper import RandomWord, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

# Generate 15 random words (3-10 chars) and reverse them
generator = Generator(
    tests_generator=RandomWord(),
    tests_count=15,
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

3. Matrix Generation

from contest_helper import RandomNumber, RandomList, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

# Generate 10 random 3x3 matrices (values 0-9)
matrix_gen = RandomList(
    value_generator=RandomList(RandomNumber(0, 10), 3),
    length=3
)

generator = Generator(
    tests_generator=matrix_gen,
    tests_count=10,
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

4. Graph Problem (Edges List)

from contest_helper import RandomNumber, RandomDict, Generator
from contest_helper.basic import TextOutputAdapter, TextInputAdapter

# Generate graphs with 5-10 nodes and random edges
graph_gen = RandomDict(
    key_generator=RandomNumber(1, 11),  # Node IDs 1-10
    value_generator=RandomList(RandomNumber(1, 11), RandomNumber(1, 4)),  # Adjacent nodes
    length=RandomNumber(5, 11)  # Node count
)

class GraphInputAdapter(TextInputAdapter):
    def input_lines(self, value):
        edges = []
        for node, neighbors in value.items():
            edges.extend(f"{node} {n}" for n in neighbors)
        return edges

generator = Generator(
    tests_generator=graph_gen,
    tests_count=5,
    input_adapter=GraphInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

5. Combined Generators

from contest_helper import CombineValues, RandomWord, RandomNumber, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

# Generate tests with multiple values per case
combined_gen = CombineValues([
    RandomWord(min_length=5, max_length=10),  # String
    RandomNumber(1, 100),                     # Number
    RandomNumber(0, 2)                        # Boolean-like
])

generator = Generator(
    tests_generator=combined_gen,
    tests_count=8,
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

Grouped Test Generation Examples

1. Basic Grouped Tests

from contest_helper import RandomNumber, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

# Different groups with different number ranges
generator = Generator(
    tests_generator={
        'small': RandomNumber(1, 11),      # 1-10
        'medium': RandomNumber(10, 101),   # 10-100
        'large': RandomNumber(100, 1001)   # 100-1000
    },
    tests_count={
        'small': 5,    # 5 small tests
        'medium': 3,   # 3 medium tests
        'large': 2     # 2 large tests
    },
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

2. String Problems with Difficulty Groups

from contest_helper import RandomWord, RandomSentence, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

generator = Generator(
    tests_generator={
        'easy': RandomWord(min_length=3, max_length=5),
        'medium': RandomWord(min_length=10, max_length=20),
        'hard': RandomSentence(min_length=3, max_length=5)  # Multi-word sentences
    },
    tests_count={
        'easy': 3,
        'medium': 2,
        'hard': 1
    },
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

3. Graph Problems with Increasing Complexity

from contest_helper import RandomDict, RandomNumber, RandomList, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

generator = Generator(
    tests_generator={
        'trees': RandomDict(
            key_generator=RandomNumber(1, 6),
            value_generator=RandomList(RandomNumber(1, 6), 1),  # Trees have 1 parent
            length=5
        ),
        'graphs': RandomDict(
            key_generator=RandomNumber(1, 11),
            value_generator=RandomList(RandomNumber(1, 11), RandomNumber(1, 3)),
            length=10
        )
    },
    tests_count={
        'trees': 3,
        'graphs': 2
    },
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

4. Combined Groups with Custom Logic

from contest_helper import CombineValues, RandomWord, RandomNumber, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter

generator = Generator(
    tests_generator={
        'arithmetic': RandomNumber(1, 100),
        'strings': RandomWord(min_length=5, max_length=10),
        'mixed': CombineValues([
            RandomWord(min_length=3, max_length=5),
            RandomNumber(10, 20)
        ])
    },
    tests_count={
        'arithmetic': 4,
        'strings': 3,
        'mixed': 2
    },
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

5. Scientific Formatting with Groups

from contest_helper import RandomNumber, Generator
from contest_helper.basic import TextInputAdapter, TextOutputAdapter
import math

generator = Generator(
    tests_generator={
        'precision_low': RandomNumber(1.0, 5.0, 0.1),   # 1 decimal
        'precision_high': RandomNumber(1.0, 5.0, 0.001) # 3 decimals
    },
    tests_count={
        'precision_low': 3,
        'precision_high': 2
    },
    input_adapter=TextInputAdapter(),
    output_adapter=TextOutputAdapter()
)
generator.run()

Compiler Search Utility

The ch-compilers command allows you to search through available compilers and development tools. It supports flexible name matching and displays results in an easy-to-read table format.

Basic Usage

ch-compilers <query>

Examples

  1. Search for Python compilers:

    ch-compilers python
    
  2. Search for Java compilers (case insensitive):

    ch-compilers java
    
  3. Search with a custom CSV data file:

    ch-compilers "c++"
    

Expected Output

Found 3 matches for 'python':

+----+----------------+------------------------------------+
| #  | ID             | Name                               |
+====+================+====================================+
| 1  | python3_13     | Python 3.13.2                      |
+----+----------------+------------------------------------+
| 2  | pypy3_7_1_0    | Python 3.11 (PyPy 7.3.19)          |
+----+----------------+------------------------------------+
| 3  | python2_6      | Python 2.7                         |
+----+----------------+------------------------------------+

Automated Testing Utility

The ch-test command provides comprehensive automated testing capabilities for competitive programming solutions.

Key Features

  • Multi-format support: Tests binary executables and interpreted scripts
  • Flexible execution: Handles C/C++/Rust/Go binaries and Python/Bash scripts
  • Smart test discovery: Automatically pairs input files with expected outputs
  • Custom validation: Supports both direct comparison and checker programs
  • Detailed reporting: Provides test-by-test results and summary statistics

Basic Usage

ch-test ./solution [options]

Common Options

Option Description Example
-c/--checker Path to custom checker program ch-test ./sol -c ./checker
-i/--interpreter Specify script interpreter ch-test sol.py -i python3
-t/--timeout Set execution timeout (seconds) ch-test ./sol -t 5

Test File Structure

Organize tests in a tests directory with pairs of:

  • Input files (any name without .a extension)
  • Output files (same name with .a extension)

Example:

tests/
├── 001       # Test input
├── 001.a     # Expected output
├── 002       # Another test
└── 002.a     # Its expected output

Execution Examples

  1. Test a C++ binary:
ch-test ./solution_cpp
  1. Test a Python script:
ch-test solution.py -i python3
  1. With custom checker:
ch-test ./solution -c ./checker -t 3
  1. Test a Bash script:
ch-test script.sh -i bash

Output Format

[timestamp] INFO - Executing: 001
[timestamp] INFO - Result: PASSED (exact match)
[timestamp] ERROR - Result: FAILED
Expected: 42
Actual: 43

=== Test Execution Summary ===
Total tests run:      5
Passed:               3
Failed:               1
Execution errors:     1
Success rate:    60.00%

Advanced Features

  • Group-based test generation: Organize tests into logical groups
  • Custom scoring: Differential scoring by test difficulty
  • Multi-language support: English and Russian statements
  • Flexible configuration: Override defaults via command line

Requirements

  • Python 3.10+
  • Standard library only (no external dependencies)

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

contest_helper-0.6.5.tar.gz (42.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

contest_helper-0.6.5-py3-none-any.whl (46.6 kB view details)

Uploaded Python 3

File details

Details for the file contest_helper-0.6.5.tar.gz.

File metadata

  • Download URL: contest_helper-0.6.5.tar.gz
  • Upload date:
  • Size: 42.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for contest_helper-0.6.5.tar.gz
Algorithm Hash digest
SHA256 4b26cc8ee3ccb4bec025ef1bef6c2e340d8ea25da5c4ab03ab914337abdf1ae4
MD5 8be3459d0dea5abd3dee7f4eb1c26d0e
BLAKE2b-256 a8639a9b45b528c9738a95c5fb9760098d8076431ca98a93723b1028ba940f15

See more details on using hashes here.

File details

Details for the file contest_helper-0.6.5-py3-none-any.whl.

File metadata

  • Download URL: contest_helper-0.6.5-py3-none-any.whl
  • Upload date:
  • Size: 46.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.5

File hashes

Hashes for contest_helper-0.6.5-py3-none-any.whl
Algorithm Hash digest
SHA256 92ddd7ef8e56962d9fd4d93295bce0100dbe4dae1701b18d5e6535a3db28c368
MD5 33bc38e965e3e9012920988c8d93131f
BLAKE2b-256 d75b5fee50390433edab9a094658d3305d9c592696f7d64935975da8a16bdbeb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page