This commit is contained in:
Tyler Beckman 2023-12-04 06:42:50 -07:00
parent 2415fd02c2
commit fba8779f72
Signed by: Ty
GPG key ID: 2813440C772555A4
2 changed files with 124 additions and 4 deletions

106
src/day4/mod.rs Normal file
View file

@ -0,0 +1,106 @@
use std::collections::HashMap;
use crate::utils::Day;
#[derive(Debug)]
pub struct Day4 {
pub input: String,
pub acc: usize,
pub cards: HashMap::<usize /* Card # */, Vec<usize> /* (won card indexes) */>
}
impl Day4 {
fn recurse(&mut self, cards: &Vec<usize>) {
for card in cards {
self.acc += 1;
if let Some(won_cards) = self.cards.get(card) {
self.recurse(&won_cards.clone())
}
}
}
}
impl Day for Day4 {
fn part1(&mut self) -> String {
let mut sum = 0usize;
for line in self.input.lines() {
let (winning, numbers) = line.split_once(": ").unwrap().1.split_once(" | ").unwrap();
let winning = winning.split_whitespace().collect::<Vec<_>>();
let mut winning_numbers = Vec::<&str>::new();
for number in numbers.split_whitespace() {
if winning.contains(&number) && !winning_numbers.contains(&number) {
winning_numbers.push(number);
}
}
if winning_numbers.len() != 0 {
sum += winning_numbers.iter().skip(1).fold(1usize, |acc, _| acc * 2);
}
}
sum.to_string()
}
fn part2(&mut self) -> String {
self.cards = HashMap::<usize /* Card # */, Vec<usize> /* won card indexes */>::new();
for (i, line) in self.input.lines().enumerate() {
let (winning, numbers) = line.split_once(": ").unwrap().1.split_once(" | ").unwrap();
let winning = winning.split_whitespace().collect::<Vec<_>>();
let mut winning_numbers = Vec::<&str>::new();
for number in numbers.split_whitespace() {
if winning.contains(&number) && !winning_numbers.contains(&number) {
winning_numbers.push(number);
}
}
self.cards.insert(i + 1, winning_numbers.into_iter().enumerate().map(|(j, _)| (i + 1) + (j + 1)).collect());
}
self.recurse(&self.cards.keys().map(|e| *e).collect::<Vec<_>>());
self.acc.to_string()
}
}
#[cfg(test)]
mod tests {
use std::collections::HashMap;
use crate::{day4::Day4, utils::Day};
#[test]
fn passes_example_1() {
dbg!(Day4 {
input: r#"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"#
.to_string(),
acc: 0usize,
cards: HashMap::new()
}
.solve(1));
}
#[test]
fn passes_example_2() {
dbg!(Day4 {
input: r#"Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11"#
.to_string(),
acc: 0usize,
cards: HashMap::new()
}
.solve(2));
}
}

View file

@ -1,15 +1,16 @@
use std::{ use std::{
io::Write, io::Write,
time::{Duration, Instant}, time::{Duration, Instant}, collections::HashMap,
}; };
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use crate::{day1::Day1, day2::Day2, day3::Day3, utils::Day}; use crate::{day1::Day1, day2::Day2, day3::Day3, utils::Day, day4::Day4};
pub mod day1; pub mod day1;
pub mod day2; pub mod day2;
pub mod day3; pub mod day3;
pub mod day4;
pub mod utils; pub mod utils;
#[derive(Parser)] #[derive(Parser)]
@ -76,13 +77,25 @@ async fn main() {
games: vec![], games: vec![],
}), }),
3 => Box::new(Day3 { input: response }), 3 => Box::new(Day3 { input: response }),
4 => Box::new(Day4 { input: response, acc: 0usize, cards: HashMap::new() }),
_ => panic!("Invalid day #"), _ => panic!("Invalid day #"),
}; };
let start = std::time::Instant::now(); let start = std::time::Instant::now();
let result = day.solve(part); let result = day.solve(part);
let end = std::time::Instant::now(); let end = std::time::Instant::now();
println!("Solution: {result}"); println!("Solution: {result}");
println!("Solved in {}ns", (end - start).as_nanos() as f64 / 1000.0);
let timing = (end - start).as_nanos();
let (timing, timing_units) = if timing >= 1000000000 {
(timing as f64 / 1000000000.0, "s")
} else if timing >= 1000000 {
(timing as f64 / 1000000.0, "ms")
} else if timing >= 1000 {
(timing as f64 / 1000.0, "µs")
} else {
(timing as f64, "ns")
};
println!("Solved in {timing}{timing_units}");
} }
Subcommands::Benchmark { Subcommands::Benchmark {
day, day,
@ -109,6 +122,7 @@ async fn main() {
games: vec![], games: vec![],
}), }),
3 => Box::new(Day3 { input: response }), 3 => Box::new(Day3 { input: response }),
4 => Box::new(Day4 { input: response, acc: 0usize, cards: HashMap::new() }),
_ => panic!("Invalid day #"), _ => panic!("Invalid day #"),
}; };
let mut timings = Vec::<Duration>::new(); let mut timings = Vec::<Duration>::new();