Solve day 5!
This commit is contained in:
parent
29e1032ce6
commit
7504eb8d8d
|
@ -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::<Vec<_>>()
|
||||
} else {
|
||||
(0..=x_amount)
|
||||
.into_iter()
|
||||
.map(|x| self.a.0 - x)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
};
|
||||
|
||||
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::<Vec<_>>()
|
||||
} else {
|
||||
(0..=y_amount)
|
||||
.into_iter()
|
||||
.map(|x| self.a.1 - x)
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
};
|
||||
|
||||
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<Self, Self::Err> {
|
||||
let numbers = s
|
||||
.replace(" -> ", ",")
|
||||
.split(",")
|
||||
.map(str::parse)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
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<usize> {
|
||||
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::<Vec<_>>();
|
||||
|
||||
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<usize> {
|
||||
let vectors = input
|
||||
.lines()
|
||||
.map(str::parse)
|
||||
.collect::<Result<Vec<Vector>>>()?;
|
||||
|
||||
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()
|
||||
}
|
|
@ -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 mut runtimes = vec![];
|
||||
let days: Vec<fn() -> Result<()>> = vec![
|
||||
day_01::solve,
|
||||
day_02::solve,
|
||||
day_03::solve,
|
||||
day_04::solve,
|
||||
day_05::solve,
|
||||
];
|
||||
|
||||
for day in days {
|
||||
let start = Instant::now();
|
||||
day()?;
|
||||
let runtime = Instant::now() - start;
|
||||
runtimes.push(runtime);
|
||||
println!("- Runtime: {:#?}\n", runtime);
|
||||
}
|
||||
|
||||
day_01::solve()?;
|
||||
day_02::solve()?;
|
||||
day_03::solve()?;
|
||||
day_04::solve()?;
|
||||
|
||||
let end = Instant::now();
|
||||
println!("Runtime: {:#?}", end - start);
|
||||
println!(
|
||||
"Total runtime: {:#?}",
|
||||
runtimes.into_iter().sum::<Duration>()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue