Day 4
This commit is contained in:
parent
2415fd02c2
commit
fba8779f72
2 changed files with 124 additions and 4 deletions
106
src/day4/mod.rs
Normal file
106
src/day4/mod.rs
Normal 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));
|
||||
}
|
||||
}
|
22
src/main.rs
22
src/main.rs
|
@ -1,15 +1,16 @@
|
|||
use std::{
|
||||
io::Write,
|
||||
time::{Duration, Instant},
|
||||
time::{Duration, Instant}, collections::HashMap,
|
||||
};
|
||||
|
||||
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 day2;
|
||||
pub mod day3;
|
||||
pub mod day4;
|
||||
pub mod utils;
|
||||
|
||||
#[derive(Parser)]
|
||||
|
@ -76,13 +77,25 @@ async fn main() {
|
|||
games: vec![],
|
||||
}),
|
||||
3 => Box::new(Day3 { input: response }),
|
||||
4 => Box::new(Day4 { input: response, acc: 0usize, cards: HashMap::new() }),
|
||||
_ => panic!("Invalid day #"),
|
||||
};
|
||||
let start = std::time::Instant::now();
|
||||
let result = day.solve(part);
|
||||
let end = std::time::Instant::now();
|
||||
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 {
|
||||
day,
|
||||
|
@ -109,6 +122,7 @@ async fn main() {
|
|||
games: vec![],
|
||||
}),
|
||||
3 => Box::new(Day3 { input: response }),
|
||||
4 => Box::new(Day4 { input: response, acc: 0usize, cards: HashMap::new() }),
|
||||
_ => panic!("Invalid day #"),
|
||||
};
|
||||
let mut timings = Vec::<Duration>::new();
|
||||
|
@ -121,7 +135,7 @@ async fn main() {
|
|||
day.solve(part);
|
||||
let end = Instant::now();
|
||||
timings.push(end - start);
|
||||
|
||||
|
||||
print!("\r{:.2}%", (i as f32 / n as f32) * 100.0);
|
||||
let _ = std::io::stdout().flush();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue