day4.rs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. use aoc2023_niels_overkamp::common::{self, AOCResult};
  2. use nom::character::complete::multispace1;
  3. use nom::sequence::{preceded, terminated, tuple};
  4. use nom::bytes::complete::tag;
  5. use nom::character::complete::u32 as u32_parser;
  6. use nom::error::convert_error;
  7. use nom::multi::separated_list0;
  8. use nom::combinator::all_consuming;
  9. use nom::Finish;
  10. use std::collections::HashSet;
  11. const DAY: &str = "day4";
  12. fn main() -> Result<(), Box<dyn std::error::Error>> {
  13. common::run(DAY, &run)
  14. }
  15. pub fn run(input: &Vec<String>) -> AOCResult {
  16. let id_parser = preceded(tuple((tag("Card"), multispace1)), terminated(u32_parser, tuple((tag(":"), multispace1))));
  17. let numbers_parser_gen = || separated_list0(multispace1, u32_parser);
  18. let mut card_parser = all_consuming(tuple((
  19. id_parser,
  20. terminated(
  21. numbers_parser_gen(),
  22. tuple((tag(" |"), multispace1))),
  23. numbers_parser_gen())));
  24. let mut copy_counter = vec![];
  25. let mut sum = 0;
  26. for line in input.iter() {
  27. let (_, (id, win_numbers, my_numbers)) = card_parser(line.as_str())
  28. .finish()
  29. .map_err(|e| convert_error(line.as_str(), e))?;
  30. let win_numbers = HashSet::<_>::from_iter(win_numbers.into_iter());
  31. let my_numbers = HashSet::<_>::from_iter(my_numbers.into_iter());
  32. let id = id as usize;
  33. let win_count = win_numbers.intersection(&my_numbers).count();
  34. copy_counter.resize(copy_counter.len().max(id+win_count), 1);
  35. let copy_count = copy_counter[id - 1];
  36. if win_count > 0 {
  37. sum += 1 << (win_count - 1);
  38. for id in id..id+win_count {
  39. copy_counter[id] += copy_count;
  40. }
  41. }
  42. }
  43. Ok([Some(sum.to_string()), Some(copy_counter.into_iter().sum::<u32>().to_string())])
  44. }
  45. #[test]
  46. pub fn test_day4() {
  47. assert!(common::run_test(DAY, &run))
  48. }