day3: both solutions

This commit is contained in:
2025-12-01 16:24:28 -08:00
parent 42d13d41b1
commit b165cfce48
2 changed files with 116 additions and 2 deletions

113
src/day3.rs Normal file
View File

@@ -0,0 +1,113 @@
use aoc_runner_derive::{aoc, aoc_generator};
use itertools::Itertools;
use std::fmt::Display;
struct Rucksack {
items: Vec<u8>,
}
impl From<&[u8]> for Rucksack {
fn from(s: &[u8]) -> Self {
Self {
items: s.iter().cloned().collect(),
}
}
}
impl Display for Rucksack {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
"{}{}",
String::from_utf8_lossy(&self.compartments()[0]),
String::from_utf8_lossy(&self.compartments()[1])
))
}
}
impl Rucksack {
fn compartments(&self) -> [&[u8]; 2] {
let tup = self.items.split_at(self.items.len() / 2);
[tup.0, tup.1]
}
fn common(&self) -> u8 {
for item in self.compartments()[0] {
if self.compartments()[1].contains(&item) {
return *item;
}
}
panic!("Common item not found");
}
fn contains(&self, item: &u8) -> bool {
self.compartments().into_iter().flatten().contains(item)
}
fn common_with<'a>(&self, other: &[u8]) -> impl Iterator<Item = u8> {
self.compartments()
.into_iter()
.flatten()
.filter(|c| other.contains(c))
.cloned()
}
}
fn priority(c: u8) -> u8 {
if c >= b'A' && c <= b'Z' {
c - b'A' + 27
} else if c >= b'a' && c <= b'z' {
c - b'a' + 1
} else {
panic!("Invalid item {c}")
}
}
#[aoc_generator(day3)]
fn parse(input: &[u8]) -> Vec<Rucksack> {
input.split(|i| *i == b'\n').map(|x| x.into()).collect()
}
#[aoc(day3, part1)]
fn part1(input: &Vec<Rucksack>) -> u64 {
input.iter().map(|sack| priority(sack.common()) as u64).sum()
}
#[aoc(day3, part2)]
fn part2(input: &Vec<Rucksack>) -> u64 {
let mut total = 0u64;
for sacks in input.chunks(3) {
let commons_1 = sacks[0].common_with(&sacks[1].items).unique().collect_vec();
let commons = sacks[2].common_with(&commons_1).unique().collect_vec();
if commons.len() != 1 {
panic!(
"Wrong number ({}) of commons for sacks {} {} {}",
commons.len(),
sacks[0],
sacks[1],
sacks[2]
);
}
total += priority(commons[0]) as u64
}
total
}
#[cfg(test)]
mod tests {
use super::*;
const EXAMPLE: &[u8] = b"vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw";
#[test]
fn part1_example() {
assert_eq!(part1(&parse(EXAMPLE)), 157);
}
#[test]
fn part2_example() {
assert_eq!(part2(&parse(EXAMPLE)), 70);
}
}

View File

@@ -1,7 +1,8 @@
mod day2;
mod day1; mod day1;
mod day2;
mod day3;
use aoc_runner_derive::aoc_lib; use aoc_runner_derive::aoc_lib;
pub mod day6; mod day6;
aoc_lib! { year = 2022 } aoc_lib! { year = 2022 }