From eb9e0e3ed44ea3e4ed5352e7dc476b476c889d8b Mon Sep 17 00:00:00 2001 From: Xiretza Date: Sat, 2 Dec 2023 12:55:16 +0000 Subject: [PATCH] 2023 day1/rust: add solution --- 2023/day1/rust/Cargo.toml | 9 ++++++ 2023/day1/rust/src/main.rs | 65 ++++++++++++++++++++++++++++++++++++++ Cargo.lock | 7 ++++ Cargo.toml | 1 + 4 files changed, 82 insertions(+) create mode 100644 2023/day1/rust/Cargo.toml create mode 100644 2023/day1/rust/src/main.rs diff --git a/2023/day1/rust/Cargo.toml b/2023/day1/rust/Cargo.toml new file mode 100644 index 0000000..fe3921e --- /dev/null +++ b/2023/day1/rust/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust_2023_01" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +aoc = { path = "../../../common/rust" } diff --git a/2023/day1/rust/src/main.rs b/2023/day1/rust/src/main.rs new file mode 100644 index 0000000..24ec2cd --- /dev/null +++ b/2023/day1/rust/src/main.rs @@ -0,0 +1,65 @@ +#![warn(clippy::pedantic)] + +use std::io::stdin; + +const DIGIT_WORDS: [&str; 9] = [ + "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", +]; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Direction { + Forward, + Backward, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum DigitMode { + NumeralsOnly, + NumeralsAndWords, +} + +fn locate_digit(s: &str, direction: Direction, mode: DigitMode) -> usize { + let locate_digit = |n: usize, word| { + let locate = match direction { + Direction::Forward => str::find, + Direction::Backward => str::rfind, + }; + let numeral = n.to_string(); + let numeral_pos = locate(s, numeral.as_str()); + let word_pos = if mode == DigitMode::NumeralsAndWords { + locate(s, word) + } else { + None + }; + [numeral_pos, word_pos].into_iter().flatten() + }; + + let positions = DIGIT_WORDS.into_iter().enumerate().flat_map(|(n, word)| { + let n = n + 1; + locate_digit(n, word).map(move |pos| (pos, n)) + }); + + match direction { + Direction::Forward => positions.min_by_key(|(pos, _)| *pos), + Direction::Backward => positions.max_by_key(|(pos, _)| *pos), + } + .unwrap() + .1 +} + +fn get_number(s: &str, mode: DigitMode) -> usize { + let first = locate_digit(s, Direction::Forward, mode); + let last = locate_digit(s, Direction::Backward, mode); + first * 10 + last +} + +fn get_sum(lines: &[String], mode: DigitMode) -> usize { + lines.iter().map(|l| get_number(l, mode)).sum() +} + +fn main() { + let lines: Vec<_> = stdin().lines().map(Result::unwrap).collect(); + + println!("{}", get_sum(&lines, DigitMode::NumeralsOnly)); + println!("{}", get_sum(&lines, DigitMode::NumeralsAndWords)); +} diff --git a/Cargo.lock b/Cargo.lock index f4aa06b..c654657 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -628,6 +628,13 @@ dependencies = [ "strum", ] +[[package]] +name = "rust_2023_01" +version = "0.1.0" +dependencies = [ + "aoc", +] + [[package]] name = "rustversion" version = "1.0.11" diff --git a/Cargo.toml b/Cargo.toml index 5c9bd9d..4f9841e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,4 +27,5 @@ members = [ "2022/day14/rust", "2022/day15/rust", "2022/day18/rust", + "2023/day1/rust", ]