109 lines
2.7 KiB
Rust
109 lines
2.7 KiB
Rust
advent_of_code::solution!(4);
|
|
|
|
use std::collections::HashSet;
|
|
|
|
struct Card {
|
|
id: usize,
|
|
winning: HashSet<u32>,
|
|
present: HashSet<u32>,
|
|
}
|
|
|
|
impl Card {
|
|
fn matching_numbers(&self) -> Vec<&u32> {
|
|
self.winning
|
|
.intersection(&self.present)
|
|
.collect::<Vec<&u32>>()
|
|
}
|
|
}
|
|
|
|
fn parse(input: &str) -> Vec<Card> {
|
|
input
|
|
.lines()
|
|
.filter_map(|line| {
|
|
if !line.is_empty() {
|
|
let cparts: Vec<&str> = line.split(": ").collect();
|
|
let id = cparts[0]
|
|
.split(" ")
|
|
.collect::<Vec<&str>>()
|
|
.last()?
|
|
.trim_start()
|
|
.parse::<usize>()
|
|
.unwrap();
|
|
let cnums: Vec<&str> = cparts[1].split(" | ").collect();
|
|
let winning: HashSet<u32> = cnums[0]
|
|
.replace(" ", " ")
|
|
.trim_start()
|
|
.split(" ")
|
|
.map(|n| n.parse::<u32>().unwrap())
|
|
.collect();
|
|
let present: HashSet<u32> = cnums[1]
|
|
.replace(" ", " ")
|
|
.trim_start()
|
|
.split(" ")
|
|
.map(|n| n.parse::<u32>().unwrap())
|
|
.collect();
|
|
Some(Card {
|
|
id,
|
|
winning,
|
|
present,
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
pub fn part_one(input: &str) -> Option<u32> {
|
|
let mut sum = 0;
|
|
let base: i32 = 2;
|
|
for c in parse(input).iter() {
|
|
let m = c.matching_numbers();
|
|
if m.is_empty() {
|
|
continue;
|
|
}
|
|
let p = base.pow(m.len() as u32 - 1);
|
|
if m.len() > 0 {
|
|
sum += p;
|
|
}
|
|
}
|
|
Some(sum.try_into().unwrap())
|
|
}
|
|
|
|
pub fn part_two(input_str: &str) -> Option<u32> {
|
|
let mut cards: [u32; 202] = [1; 202];
|
|
let input = parse(input_str);
|
|
for i in input.len()..cards.len() {
|
|
cards[i] = 0;
|
|
}
|
|
for c in input.iter() {
|
|
let m = c.matching_numbers();
|
|
let cur = c.id - 1;
|
|
for i in 1..=m.len() {
|
|
let dest = cur + i;
|
|
if dest >= input.len() {
|
|
continue;
|
|
}
|
|
cards[dest] += cards[cur];
|
|
}
|
|
}
|
|
Some(cards.iter().sum())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_part_one() {
|
|
let result = part_one(&advent_of_code::template::read_file("examples", DAY));
|
|
assert_eq!(result, Some(13));
|
|
}
|
|
|
|
#[test]
|
|
fn test_part_two() {
|
|
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
|
|
assert_eq!(result, Some(30));
|
|
}
|
|
}
|