92 lines
2.7 KiB
Rust
92 lines
2.7 KiB
Rust
use crate::day_solver::DaySolver;
|
|
|
|
pub struct Day4 {
|
|
cards: Vec<Card>
|
|
}
|
|
|
|
struct Card {
|
|
// id: u32,
|
|
winning: Vec<u32>,
|
|
having: Vec<u32>
|
|
}
|
|
|
|
impl Card {
|
|
fn win_count(&self) -> usize {
|
|
self.having.iter().filter(|n| self.winning.contains(n)).count()
|
|
}
|
|
fn score(&self) -> u32 {
|
|
let win_count = self.win_count();
|
|
if win_count == 0 { return 0 };
|
|
return 1 << (win_count - 1)
|
|
}
|
|
}
|
|
|
|
impl Day4 {
|
|
|
|
pub fn create(input: String) -> Self {
|
|
let lines = input.lines();
|
|
// let lines = util::read_file("input/dayX.txt");
|
|
|
|
// For performance reasons, let's first figure out the how many winning numbers and "having" numbers we get per card
|
|
let (_, right) = input.lines().next().unwrap().split_once(":").unwrap();
|
|
let (win_str, having_str) = right.split_once("|").unwrap();
|
|
let win_count = win_str.trim().split_whitespace().count();
|
|
let having_count = having_str.trim().split_whitespace().count();
|
|
|
|
// Put the input into the day struct
|
|
return Day4 {
|
|
cards: lines
|
|
.map(|l| {
|
|
let (_, right) = l.split_once(": ").unwrap();
|
|
let (win_str, having_str) = right.split_once("|").unwrap();
|
|
|
|
let mut winning_vec = Vec::with_capacity(win_count + 1);
|
|
winning_vec.extend(win_str.trim().split_whitespace().map(|n| n.parse::<u32>().unwrap()));
|
|
let mut having_vec = Vec::with_capacity(having_count + 1);
|
|
having_vec.extend(having_str.trim().split_whitespace().map(|n| n.parse::<u32>().unwrap()));
|
|
Card {
|
|
// id: left[5..].trim().parse().unwrap(),
|
|
winning: winning_vec,
|
|
having: having_vec
|
|
}
|
|
})
|
|
.collect()
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DaySolver for Day4 {
|
|
|
|
|
|
fn solve_part1(&mut self) -> String {
|
|
return self.cards.iter().map(|c| c.score()).sum::<u32>().to_string()
|
|
}
|
|
|
|
fn solve_part2(&mut self) -> String {
|
|
let mut card_counts: Vec<u32> = vec![1; self.cards.len()];
|
|
card_counts.fill(1);
|
|
|
|
for (i, card) in self.cards.iter().enumerate() {
|
|
let copies = card_counts[i];
|
|
let win_count = card.win_count();
|
|
for j in 0..win_count {
|
|
card_counts[i + j + 1] += copies
|
|
}
|
|
}
|
|
|
|
return card_counts.iter().sum::<u32>().to_string();
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_part1() {
|
|
let mut day = Day4::create("input/day04_example.txt".to_string());
|
|
assert_eq!("13", day.solve_part1());
|
|
}
|
|
|
|
#[test]
|
|
fn test_part2() {
|
|
let mut day = Day4::create("input/day04_example.txt".to_string());
|
|
assert_eq!("30", day.solve_part2());
|
|
}
|