summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorToby Vincent <tobyv@tobyvin.dev>2023-12-01 18:17:33 -0600
committerToby Vincent <tobyv@tobyvin.dev>2023-12-01 18:17:33 -0600
commit8525793927ad76a5ffa4a5f522b9a80c1a637644 (patch)
tree3b502ed3f841ac3e7498f8c4c802b86effeb97a2 /src
feat: impl day 1
Diffstat (limited to 'src')
-rw-r--r--src/day_01.rs103
-rw-r--r--src/lib.rs27
-rw-r--r--src/main.rs7
3 files changed, 137 insertions, 0 deletions
diff --git a/src/day_01.rs b/src/day_01.rs
new file mode 100644
index 0000000..9c0310e
--- /dev/null
+++ b/src/day_01.rs
@@ -0,0 +1,103 @@
+use anyhow::Context;
+
+use crate::{Problem, Solution};
+
+pub struct Day01;
+
+impl Problem for Day01 {
+ const DAY: u8 = 1;
+
+ const INPUT: &'static str = include_str!("../input/day_01.txt");
+}
+
+impl Solution for Day01 {
+ type Answer1 = usize;
+
+ type Answer2 = usize;
+
+ fn part_1(input: &str) -> anyhow::Result<Self::Answer1> {
+ input.trim().split('\n').try_fold(0, |acc, line| {
+ let first = line
+ .chars()
+ .find_map(|c| c.to_digit(10).map(|n| n as usize))
+ .context("Failed to find first number")?;
+
+ let last = line
+ .chars()
+ .rev()
+ .find_map(|c| c.to_digit(10).map(|n| n as usize))
+ .unwrap_or(first);
+
+ Ok(acc + first * 10 + last)
+ })
+ }
+
+ fn part_2(input: &str) -> anyhow::Result<Self::Answer2> {
+ let words = [
+ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
+ ];
+
+ input.trim().split('\n').try_fold(0, |acc, line| {
+ let mut buf = String::new();
+ let first = line
+ .chars()
+ .find_map(|c| {
+ buf.push(c);
+ words
+ .iter()
+ .enumerate()
+ .find_map(|(n, w)| buf.contains(w).then_some(n))
+ .or_else(|| c.to_digit(10).map(|n| n as usize))
+ })
+ .context("Failed to find first number")?;
+
+ buf.clear();
+ let last = line
+ .chars()
+ .rev()
+ .find_map(|c| {
+ buf.insert(0, c);
+ words
+ .iter()
+ .enumerate()
+ .find_map(|(n, w)| buf.contains(w).then_some(n))
+ .or_else(|| c.to_digit(10).map(|n| n as usize))
+ })
+ .unwrap_or(first);
+
+ Ok(acc + first * 10 + last)
+ })
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_part_1() -> anyhow::Result<()> {
+ let input = indoc::indoc! {"
+ 1abc2
+ pqr3stu8vwx
+ a1b2c3d4e5f
+ treb7uchet
+ "};
+
+ Ok(assert_eq!(142, Day01::part_1(input)?))
+ }
+
+ #[test]
+ fn test_part_2() -> anyhow::Result<()> {
+ let input = indoc::indoc! {"
+ two1nine
+ eightwothree
+ abcone2threexyz
+ xtwone3four
+ 4nineeightseven2
+ zoneight234
+ 7pqrstsixteen
+ "};
+
+ Ok(assert_eq!(281, Day01::part_2(input)?))
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..a895a9d
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,27 @@
+pub mod day_01;
+
+pub trait Solution: Problem {
+ type Answer1: std::fmt::Display + Default;
+
+ type Answer2: std::fmt::Display + Default;
+
+ fn part_1(input: &str) -> anyhow::Result<Self::Answer1>;
+
+ fn part_2(input: &str) -> anyhow::Result<Self::Answer2>;
+
+ fn solve() -> anyhow::Result<()> {
+ println!("Day {}.1", Self::DAY);
+ println!("{}\n", Self::part_1(Self::INPUT)?);
+
+ println!("Day {}.2", Self::DAY);
+ println!("{}\n", Self::part_2(Self::INPUT)?);
+
+ Ok(())
+ }
+}
+
+pub trait Problem {
+ const DAY: u8;
+
+ const INPUT: &'static str;
+}
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..689a756
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,7 @@
+use aoc_2023::{day_01::Day01, Solution};
+
+fn main() -> anyhow::Result<()> {
+ Day01::solve()?;
+
+ Ok(())
+}