Source: Day 25: Code Chronicle
Full solution for today (spoilers!).
Part 1
You are given a series of locks and keys (see below). How many unique
(lock, key)
are there that do not overlap (they do not have to fit perfectly).A lock starts from the top. The entire top row is
#
and the entire bottom row is.
.##### .#### .#### .#### .#.#. .#... .....
A key is the opposite:
..... ..... ..... #.... #.#.. #.#.# #####
Like the last day of Advent of Code generally is, it’s a lighter day. Most of the weirdness in this day comes from parsing:
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum LocksAndKeys {
Lock([u8; 5]),
Key([u8; 5]),
}
#[aoc_generator(day25)]
fn parse(input: &str) -> Vec<LocksAndKeys> {
let mut lines = input.lines();
let mut result = vec![];
loop {
let mut buffer = vec![];
for _ in 0..7 {
let line = lines.next().unwrap();
buffer.push(line);
}
let is_lock = buffer[0].starts_with('#');
let mut values = [0u8; 5];
// First and last line are always ### and ...
// For locks, it's #s going down, otherwise . going up
#[allow(clippy::needless_range_loop)]
for x in 0..5 {
values[x] = if is_lock {
(0..5)
.find(|y| buffer[y + 1].chars().nth(x).unwrap() == '.')
.unwrap_or(5)
} else {
(0..5)
.find(|y| buffer[5 - y].chars().nth(x).unwrap() == '.')
.unwrap_or(5)
} as u8;
}
result.push(if is_lock {
LocksAndKeys::Lock(values)
} else {
LocksAndKeys::Key(values)
});
if lines.next().is_none() {
break;
}
}
result
}
I totally could have done that much easier by iterating over each row and adding to the values
rather than setting each value once. So it goes.
And the problem:
#[aoc(day25, part1, v1)]
fn part1_v1(input: &[LocksAndKeys]) -> usize {
use LocksAndKeys::*;
input
.iter()
.permutations(2)
.filter(|p| {
let a = p[0];
let b = p[1];
// We'll generate both orders, so only count the one with the lock first
// A lock and key match if there's no overlap *not* if they're exact
match (a, b) {
(Lock(a), Key(b)) => a.iter().zip(b.iter()).all(|(a, b)| a + b <= 5),
_ => false,
}
})
.count()
}
Runtime:
$ cargo aoc --day 25
AOC 2024
Day 25 - Part 1 - v1 : 2835
generator: 343.708ยตs,
runner: 16.44375ms
I could probably get that sub-millisecond, but it’s Christmas. This is enough for now. ๐
Part 2
There’s never a part 2 on day 25 ๐
Merry Christmas!
Benchmarks
$ cargo aoc bench --day 25
Day25 - Part1/v1 time: [5.3849 ms 5.4248 ms 5.4770 ms]