2023 - Day 04

This commit is contained in:
2023-12-04 11:29:16 +01:00
parent 082d153939
commit 3720115175
3 changed files with 337 additions and 0 deletions

135
2023/src/bin/day04.rs Normal file
View File

@@ -0,0 +1,135 @@
#![feature(test)]
use anyhow::Result;
use aoc::Solver;
// -- Runners --
fn main() -> Result<()> {
Day::solve()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn part1_test1() -> Result<()> {
Day::test(Day::part1, "test-1", 13)
}
#[test]
fn part1_solution() -> Result<()> {
Day::test(Day::part1, "input", 24706)
}
#[test]
fn part2_test1() -> Result<()> {
Day::test(Day::part2, "test-1", 30)
}
#[test]
fn part2_solution() -> Result<()> {
Day::test(Day::part2, "input", 13114317)
}
// Benchmarks
extern crate test;
#[bench]
#[ignore]
fn part1_bench(b: &mut test::Bencher) {
Day::benchmark(Day::part1, b)
}
#[bench]
#[ignore]
fn part2_bench(b: &mut test::Bencher) {
Day::benchmark(Day::part2, b)
}
}
// -- Solution --
pub struct Day;
impl aoc::Solver for Day {
type Output1 = usize;
type Output2 = usize;
fn day() -> u8 {
4
}
fn part1(input: &str) -> Self::Output1 {
// Calculate the score for every game and sum it
input
.lines()
.map(|line| {
// Get rid of the first part
let (_, line) = line
.split_once(": ")
.expect("Input should be formatted properly");
// Seperate the winning numbers and numbers we have
let (winning, numbers) = line
.split_once(" | ")
.expect("Input should be formatted properly");
// Parse the winning numbers
let winning: Vec<_> = winning.split(' ').flat_map(str::parse::<usize>).collect();
// Parse the numbers we have, check if they are a winning number and count the
// amount of winning numbers we have
let count = numbers
.split(' ')
.flat_map(str::parse::<usize>)
.filter(|num| winning.contains(num))
.count();
// Calculate the score
if count > 0 {
return 2_usize.pow(count as u32 - 1);
}
0
})
.sum()
}
fn part2(input: &str) -> Self::Output2 {
// Calculate how many wins we have per game
let wins: Vec<_> = input
.lines()
.map(|line| {
// Get rid of the first part
let (_, line) = line
.split_once(": ")
.expect("Input should be formatted properly");
// Seperate the winning numbers and numbers we have
let (winning, numbers) = line
.split_once(" | ")
.expect("Input should be formatted properly");
// Parse the winning numbers
let winning: Vec<_> = winning.split(' ').flat_map(str::parse::<usize>).collect();
// Parse the numbers we have, check if they are a winning number and count the
// amount of winning numbers we have
numbers
.split(' ')
.flat_map(str::parse::<usize>)
.filter(|num| winning.contains(num))
.count()
})
.collect();
// Start out with one copy of every card
let mut copies = vec![1; wins.len()];
// Keep track of how many copies we get of every card
for (i, win) in wins.iter().enumerate() {
for j in (i + 1)..(i + win + 1) {
// Add the current amount of copies to the card we win
// e.g. we have 2 copies of the current card that has 3 wins, this means we add 2
// to the next 3 cards
copies[j] += copies[i]
}
}
copies.iter().sum()
}
}