//! Day 4: Scratchcards use std::collections::HashSet; use itertools::Itertools; pub const DAY: u8 = 4; pub const TITLE: &str = "Scratchcards"; fn parse(line: &str) -> (HashSet, HashSet) { let (_, tmp) = line.split_once(": ").unwrap(); let (win, got) = tmp.split_once(" | ").unwrap(); ( win.split_ascii_whitespace() .map(|p| p.parse::().unwrap()) .collect(), got.split_ascii_whitespace() .map(|p| p.parse::().unwrap()) .collect(), ) } pub fn part1(input: Vec) -> String { input .iter() .map(|ln| { let (win, got) = parse(ln); let nm = win.intersection(&got).count(); if nm > 0 { 2_u32.pow(nm as u32 - 1) } else { 0 } }) .sum::() .to_string() } pub fn part2(input: Vec) -> String { let cards = input .iter() .map(|ln| { let (win, got) = parse(ln); win.intersection(&got).count() }) .collect_vec(); let mut n_cards = 0; fn process_card(i: usize, cards: &[usize], n_cards: &mut u32) { *n_cards += 1; let nw = cards[i]; for ni in i + 1..(i + 1 + nw).min(cards.len()) { process_card(ni, cards, n_cards); } } for i in 0..cards.len() { process_card(i, &cards, &mut n_cards); } n_cards.to_string() } #[cfg(test)] mod tests { use super::*; #[test] fn t_example1() { assert_eq!(part1(crate::read_example(DAY, 1)), "13"); } #[test] fn t_part1() { assert_eq!(part1(crate::read_input(DAY)), "20855"); } #[test] fn t_example2() { assert_eq!(part2(crate::read_example(DAY, 2)), "30"); } #[test] fn t_part2() { assert_eq!(part2(crate::read_input(DAY)), "5489600"); } }