This commit is contained in:
Pascal Phelipot 2023-12-01 19:44:53 +01:00
commit 83cb093d0a
7 changed files with 1121 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "advent_of_code_2023"
version = "0.1.0"

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "advent_of_code_2023"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

File diff suppressed because it is too large Load Diff

63
src/day1/mod.rs Normal file
View File

@ -0,0 +1,63 @@
pub enum PART {
ONE,
TWO
}
fn line_to_calibration_part1(line: &str) -> (Option<u32>, Option<u32>) {
let a = line.chars().find(|c| c.is_ascii_digit()).expect("Could not find a valid number from the left").to_digit(10);
let b = line.chars().rev().find(|c| c.is_ascii_digit()).expect("Could not find a valid number from the right").to_digit(10);
(a, b)
}
fn line_to_calibration_part2(line: &str) -> (Option<u32>, Option<u32>) {
let digits_words = &["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"];
let mut a: Option<u32> = None;
let mut b: Option<u32> = None;
'search: for i in 0..line.len() {
let (_, remaining_line) = line.split_at(i);
for (j, word) in digits_words.iter().enumerate() {
if remaining_line.starts_with(word) {
a = Some(j as u32 + 1);
break 'search;
}else if let Some(char) = remaining_line.chars().next() && char.is_numeric() {
a = char.to_digit(10);
break 'search;
}
}
}
'search: for i in 0..line.len() {
let (remaining_line, _) = line.split_at(line.len() - i);
for (j, word) in digits_words.iter().enumerate() {
if remaining_line.ends_with(word) {
b = Some(j as u32 + 1);
break 'search;
}else if let Some(char) = remaining_line.chars().last() && char.is_numeric() {
b = char.to_digit(10);
break 'search;
}
}
}
(a,b)
}
pub fn solve(lines: Vec<String>, part: self::PART) -> u32 {
let mut sum = 0;
for line in lines.iter() {
let (a, b) = match part {
PART::ONE => line_to_calibration_part1(line),
PART::TWO => line_to_calibration_part2(line)
};
if let (Some(a), Some(b)) = (a, b) {
sum += a * 10 + b;
}
}
sum
}

30
src/main.rs Normal file
View File

@ -0,0 +1,30 @@
#![feature(let_chains)]
mod day1;
mod utils;
fn main() {
let day1_data_path = "./datasets/adventofcode.com_2023_day_1_input.txt";
let day1_result_part1 = day1::solve(utils::lines_from_file(day1_data_path).expect("Could not load the dataset for day 1"), day1::PART::ONE);
let day1_result_part2 = day1::solve(utils::lines_from_file(day1_data_path).expect("Could not load the dataset for day 1"), day1::PART::TWO);
println!("Day 1 (part 1) result is {}", day1_result_part1);
println!("Day 1 (part 2) result is {}", day1_result_part2);
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn day1() {
let day1_data_path = "./datasets/adventofcode.com_2023_day_1_input.txt";
let day1_result_part1 = day1::solve(utils::lines_from_file(day1_data_path).expect("Could not load the dataset for day 1"), day1::PART::ONE);
let day1_result_part2 = day1::solve(utils::lines_from_file(day1_data_path).expect("Could not load the dataset for day 1"), day1::PART::TWO);
assert_eq!(day1_result_part1, 54338);
assert_eq!(day1_result_part2, 53389);
}
}

12
src/utils.rs Normal file
View File

@ -0,0 +1,12 @@
use std::{
fs::File,
io::{prelude::*, BufReader,Result},
path::Path,
};
pub fn lines_from_file(filename: impl AsRef<Path>) -> Result<Vec<String>> {
let file = File::open(filename)?;
let buf = BufReader::new(file);
buf.lines().collect()
}