The cdbx kit
Every new Advent of Code Program and every prep-course Program has a kit file next to your code: kit.py,
kit.go, Kit.java and so on. It holds small helpers for the things you do every day: checking on the example,
timing two versions, and reading input. It’s ordinary code in your Program, so you can read it, change it, or
delete it.
The helpers have the same names in every language, in that language’s own casing (bench.growth in Python,
kit.Bench.Growth in Go).
Check on the example first
from kit import check
check(part1, example, 13)Runs part1 on the example and prints ✓ or ✗ with what it got. Do this before the real input: an answer that’s
wrong on 10 lines is much easier to fix than one that’s wrong on 1,000.
Time it
from kit import bench
bench.time(part1, data) # part1 12.3 ms
bench.compare(slow, part1, on=data) # fastest first, "684× faster", and whether they agreecompare runs each version on the same input and tells you if they gave different answers, so a faster version
that’s wrong doesn’t sneak through.
Is it fast enough?
bench.growth(slow, part1, on=data)growth runs your function on a quarter, a half and all of the input, and names how the time grows:
growth: doubling the input
slow ×4 each time ≈ n²
part1 ×2.2 each time ≈ n log n×2 each time is n, ×4 is n², ×8 is n³. If your code is n² and the real input is ten times bigger than the example, it takes a hundred times longer. This is how the prep course teaches big O: by measuring, not with formulas. Your functions shouldn’t change their input, because they’re called more than once on it.
Memory
from kit import memory
memory.peak(part1, data) # the most memory the call held at onceReading input
| Call | Gives you |
|---|---|
lines(text) | the lines |
numbers(text) | every whole number in the text, negatives included |
grid(text) | rows of characters |
blocks(text) | the groups between blank lines |
neighbours4(r, c), neighbours8(r, c) | the cells next to (r, c), without or with diagonals |
in_bounds(g, r, c) | whether (r, c) is on the grid |
find(g, "S") | where “S” first appears |
memo | remembers a function’s answers |
Languages without a built-in priority queue (JavaScript, TypeScript, Go, Ruby) also get a small heap.
In each language
The top of each kit file lists every call in that language. How to start:
| Language | Start with |
|---|---|
| Python | from kit import bench, check, numbers |
| JavaScript | const { bench, check, numbers } = require('./kit.js'); |
| TypeScript (Bun) | import { bench, check, numbers } from './kit.ts'; |
| Go | nothing to import: kit.Check(day01Part1, example, 13), kit.Bench.Growth(input, day01Part1) |
| Rust | #[path = "kit.rs"] mod kit; in the day file, then kit::check(part1, example, 13) |
| C# | #load "kit.cs" at the top of the day file, then Kit.Check(Part1, example, 13) |
| Java | nothing to import: Kit.check("part1", Day01::part1, example, 13) |
| C++ | #include "kit.hpp", then kit::check("part1", part1, example, 13) |
| Ruby | require_relative "kit", then Kit.check(method(:part1), example, 13) |
The AI knows it too
The tutor and Review my code know the kit. Ask “is this fast enough?” and the tutor will point you at
bench.growth. When Review suggests a faster idea, it can tell you how to measure the difference yourself.
Prep-course Programs made before the kit existed get it the next time you open a day.