88 lines
2.4 KiB
Rust
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);
|
|
}
|
|
}
|