mirror of
				https://github.com/theoludwig/advent_of_code.git
				synced 2025-09-11 23:11:18 +02:00 
			
		
		
		
	feat: add day 4 - part 2
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
use std::cmp;
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default, PartialEq)]
 | 
			
		||||
#[derive(Debug, Default, PartialEq, Clone)]
 | 
			
		||||
pub struct CardNumbers {
 | 
			
		||||
    pub numbers: Vec<u32>,
 | 
			
		||||
}
 | 
			
		||||
@@ -41,11 +42,10 @@ impl FromStr for CardNumbers {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Debug, Default, PartialEq)]
 | 
			
		||||
#[derive(Debug, Default, PartialEq, Clone)]
 | 
			
		||||
pub struct Card {
 | 
			
		||||
    pub id: usize,
 | 
			
		||||
    pub winning_numbers: CardNumbers,
 | 
			
		||||
    pub owned_numbers: CardNumbers,
 | 
			
		||||
    pub winning_numbers_count: usize,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl FromStr for Card {
 | 
			
		||||
@@ -66,8 +66,7 @@ impl FromStr for Card {
 | 
			
		||||
    /// let string = "Card 1: 41 48 83 86 17 | 83 86  6 31 17  9 48 53";
 | 
			
		||||
    /// let expected_result = Card {
 | 
			
		||||
    ///     id: 1,
 | 
			
		||||
    ///     winning_numbers: CardNumbers { numbers: vec![41, 48, 83, 86, 17], },
 | 
			
		||||
    ///     owned_numbers: CardNumbers { numbers: vec![83, 86, 6, 31, 17, 9, 48, 53], },
 | 
			
		||||
    ///     winning_numbers_count: 4,
 | 
			
		||||
    /// };
 | 
			
		||||
    /// let actual_result = Card::from_str(string).unwrap();
 | 
			
		||||
    ///
 | 
			
		||||
@@ -81,16 +80,23 @@ impl FromStr for Card {
 | 
			
		||||
            .unwrap_or("Card 1")
 | 
			
		||||
            .strip_prefix("Card ")
 | 
			
		||||
            .unwrap_or("1")
 | 
			
		||||
            .trim()
 | 
			
		||||
            .parse()
 | 
			
		||||
            .unwrap_or(1);
 | 
			
		||||
 | 
			
		||||
        let mut numbers_parts = parts.next().unwrap_or("").split(" | ");
 | 
			
		||||
 | 
			
		||||
        result.winning_numbers =
 | 
			
		||||
        let winning_numbers =
 | 
			
		||||
            CardNumbers::from_str(numbers_parts.next().unwrap_or("")).unwrap_or_default();
 | 
			
		||||
        result.owned_numbers =
 | 
			
		||||
        let owned_numbers =
 | 
			
		||||
            CardNumbers::from_str(numbers_parts.next().unwrap_or("")).unwrap_or_default();
 | 
			
		||||
 | 
			
		||||
        result.winning_numbers_count = owned_numbers
 | 
			
		||||
            .numbers
 | 
			
		||||
            .iter()
 | 
			
		||||
            .filter(|&owned_number| winning_numbers.numbers.contains(owned_number))
 | 
			
		||||
            .count();
 | 
			
		||||
 | 
			
		||||
        Ok(result)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -100,15 +106,10 @@ pub fn part_1(input: &str) -> usize {
 | 
			
		||||
        .lines()
 | 
			
		||||
        .map(|line| Card::from_str(line).unwrap_or_default())
 | 
			
		||||
        .map(|card| {
 | 
			
		||||
            let numbers_matches_count = card
 | 
			
		||||
                .owned_numbers
 | 
			
		||||
                .numbers
 | 
			
		||||
                .iter()
 | 
			
		||||
                .filter(|&owned_number| card.winning_numbers.numbers.contains(owned_number))
 | 
			
		||||
                .count() as u32;
 | 
			
		||||
            let winning_numbers_count = card.winning_numbers_count as u32;
 | 
			
		||||
            let base: usize = 2;
 | 
			
		||||
            if numbers_matches_count > 0 {
 | 
			
		||||
                base.pow(numbers_matches_count.saturating_sub(1))
 | 
			
		||||
            if winning_numbers_count > 0 {
 | 
			
		||||
                base.pow(winning_numbers_count.saturating_sub(1))
 | 
			
		||||
            } else {
 | 
			
		||||
                0
 | 
			
		||||
            }
 | 
			
		||||
@@ -116,6 +117,36 @@ pub fn part_1(input: &str) -> usize {
 | 
			
		||||
        .sum::<usize>()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn part_2(input: &str) -> usize {
 | 
			
		||||
    let cards = input
 | 
			
		||||
        .lines()
 | 
			
		||||
        .map(|line| Card::from_str(line).unwrap_or_default())
 | 
			
		||||
        .collect::<Vec<Card>>();
 | 
			
		||||
    let mut cards_identifiers = cards.iter().map(|card| card.id).collect::<Vec<usize>>();
 | 
			
		||||
 | 
			
		||||
    let mut index_card = 0;
 | 
			
		||||
    loop {
 | 
			
		||||
        if index_card >= cards_identifiers.len() {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if let Some(card) = cards.get(cards_identifiers.get(index_card).unwrap_or(&0) - 1) {
 | 
			
		||||
            let card_position_index = card.id - 1;
 | 
			
		||||
            let maximum_index = cmp::min(
 | 
			
		||||
                card_position_index + card.winning_numbers_count,
 | 
			
		||||
                cards.len() - 1,
 | 
			
		||||
            );
 | 
			
		||||
            for index in card_position_index + 1..=maximum_index {
 | 
			
		||||
                cards_identifiers.push(index + 1);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        index_card += 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cards_identifiers.len()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod day_4_tests {
 | 
			
		||||
    use super::*;
 | 
			
		||||
@@ -125,8 +156,8 @@ mod day_4_tests {
 | 
			
		||||
        assert_eq!(part_1(include_str!("../input_example_1.txt")), 13);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // #[test]
 | 
			
		||||
    // fn test_part_2_example() {
 | 
			
		||||
    //     assert_eq!(part_2(include_str!("../input_example_1.txt")), 467835);
 | 
			
		||||
    // }
 | 
			
		||||
    #[test]
 | 
			
		||||
    fn test_part_2_example() {
 | 
			
		||||
        assert_eq!(part_2(include_str!("../input_example_1.txt")), 30);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
use day_4::part_1;
 | 
			
		||||
use day_4::{part_1, part_2};
 | 
			
		||||
 | 
			
		||||
fn main() {
 | 
			
		||||
    let input = include_str!("../input.txt");
 | 
			
		||||
    println!("- Day 4: Scratchcards -");
 | 
			
		||||
    println!("Answer Part 1: {}", part_1(input));
 | 
			
		||||
    // println!("Answer Part 2: {}", part_2(input));
 | 
			
		||||
    println!("Answer Part 2: {}", part_2(input));
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user