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
- Create a new problem:
ch-start-problem my_problem -l en -c
-
Generate tests: Edit the generated
generator.pyto define your test cases -
Preview statement:
ch-statement-preview my_problem --lang en
- Package for import:
ch-combine my_problem --time-limit 2000 --memory-limit 256000000
Test Generation Examples
1. Basic Number Generation
from contest_helper import RandomNumber, Generator
# Generate 20 random numbers between 1-100
generator = Generator(
tests_generator=RandomNumber(1, 101),
tests_count=20,
input_printer=lambda x: [str(x)],
output_printer=lambda x: [str(x**2)] # Output is input squared
)
generator.run()
2. String Manipulation Problem
from contest_helper import RandomWord
# Generate 15 random words (3-10 chars) and reverse them
generator = Generator(
tests_generator=RandomWord(),
tests_count=15,
input_printer=lambda x: [x],
output_printer=lambda x: [x[::-1]] # Reversed string
)
generator.run()
3. Matrix Generation
from contest_helper import RandomNumber, RandomList
# 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_printer=lambda m: [f"{n}" for row in m for n in row],
output_printer=lambda m: [str(sum(sum(row) for row in m))] # Sum of all elements
)
generator.run()
4. Graph Problem (Edges List)
from contest_helper import RandomNumber, RandomDict
# 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
)
def print_graph(g):
edges = []
for node, neighbors in g.items():
edges.extend(f"{node} {n}" for n in neighbors)
return edges
generator = Generator(
tests_generator=graph_gen,
tests_count=5,
input_printer=print_graph,
output_printer=lambda _: ["1"] # Dummy output
)
generator.run()
5. Combined Generators
from contest_helper import CombineValues, RandomWord, RandomNumber
# 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_printer=lambda vals: [str(v) for v in vals],
output_printer=lambda vals: [str(len(vals[0]) * vals[1])] # String length repeated N times
)
generator.run()
Grouped Test Generation Examples
1. Basic Grouped Tests
from contest_helper import RandomNumber, Generator
# 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_printer=lambda x: [str(x)],
output_printer=lambda x: [str(x % 10)] # Last digit
)
generator.run()
2. String Problems with Difficulty Groups
from contest_helper import RandomWord, RandomSentence
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_printer=lambda x: [x],
output_printer=lambda x: [x.upper()] # Convert to uppercase
)
generator.run()
3. Graph Problems with Increasing Complexity
from contest_helper import RandomDict, RandomNumber, RandomList
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_printer=lambda g: [f"{k}:{','.join(map(str,v))}" for k,v in g.items()],
output_printer=lambda _: ["1"] # Dummy output
)
generator.run()
4. Combined Groups with Custom Logic
from contest_helper import CombineValues, RandomWord, RandomNumber
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_printer=lambda x: [str(x) if isinstance(x, int) else x],
output_printer=lambda x: (
[str(x*2)] if isinstance(x, int)
else [x[::-1]] if isinstance(x, str)
else [x[0]*x[1]] # string repeated N times
)
)
generator.run()
5. Scientific Formatting with Groups
from contest_helper import RandomNumber, Generator
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_printer=lambda x: [f"{x:.3f}"],
output_printer=lambda x: [f"{math.sin(x):.5e}"] # Scientific notation
)
generator.run()
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file contest_helper-0.4.3.tar.gz.
File metadata
- Download URL: contest_helper-0.4.3.tar.gz
- Upload date:
- Size: 30.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4493f909572a734bcecab5358fba9ad94ba589cf6194644303dc83aa8aa9eeb8
|
|
| MD5 |
a604a17711d1e4eb649786f87640fe46
|
|
| BLAKE2b-256 |
2c2775c3da7559cacb57867825c8f49c423edb106789d6564f3b500e00e061fc
|
File details
Details for the file contest_helper-0.4.3-py3-none-any.whl.
File metadata
- Download URL: contest_helper-0.4.3-py3-none-any.whl
- Upload date:
- Size: 33.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d960d85e066a781e40e3c4d7a6a6d362402d9fa198aa047fd8892f8a7fc211aa
|
|
| MD5 |
c9e0a81feb3071aa7c559fe23cf96983
|
|
| BLAKE2b-256 |
212706712a2b40e122dab1780b674338b692a481c0c541bcfc70c5fedef15884
|