1
1
mirror of https://github.com/theoludwig/advent_of_code.git synced 2025-05-18 19:27:51 +02:00

feat: add day 4 - part 2

This commit is contained in:
2023-12-08 09:09:32 +01:00
parent eddd683cdf
commit e0d5fd7b93
3 changed files with 88 additions and 22 deletions

View File

@ -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);
}
}

View File

@ -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));
}