Advent of Code 2023 - Day 12Hot Springs
| Problem statement | Source code | Tags: Dynamic programming
Because we are making a series of decisions (do I fill the ? with # or .?) and each one determines what decisions we can make next (in order to satisfy the arrangement given), this strongly suggests dynamic programming.
We iterate through each spring in the condition records and build groups one by one. The state consists of the current group's index (, is the number of groups) and size (). indicates an "idle" state, i.e., not actively adding springs to the current group. We count how many ways there are to reach each state (see 2021 day 6).
Initially we start at state (want to construct the first group, but no springs added yet). Because in R indices start at 1, all indices into dp are shifted by 1, so 1, 1 corresponds to .
Given a current state, we can do one of the following transitions:
- If the current spring may be operational (
.or?), and the current group size is positive (i.e., the group is active), then we close the current group. However, if the current group size is not equal to the expected size, then it's not a valid place to close, and this state contributes nothing. Otherwise, this state contributes its number to the next state . - If the current spring may be operational (
.or?), and the current group size is zero (i.e., the group is idle), then we are idle and should stay idle. This state contributes its number to the next state . - If the current spring may be damaged (
#or?), then we add it to the current group. However, if the current group size is already at the expected size, or if we have already built enough groups, then this is invalid and contributes nothing. Otherwise, this state contributes its number to the next state .
The valid ending states are those where we have built all groups and the -th group is idle (), or we have built groups and the -th group is active with the expected size (). We sum these two states to get the final answer.
Parts 1 and 2 are exactly the same, except that in part 2 there's some preprocessing with the input, and the count is so big that we need gmp again for the total. (But each count_dp still fits in a 32-bit integer.)