From 7504eb8d8d30917efcdca549b6e9f4284159548e Mon Sep 17 00:00:00 2001 From: Bauke Date: Sun, 5 Dec 2021 14:02:50 +0100 Subject: [PATCH] Solve day 5! --- source/day_05/mod.rs | 163 +++++++++++++++++++++++++++++++++++++++++++ source/main.rs | 35 +++++++--- 2 files changed, 188 insertions(+), 10 deletions(-) create mode 100644 source/day_05/mod.rs diff --git a/source/day_05/mod.rs b/source/day_05/mod.rs new file mode 100644 index 0000000..1630189 --- /dev/null +++ b/source/day_05/mod.rs @@ -0,0 +1,163 @@ +use std::{collections::HashMap, str::FromStr}; + +use color_eyre::{ + eyre::{eyre, Error}, + Result, +}; + +pub fn solve() -> Result<()> { + let input_data = include_str!("../../data/day_05.txt").trim(); + println!("Day 05 Part 1: {}", part_1(input_data)?); + println!("Day 05 Part 2: {}", part_2(input_data)?); + Ok(()) +} + +#[derive(Debug)] +struct Vector { + a: (isize, isize), + b: (isize, isize), +} + +impl Vector { + fn diagonal_coordinates(&self) -> Vec<(isize, isize)> { + let x_coordinates = { + let x_amount = (self.a.0 - self.b.0).abs(); + if self.a.0 < self.b.0 { + (0..=x_amount) + .into_iter() + .map(|x| self.a.0 + x) + .collect::>() + } else { + (0..=x_amount) + .into_iter() + .map(|x| self.a.0 - x) + .collect::>() + } + }; + + let y_coordinates = { + let y_amount = (self.a.1 - self.b.1).abs(); + if self.a.1 < self.b.1 { + (0..=y_amount) + .into_iter() + .map(|x| self.a.1 + x) + .collect::>() + } else { + (0..=y_amount) + .into_iter() + .map(|x| self.a.1 - x) + .collect::>() + } + }; + + x_coordinates.into_iter().zip(y_coordinates).collect() + } + + fn horizontal_coordinates(&self) -> Vec<(isize, isize)> { + let y = self.a.1; + + let (x1, x2) = if self.a.0 < self.b.0 { + (self.a.0, self.b.0) + } else { + (self.b.0, self.a.0) + }; + + (x1..=x2).into_iter().map(|x| (x, y)).collect() + } + + fn vertical_coordinates(&self) -> Vec<(isize, isize)> { + let x = self.a.0; + + let (y1, y2) = if self.a.1 < self.b.1 { + (self.a.1, self.b.1) + } else { + (self.b.1, self.a.1) + }; + + (y1..=y2).into_iter().map(|y| (x, y)).collect() + } +} + +impl FromStr for Vector { + type Err = Error; + + fn from_str(s: &str) -> Result { + let numbers = s + .replace(" -> ", ",") + .split(",") + .map(str::parse) + .collect::, _>>()?; + + if numbers.len() == 4 { + Ok(Self { + a: (numbers[0], numbers[1]), + b: (numbers[2], numbers[3]), + }) + } else { + Err(eyre!("Invalid input: {}", s)) + } + } +} + +fn part_1(input: &str) -> Result { + let vectors = input + .lines() + .filter_map(|line| { + if let Ok(vector) = Vector::from_str(line) { + if vector.a.0 == vector.b.0 || vector.a.1 == vector.b.1 { + return Some(vector); + } + } + + None + }) + .collect::>(); + + let mut travelled_coordinates = HashMap::<(isize, isize), isize>::new(); + for vector in vectors { + let coordinates = if vector.a.0 == vector.b.0 { + vector.vertical_coordinates() + } else { + vector.horizontal_coordinates() + }; + + for coordinate in coordinates { + let amount = travelled_coordinates.entry(coordinate).or_default(); + *amount += 1; + } + } + + Ok(count_result(travelled_coordinates)) +} + +fn part_2(input: &str) -> Result { + let vectors = input + .lines() + .map(str::parse) + .collect::>>()?; + + let mut travelled_coordinates = HashMap::<(isize, isize), isize>::new(); + for vector in vectors { + let coordinates = if vector.a.0 == vector.b.0 { + vector.vertical_coordinates() + } else if vector.a.1 == vector.b.1 { + vector.horizontal_coordinates() + } else { + vector.diagonal_coordinates() + }; + + for coordinate in coordinates { + let amount = travelled_coordinates.entry(coordinate).or_default(); + *amount += 1; + } + } + + Ok(count_result(travelled_coordinates)) +} + +fn count_result(coordinates: HashMap<(isize, isize), isize>) -> usize { + coordinates + .into_iter() + .filter(|(_, amount)| amount >= &2) + .count() +} diff --git a/source/main.rs b/source/main.rs index fb2165c..376bdd0 100644 --- a/source/main.rs +++ b/source/main.rs @@ -1,23 +1,38 @@ -use std::time::Instant; +use std::time::{Duration, Instant}; + +use color_eyre::Result; mod day_01; mod day_02; mod day_03; mod day_04; +mod day_05; -fn main() -> color_eyre::Result<()> { +fn main() -> Result<()> { color_eyre::install()?; + println!("Advent of Code 2021\n"); - println!("Advent of Code 2021"); - let start = Instant::now(); + let mut runtimes = vec![]; + let days: Vec Result<()>> = vec![ + day_01::solve, + day_02::solve, + day_03::solve, + day_04::solve, + day_05::solve, + ]; - day_01::solve()?; - day_02::solve()?; - day_03::solve()?; - day_04::solve()?; + for day in days { + let start = Instant::now(); + day()?; + let runtime = Instant::now() - start; + runtimes.push(runtime); + println!("- Runtime: {:#?}\n", runtime); + } - let end = Instant::now(); - println!("Runtime: {:#?}", end - start); + println!( + "Total runtime: {:#?}", + runtimes.into_iter().sum::() + ); Ok(()) }