day 4 part 2

This commit is contained in:
Dominic 2023-12-04 10:59:19 +01:00
parent d618c30f3d
commit 4b0072f574
Signed by: msrd0
GPG key ID: DCC8C247452E98F9

View file

@ -2,16 +2,15 @@
use aoc23::read; use aoc23::read;
use chumsky::{prelude::*, text::int}; use chumsky::{prelude::*, text::int};
use std::collections::HashSet; use std::collections::{BTreeMap, HashSet};
struct Card { struct Card {
id: usize,
winning_nums: HashSet<usize>, winning_nums: HashSet<usize>,
nums: HashSet<usize> nums: HashSet<usize>
} }
impl Card { impl Card {
fn parser() -> impl Parser<char, Self, Error = Simple<char>> { fn parser() -> impl Parser<char, (usize, Self), Error = Simple<char>> {
let nums = just(" ") let nums = just(" ")
.repeated() .repeated()
.ignore_then(int(10)) .ignore_then(int(10))
@ -29,36 +28,62 @@ impl Card {
.then(nums) .then(nums)
.then_ignore(just(" | ")) .then_ignore(just(" | "))
.then(nums) .then(nums)
.map(|((id, winning_nums), nums): ((String, _), _)| Self { .map(|((id, winning_nums), nums): ((String, _), _)| {
id: id.parse().unwrap(), (id.parse().unwrap(), Self { winning_nums, nums })
winning_nums,
nums
}) })
} }
} }
fn parser() -> impl Parser<char, Vec<Card>, Error = Simple<char>> { fn parser() -> impl Parser<char, BTreeMap<usize, Card>, Error = Simple<char>> {
Card::parser() Card::parser()
.then_ignore(just("\n")) .then_ignore(just("\n"))
.repeated() .repeated()
.map(|cards| cards.into_iter().collect())
.then_ignore(end()) .then_ignore(end())
} }
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
let cards = read("inputs/day4.txt", parser())?; let cards = read("inputs/day4.txt", parser())?;
let mut points = 0; let matches = cards
for card in &cards { .iter()
let matches = card .map(|(id, card)| {
.nums (
.iter() *id,
.filter(|num| card.winning_nums.contains(num)) card.nums
.count(); .iter()
if matches > 0 { .filter(|num| card.winning_nums.contains(num))
points += 1 << (matches - 1); .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!("{points}"); println!("{}", copies.values().sum::<usize>());
Ok(()) Ok(())
} }