12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 |
- use aoc2023_niels_overkamp::common::{self, AOCResult};
- use nom::character::complete::multispace1;
- use nom::sequence::{preceded, terminated, tuple};
- use nom::bytes::complete::tag;
- use nom::character::complete::u32 as u32_parser;
- use nom::error::convert_error;
- use nom::multi::separated_list0;
- use nom::combinator::all_consuming;
- use nom::Finish;
- use std::collections::HashSet;
- const DAY: &str = "day4";
- fn main() -> Result<(), Box<dyn std::error::Error>> {
- common::run(DAY, &run)
- }
- pub fn run(input: &Vec<String>) -> AOCResult {
- let id_parser = preceded(tuple((tag("Card"), multispace1)), terminated(u32_parser, tuple((tag(":"), multispace1))));
- let numbers_parser_gen = || separated_list0(multispace1, u32_parser);
- let mut card_parser = all_consuming(tuple((
- id_parser,
- terminated(
- numbers_parser_gen(),
- tuple((tag(" |"), multispace1))),
- numbers_parser_gen())));
-
- let mut copy_counter = vec![];
- let mut sum = 0;
- for line in input.iter() {
- let (_, (id, win_numbers, my_numbers)) = card_parser(line.as_str())
- .finish()
- .map_err(|e| convert_error(line.as_str(), e))?;
- let win_numbers = HashSet::<_>::from_iter(win_numbers.into_iter());
- let my_numbers = HashSet::<_>::from_iter(my_numbers.into_iter());
-
- let id = id as usize;
- let win_count = win_numbers.intersection(&my_numbers).count();
- copy_counter.resize(copy_counter.len().max(id+win_count), 1);
- let copy_count = copy_counter[id - 1];
- if win_count > 0 {
- sum += 1 << (win_count - 1);
-
- for id in id..id+win_count {
- copy_counter[id] += copy_count;
- }
- }
- }
-
- Ok([Some(sum.to_string()), Some(copy_counter.into_iter().sum::<u32>().to_string())])
- }
- #[test]
- pub fn test_day4() {
- assert!(common::run_test(DAY, &run))
- }
|