aoc-2023/d04t2/src/main.rs

88 lines
2.4 KiB
Rust

fn main() {
let input = include_str!("../input.txt");
println!("d04t2: {}", d04t2(input));
}
struct Card {
card_id: usize,
winning_amount: usize,
}
#[must_use]
pub fn d04t2(input: &str) -> usize {
let mut result = 0;
let cards: Vec<Card> = input
.lines()
.map(|line| {
let (card_id, card_data) = line
.split_once(": ")
.map(|(cid, cd)| {
(
cid.split_once(' ')
.unwrap()
.1
.trim()
.parse::<usize>()
.unwrap(),
cd,
)
})
.unwrap();
let (winning_numbers, actual_numbers) = card_data
.split_once(" | ")
.map(|(a, b)| {
(
a.split_whitespace()
.map(|e| e.parse::<usize>().unwrap())
.collect::<Vec<_>>(),
b.split_whitespace()
.map(|e| e.parse::<usize>().unwrap())
.collect::<Vec<_>>(),
)
})
.unwrap();
let winning_amount = actual_numbers
.iter()
.filter(|num| winning_numbers.contains(num))
.count();
Card {
card_id,
winning_amount,
}
})
.collect();
for card in &cards {
result += 1;
println!(
"Checking card {} - {} winning",
card.card_id, card.winning_amount
);
result += add_rec(card, &cards);
}
result
}
fn add_rec(card: &Card, cards: &Vec<Card>) -> usize {
let mut to_add = 0;
for cid in 1..=card.winning_amount {
let found_card = cards.iter().find(|c| c.card_id == card.card_id + cid);
if let Some(found_card) = found_card {
to_add += 1;
to_add += add_rec(found_card, cards);
} else {
println!("\tdidn't find card {}", card.card_id + cid);
}
}
to_add
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_d04t2() {
let input = include_str!("../demo_input.txt");
assert_eq!(d04t2(input), 30);
}
}