92 lines
3.0 KiB
Rust
92 lines
3.0 KiB
Rust
use std::collections::VecDeque;
|
|
|
|
use log::debug;
|
|
|
|
use super::utils::Part;
|
|
|
|
struct Card {
|
|
nb_winning: u32,
|
|
value: u32,
|
|
count: u32
|
|
}
|
|
|
|
fn parse(line: &str) -> Card {
|
|
debug!("Processing {}", line);
|
|
let (_, values) = line.split_once(':').unwrap();
|
|
let (winning, numbers) = values.split_once('|').unwrap();
|
|
let nb_win : Vec<u32> = winning.trim().split(' ').filter(|v| !v.is_empty()).map(|v| v.parse().unwrap()).collect();
|
|
let nb_card : Vec<u32> = numbers.trim().split(' ').filter(|v| !v.is_empty()).map(|v| v.parse().unwrap()).collect();
|
|
|
|
debug!("{:?}", nb_win);
|
|
debug!("{:?}", nb_card);
|
|
|
|
let mut value = 0;
|
|
let mut winner_nb = 0;
|
|
for nb in nb_card {
|
|
if nb_win.contains(&nb) {
|
|
winner_nb += 1;
|
|
if value == 0 {
|
|
value = 1;
|
|
}else{
|
|
value *= 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
Card { nb_winning: winner_nb, value, count: 1 }
|
|
}
|
|
|
|
pub fn solve(lines: Vec<String>, part: Part) -> u32 {
|
|
let mut cards : Vec<Card> = lines.iter().map(|l| parse(l)).collect();
|
|
|
|
|
|
match part {
|
|
Part::One => cards.iter().map(|c| c.value).sum(),
|
|
Part::Two => {
|
|
let mut next_adds : VecDeque<u32> = VecDeque::new();
|
|
let mut counter = 0;
|
|
for card in &mut cards {
|
|
counter += 1;
|
|
debug!("Card {}: Adding {} next cards", counter, card.nb_winning);
|
|
|
|
if let Some(bonus) = next_adds.pop_front(){
|
|
// If there is a value, we add it to the current card
|
|
card.count += bonus;
|
|
debug!("Current card count is {}", card.count);
|
|
}
|
|
for i in 0..(card.nb_winning) {
|
|
// For each value our current card has we add all those on the stack
|
|
if let Some(value) = next_adds.get_mut(i as usize){
|
|
*value += card.count;
|
|
}else{
|
|
next_adds.push_back(card.count);
|
|
}
|
|
}
|
|
debug!("Next bonus: {:?}", next_adds);
|
|
}
|
|
|
|
cards.iter().map(|c| c.count).sum()
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{parse, solve};
|
|
|
|
#[test]
|
|
fn test_line() {
|
|
let line = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53".to_owned();
|
|
|
|
let card = parse(&line);
|
|
assert_eq!(card.value, 8);
|
|
}
|
|
|
|
#[test]
|
|
fn test_part2(){
|
|
let lines = "Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53\nCard 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19\nCard 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1\nCard 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83\nCard 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36\nCard 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11".to_owned();
|
|
let result =solve(lines.lines().map(|v| v.to_owned()).collect(), crate::utils::Part::Two);
|
|
|
|
assert_eq!(result, 30);
|
|
}
|
|
} |