aoc2022/src/day03.rs

101 lines
2.5 KiB
Rust

use std::str::FromStr;
use aoc_runner_derive::{aoc, aoc_generator};
#[derive(Debug, Default)]
struct Rucksack {
first_half: Vec<u8>,
second_half: Vec<u8>,
}
#[derive(Debug, Copy, Clone)]
struct NoItemInBothHalves;
#[derive(Debug, Copy, Clone)]
struct NoCommonItem;
impl Rucksack {
fn find_item_in_both_halves(&self) -> Result<u8, NoItemInBothHalves> {
self.first_half
.iter()
.copied()
.find(|item| self.second_half.contains(item))
.ok_or(NoItemInBothHalves)
}
fn has_item(&self, item: u8) -> bool {
self.first_half.contains(&item) | self.second_half.contains(&item)
}
fn find_common_item(&self, others: &[Rucksack]) -> Result<u8, NoCommonItem> {
self.first_half
.iter()
.chain(&self.second_half)
.copied()
.find(|&item| others.iter().all(|rucksack| rucksack.has_item(item)))
.ok_or(NoCommonItem)
}
}
#[derive(Debug, Copy, Clone)]
struct InvalidRucksack;
impl FromStr for Rucksack {
type Err = InvalidRucksack;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut priorities = s
.chars()
.map(|ch| {
if !ch.is_ascii_alphabetic() {
Err(InvalidRucksack)
} else if ch.is_ascii_uppercase() {
Ok(ch as u8 - b'A' + 27)
} else {
Ok(ch as u8 - b'a' + 1)
}
})
.collect::<Result<Vec<_>, _>>()?;
let second_half = priorities.split_off(priorities.len() / 2);
Ok(Rucksack {
first_half: priorities,
second_half,
})
}
}
#[aoc_generator(day3, part1)]
fn input_generator_part1(input: &str) -> Vec<Rucksack> {
input.lines().map(|l| l.parse().unwrap()).collect()
}
#[aoc_generator(day3, part2)]
fn input_generator_part2(input: &str) -> Vec<Vec<Rucksack>> {
input
.lines()
.collect::<Vec<_>>()
.chunks(3)
.map(|list| {
list.iter()
.map(|el| el.parse().unwrap())
.collect::<Vec<_>>()
})
.collect::<Vec<_>>()
}
#[aoc(day3, part1)]
fn solve_part1(input: &[Rucksack]) -> u64 {
input
.iter()
.map(|rucksack| rucksack.find_item_in_both_halves().unwrap() as u64)
.sum()
}
#[aoc(day3, part2)]
fn solve_part2(input: &[Vec<Rucksack>]) -> u64 {
input
.iter()
.map(|rucksacks| rucksacks[0].find_common_item(&rucksacks[1..]).unwrap() as u64)
.sum()
}