1
1
mirror of https://github.com/theoludwig/advent_of_code.git synced 2025-05-18 19:27:51 +02:00

feat: add day 3 - part 1

This commit is contained in:
2023-12-03 23:38:44 +01:00
parent 0ef3abfb3f
commit 96a0eb6d4d
9 changed files with 355 additions and 0 deletions

108
day_3/src/lib.rs Normal file
View File

@ -0,0 +1,108 @@
#[derive(Debug, PartialEq)]
pub struct NumberPosition {
pub index_start: usize,
pub index_end: usize,
pub value: usize,
}
pub fn get_numbers_positions_from_line(line: &str) -> Vec<NumberPosition> {
let mut result = vec![];
let mut number_string = String::from("");
let mut index_start = 0;
let mut index_end = 0;
for (index_character, character) in line.chars().enumerate() {
if character.is_ascii_digit() {
if number_string.is_empty() {
index_start = index_character;
}
index_end = index_character;
number_string += &character.to_string();
} else if !number_string.is_empty() {
let value: usize = number_string.parse().expect("Should parse as a `usize`");
result.push(NumberPosition {
index_start,
index_end,
value,
});
number_string = String::from("");
index_start = 0;
index_end = 0;
}
}
if !number_string.is_empty() {
let value: usize = number_string.parse().expect("Should parse as a `usize`");
result.push(NumberPosition {
index_start,
index_end,
value,
});
}
result
}
pub fn is_symbol(character: char) -> bool {
!character.is_ascii_digit() && character != '.'
}
pub fn part_1(input: &str) -> usize {
let lines = input.lines().collect::<Vec<&str>>();
lines
.iter()
.enumerate()
.map(|(index_line, &line)| {
get_numbers_positions_from_line(line)
.iter()
.filter(|&number_position| {
let index_start = number_position.index_start.saturating_sub(1);
let index_end = if number_position.index_end + 1 >= line.len() {
line.len().saturating_sub(1)
} else {
number_position.index_end + 1
};
let has_symbol_on_the_left =
line.chars().nth(index_start).is_some_and(is_symbol);
let has_symbol_on_the_right =
line.chars().nth(index_end).is_some_and(is_symbol);
let has_symbol_on_the_top = lines
.get(index_line.saturating_sub(1))
.is_some_and(|&line| {
line.get(index_start..=index_end)
.is_some_and(|value| value.chars().any(is_symbol))
});
let has_symbol_on_the_bottom = lines.get(index_line + 1).is_some_and(|&line| {
line.get(index_start..=index_end)
.is_some_and(|value| value.chars().any(is_symbol))
});
has_symbol_on_the_left
|| has_symbol_on_the_right
|| has_symbol_on_the_top
|| has_symbol_on_the_bottom
})
.map(|matching_number| matching_number.value)
.sum::<usize>()
})
.sum()
}
// pub fn part_2(_input: &str) -> usize {
// 42
// }
#[cfg(test)]
mod day_3_tests {
use super::*;
#[test]
fn test_part_1_example() {
assert_eq!(part_1(include_str!("../input_example_1.txt")), 4361);
}
// #[test]
// fn test_part_2_example() {
// assert_eq!(part_2(include_str!("../input_example_1.txt")), 467835);
// }
}

8
day_3/src/main.rs Normal file
View File

@ -0,0 +1,8 @@
use day_3::part_1;
fn main() {
let input = include_str!("../input.txt");
println!("- Day 3: Gear Ratios -");
println!("Answer Part 1: {}", part_1(input));
// println!("Answer Part 2: {}", part_2(input));
}