summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2023-12-06 15:01:59 -0600
committerToby Vincent <tobyv@tobyvin.dev>2023-12-06 15:01:59 -0600
commit49c163b6002d7694eec3288e3f4de93067bbe116 (patch)
tree74e9a79bd80a48d8b4e91b9875adcfae178874be
parent49694b1d007bf8489fa581fe4bd23e8f7e0dc592 (diff)
feat: impl day 6
-rw-r--r--input/day_06.txt2
-rw-r--r--src/day_06.rs122
-rw-r--r--src/lib.rs1
-rw-r--r--src/main.rs6
4 files changed, 130 insertions, 1 deletions
diff --git a/input/day_06.txt b/input/day_06.txt
new file mode 100644
index 0000000..45d4be3
--- /dev/null
+++ b/input/day_06.txt
@@ -0,0 +1,2 @@
+Time: 40 82 91 66
+Distance: 277 1338 1349 1063
diff --git a/src/day_06.rs b/src/day_06.rs
new file mode 100644
index 0000000..2b988a3
--- /dev/null
+++ b/src/day_06.rs
@@ -0,0 +1,122 @@
+use crate::{Problem, Solution};
+
+pub struct Day06;
+
+impl Problem for Day06 {
+ const DAY: u8 = 6;
+
+ const INPUT: &'static str = include_str!("../input/day_06.txt");
+}
+
+impl Solution for Day06 {
+ type Answer1 = usize;
+
+ type Answer2 = usize;
+
+ fn part_1(input: &str) -> anyhow::Result<Self::Answer1> {
+ let (time, dist) = input.split_once('\n').expect("Invalid input lines");
+ let races = time
+ .split_whitespace()
+ .skip(1)
+ .zip(dist.split_whitespace().skip(1))
+ .map(TryFrom::try_from)
+ .try_collect::<Vec<Race>>()?;
+
+ races
+ .iter()
+ .map(Race::wins)
+ .reduce(|acc, n| acc * n)
+ .ok_or(anyhow::format_err!("Failed to find race"))
+ }
+
+ fn part_2(input: &str) -> anyhow::Result<Self::Answer2> {
+ let race: Race = input.parse()?;
+ Ok(race.wins())
+ }
+}
+
+#[derive(Debug)]
+struct Race {
+ time: usize,
+ dist: usize,
+}
+
+impl Race {
+ fn run(&self, speed: usize) -> bool {
+ (speed * (self.time - speed)) > self.dist
+ }
+
+ fn wins(&self) -> usize {
+ let mut count = 0;
+ for speed in 1..self.time {
+ if self.run(speed) {
+ count += 1;
+ } else if count > 0 {
+ break;
+ }
+ }
+ count
+ }
+}
+
+impl TryFrom<(&str, &str)> for Race {
+ type Error = std::num::ParseIntError;
+
+ fn try_from((time, dist): (&str, &str)) -> Result<Self, Self::Error> {
+ Ok(Self {
+ time: time.parse()?,
+ dist: dist.parse()?,
+ })
+ }
+}
+
+impl std::str::FromStr for Race {
+ type Err = anyhow::Error;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let (time, dist) = s
+ .trim()
+ .split_once('\n')
+ .ok_or(anyhow::format_err!("Invalid race format"))?;
+
+ let time = time
+ .strip_prefix("Time: ")
+ .ok_or(anyhow::format_err!("Invalid time format"))?
+ .chars()
+ .filter(|c| *c != ' ')
+ .collect::<String>()
+ .trim()
+ .parse()?;
+
+ let dist = dist
+ .strip_prefix("Distance: ")
+ .ok_or(anyhow::format_err!("Invalid distance format"))?
+ .chars()
+ .filter(|c| *c != ' ')
+ .collect::<String>()
+ .trim()
+ .parse()?;
+
+ Ok(Race { time, dist })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ const INPUT: &str = indoc::indoc! {"
+ Time: 7 15 30
+ Distance: 9 40 200
+ "};
+
+ #[test]
+ fn test_part_1() -> anyhow::Result<()> {
+ Ok(assert_eq!(288, Day06::part_1(INPUT)?))
+ }
+
+ #[test]
+ fn test_part_2() -> anyhow::Result<()> {
+ Ok(assert_eq!(71503, Day06::part_2(INPUT)?))
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 7563500..8875ecc 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,6 +6,7 @@ pub mod day_02;
pub mod day_03;
pub mod day_04;
pub mod day_05;
+pub mod day_06;
pub trait Problem {
const DAY: u8;
diff --git a/src/main.rs b/src/main.rs
index feae755..1c93d0a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,7 @@
-use aoc_2023::{day_01::Day01, day_02::Day02, day_03::Day03, day_04::Day04, Solution, day_05::Day05};
+use aoc_2023::{
+ day_01::Day01, day_02::Day02, day_03::Day03, day_04::Day04, day_05::Day05, day_06::Day06,
+ Solution,
+};
fn main() -> anyhow::Result<()> {
Day01::solve()?;
@@ -6,6 +9,7 @@ fn main() -> anyhow::Result<()> {
Day03::solve()?;
Day04::solve()?;
Day05::solve()?;
+ Day06::solve()?;
Ok(())
}