Advent of Code Overview
This section demonstrates how to solve Advent of Code problems using Hardcaml. These examples show how hardware design principles can be applied to algorithmic challenges.
What is Advent of Code?
Section titled “What is Advent of Code?”Advent of Code is an annual programming competition with daily puzzles throughout December. Each problem presents an algorithmic challenge that can be solved with software, but we’re solving them with hardware circuits instead!
Why Hardcaml for AoC?
Section titled “Why Hardcaml for AoC?”Solving AoC problems in Hardcaml demonstrates:
- Sequential logic - State machines for processing streams of data
- Arithmetic circuits - Adders, multipliers, comparators
- Memory management - Registers and state tracking
- Real-world applications - Beyond toy examples
Problem Structure
Section titled “Problem Structure”Each AoC problem is implemented as a Hardcaml circuit with:
- Input interface - Streams of data (digits, commands, etc.)
- State registers - Track progress through the problem
- Combinational logic - Process inputs and compute results
- Output interface - Final answer or running totals
Available Problems
Section titled “Available Problems”A dial with positions 0-99 rotates left or right based on commands. Count how many times it lands on position 0.
Key concepts: Modular arithmetic, state machines, counters
Find numbers where the first half of digits equals the second half (e.g., 1212).
Key concepts: Digit extraction, pattern matching, comparisons
Process lines of digits to find maximum values in specific ranges and compute a sum.
Key concepts: Sequential processing, maximum tracking, multi-cycle computations
Count regions where shapes of a given area can fit within a grid.
Key concepts: Area calculations, comparisons, accumulation
Common Patterns
Section titled “Common Patterns”State Machines
Section titled “State Machines”Most AoC problems use state machines to process input streams:
let spec = Reg_spec.create ~clock:i.clock ~clear:i.clear () inlet open Always in
let%hw_var state = Variable.reg spec ~width:state_bits inlet%hw_var accumulator = Variable.reg spec ~width:acc_bits in
compile [ when_ i.start [ state <-- initial_state ; accumulator <-- zero acc_bits ] ; when_ i.input_valid [ (* Process input *) state <-- next_state ; accumulator <-- accumulator.value +: computed_value ] ];Modular Arithmetic
Section titled “Modular Arithmetic”Many problems require modulo operations. Since hardware doesn’t have native division, use repeated subtraction:
let mod_100 ~width x = let hundred = of_int_trunc ~width 100 in let sub_if_ge y = mux2 (y >=: hundred) (y -: hundred) y in Fn.apply_n_times ~n:9 sub_if_ge x;;Digit Processing
Section titled “Digit Processing”When working with digits, extract them from packed representations:
let get_digit ~digits ~index = let start_bit = (max_digits - 1 - index) * digit_bits in select digits ~high:(start_bit + digit_bits - 1) ~low:start_bit;;Getting Started
Section titled “Getting Started”- Open the IDE
- Select an Advent of Code example from the dropdown
- Read the problem description in the circuit file
- Study the test harness to understand the input format
- Run the circuit to see the solution
- Read the comments - Each circuit file has detailed problem descriptions
- Check the tests - Test files show expected input/output formats
- Watch waveforms - Visualize how state changes over time
- Start simple - Begin with Day 1 to understand the pattern
Next Steps
Section titled “Next Steps”- Day 1: Dial Rotation - Start with the simplest problem
- Day 2: Mirror Numbers - Learn digit manipulation
- Day 3: Digit Processing - Complex state tracking
- Day 12: Shape Counting - Area calculations