adventofcode23/src/day4.rs

87 lines
1.9 KiB
Rust

//! 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<u32>, HashSet<u32>) {
let (_, tmp) = line.split_once(": ").unwrap();
let (win, got) = tmp.split_once(" | ").unwrap();
(
win.split_ascii_whitespace()
.map(|p| p.parse::<u32>().unwrap())
.collect(),
got.split_ascii_whitespace()
.map(|p| p.parse::<u32>().unwrap())
.collect(),
)
}
pub fn part1(input: Vec<String>) -> 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::<u32>()
.to_string()
}
pub fn part2(input: Vec<String>) -> 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");
}
}