Learn how to write effective Advent of Code solutions with this runner system.
When you run a new day, the system automatically creates a template:
from typing import Any
def solve_part_1(input_data: str) -> Any:
"""Solve part 1 of the challenge."""
pass
def solve_part_2(input_data: str) -> Any:
"""Solve part 2 of the challenge."""
pass- Function Names: Must be exactly
solve_part_1andsolve_part_2 - Input Parameter: Always
input_data: str- the raw input as a string - Return Type: Can be any type (
int,str,list, etc.) - will be converted to string for display - Input Processing: You handle parsing the input string yourself
def solve_part_1(input_data: str) -> int:
# Remove trailing whitespace
lines = input_data.strip().split('\n')
# Process each line
numbers = [int(line) for line in lines]
return sum(numbers)def parse_input(input_data: str) -> list[int]:
"""Parse input into a usable format."""
return [int(line) for line in input_data.strip().split('\n')]
def solve_part_1(input_data: str) -> int:
numbers = parse_input(input_data)
return sum(numbers)
def solve_part_2(input_data: str) -> int:
numbers = parse_input(input_data)
return sum(x * 2 for x in numbers)The runner handles most errors gracefully, but you can add your own:
def solve_part_1(input_data: str) -> int:
try:
lines = input_data.strip().split('\n')
if not lines:
raise ValueError("Empty input")
return int(lines[0])
except ValueError as e:
print(f"Error parsing input: {e}")
raiseCreate sample input files in the input/YYYY/ directory:
input/
└── 2025/
├── day1.txt # Actual input
└── day1_sample.txt # Sample input
Run with sample:
python main.py 2025 1 --sampleFor quick testing:
python main.py 2025 1 --sample-input "1\n2\n3\n4\n5"-
Use appropriate data structures:
# Good for lookups seen = set() # Good for counting from collections import Counter counts = Counter(items)
-
Avoid unnecessary work:
# Don't recalculate in loops def solve_part_1(input_data: str) -> int: lines = input_data.strip().split('\n') total = 0 for line in lines: # Process line once processed = expensive_operation(line) total += processed return total
-
Consider algorithmic complexity:
- O(n²) solutions might be too slow for large inputs
- Look for patterns that allow O(n log n) or O(n) solutions
Use the built-in benchmarking to measure performance:
# Benchmark your solution
python main.py 2025 1 --benchmark
# Compare different approaches by editing and re-running
python main.py 2025 1 --benchmark --benchmark-runs 10def parse_grid(input_data: str) -> dict[tuple[int, int], str]:
"""Parse input into a coordinate dictionary."""
grid = {}
lines = input_data.strip().split('\n')
for y, line in enumerate(lines):
for x, char in enumerate(line):
grid[(x, y)] = char
return grid
def get_neighbors(x: int, y: int) -> list[tuple[int, int]]:
"""Get 4-directional neighbors."""
return [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]from collections import deque
def bfs(start, end, is_valid):
queue = deque([(start, 0)]) # (position, distance)
visited = {start}
while queue:
pos, dist = queue.popleft()
if pos == end:
return dist
for next_pos in get_neighbors(*pos):
if next_pos not in visited and is_valid(next_pos):
visited.add(next_pos)
queue.append((next_pos, dist + 1))
return -1 # No path founddef parse_complex_input(input_data: str):
sections = input_data.strip().split('\n\n')
# First section: rules
rules = {}
for line in sections[0].split('\n'):
key, value = line.split(': ')
rules[key] = int(value)
# Second section: items
items = []
for line in sections[1].split('\n'):
items.append(line.split(','))
return rules, itemsdef solve_part_1(input_data: str) -> int:
lines = input_data.strip().split('\n')
# Debug: see what we're working with
print(f"Processing {len(lines)} lines")
print(f"First line: {lines[0]}")
result = process_lines(lines)
# Debug: check intermediate results
print(f"Intermediate result: {result}")
return resultAlways test with sample input first:
# Test with sample before submitting
python main.py 2025 1 --sampleUse the history to see if your changes improved performance:
python main.py 2025 1 --historyKeep your solution files organized:
2025/
├── day1.py # Simple problems can be in one file
├── day5.py # More complex problems might need helpers
└── day5_helpers.py # Helper functions for day 5
For complex solutions, you can import helpers:
from .day5_helpers import parse_input, complex_algorithm
def solve_part_1(input_data: str) -> int:
data = parse_input(input_data)
return complex_algorithm(data)- Check out Performance Tracking to understand how your solutions are benchmarked
- Read Benchmarking for detailed performance analysis
- See CLI Reference for all available commands