89 lines
1.8 KiB
Rust
89 lines
1.8 KiB
Rust
#![forbid(elided_lifetimes_in_paths, unsafe_code)]
|
|
|
|
use aoc23::read;
|
|
use chumsky::{prelude::*, text::int};
|
|
use std::collections::{BTreeMap, HashSet};
|
|
|
|
struct Card {
|
|
winning_nums: HashSet<usize>,
|
|
nums: HashSet<usize>
|
|
}
|
|
|
|
impl Card {
|
|
fn parser() -> impl Parser<char, (usize, Self), Error = Simple<char>> {
|
|
let nums = just(" ")
|
|
.repeated()
|
|
.ignore_then(int(10))
|
|
.separated_by(just(" "))
|
|
.map(|nums| {
|
|
nums.into_iter()
|
|
.map(|num: String| num.parse().unwrap())
|
|
.collect::<HashSet<usize>>()
|
|
});
|
|
|
|
just("Card")
|
|
.ignore_then(just(" ").repeated())
|
|
.ignore_then(int(10))
|
|
.then_ignore(just(": "))
|
|
.then(nums)
|
|
.then_ignore(just(" | "))
|
|
.then(nums)
|
|
.map(|((id, winning_nums), nums): ((String, _), _)| {
|
|
(id.parse().unwrap(), Self { winning_nums, nums })
|
|
})
|
|
}
|
|
}
|
|
|
|
fn parser() -> impl Parser<char, BTreeMap<usize, Card>, Error = Simple<char>> {
|
|
Card::parser()
|
|
.then_ignore(just("\n"))
|
|
.repeated()
|
|
.map(|cards| cards.into_iter().collect())
|
|
.then_ignore(end())
|
|
}
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
let cards = read("inputs/day4.txt", parser())?;
|
|
|
|
let matches = cards
|
|
.iter()
|
|
.map(|(id, card)| {
|
|
(
|
|
*id,
|
|
card.nums
|
|
.iter()
|
|
.filter(|num| card.winning_nums.contains(num))
|
|
.count()
|
|
)
|
|
})
|
|
.collect::<BTreeMap<usize, usize>>();
|
|
|
|
// part 1
|
|
println!(
|
|
"{}",
|
|
matches
|
|
.values()
|
|
.map(|count| match count {
|
|
0 => 0,
|
|
_ => 1 << (count - 1)
|
|
})
|
|
.sum::<usize>()
|
|
);
|
|
|
|
// part 2
|
|
let mut copies = cards
|
|
.keys()
|
|
.map(|key| (*key, 1))
|
|
.collect::<BTreeMap<usize, usize>>();
|
|
for id in cards.keys() {
|
|
let num_copies = copies[id];
|
|
for next in id + 1 ..= id + matches[id] {
|
|
if let Some(next_copies) = copies.get_mut(&next) {
|
|
*next_copies += num_copies;
|
|
}
|
|
}
|
|
}
|
|
println!("{}", copies.values().sum::<usize>());
|
|
|
|
Ok(())
|
|
}
|