1
1
mirror of https://github.com/theoludwig/advent_of_code_2023.git synced 2024-10-29 22:17:19 +01:00

feat: add day 3 - part 2

This commit is contained in:
Théo LUDWIG 2023-12-08 18:29:27 +01:00
parent 96a0eb6d4d
commit cee59608de
Signed by: theoludwig
GPG Key ID: ADFE5A563D718F3B
3 changed files with 120 additions and 12 deletions

View File

@ -72,6 +72,6 @@ In this schematic, there are **two** gears. The first is in the top left; it has
**What is the sum of all of the gear ratios in your engine schematic?** **What is the sum of all of the gear ratios in your engine schematic?**
Your puzzle answer was `answer`. Your puzzle answer was `84363105`.
**Both parts of this puzzle are complete! They provide two gold stars: `**`.** **Both parts of this puzzle are complete! They provide two gold stars: `**`.**

View File

@ -1,8 +1,17 @@
#[derive(Debug, PartialEq)] use std::collections::HashMap;
#[derive(Debug, PartialEq, Default, Clone, Copy)]
pub struct GearPosition {
pub index_line: usize,
pub index_character: usize,
}
#[derive(Debug, PartialEq, Default, Clone, Copy)]
pub struct NumberPosition { pub struct NumberPosition {
pub index_start: usize, pub index_start: usize,
pub index_end: usize, pub index_end: usize,
pub value: usize, pub value: usize,
pub gear_position: GearPosition,
} }
pub fn get_numbers_positions_from_line(line: &str) -> Vec<NumberPosition> { pub fn get_numbers_positions_from_line(line: &str) -> Vec<NumberPosition> {
@ -23,6 +32,7 @@ pub fn get_numbers_positions_from_line(line: &str) -> Vec<NumberPosition> {
index_start, index_start,
index_end, index_end,
value, value,
gear_position: GearPosition::default(),
}); });
number_string = String::from(""); number_string = String::from("");
index_start = 0; index_start = 0;
@ -35,6 +45,7 @@ pub fn get_numbers_positions_from_line(line: &str) -> Vec<NumberPosition> {
index_start, index_start,
index_end, index_end,
value, value,
gear_position: GearPosition::default(),
}); });
} }
result result
@ -44,6 +55,10 @@ pub fn is_symbol(character: char) -> bool {
!character.is_ascii_digit() && character != '.' !character.is_ascii_digit() && character != '.'
} }
pub fn is_gear_symbol(character: char) -> bool {
character == '*'
}
pub fn part_1(input: &str) -> usize { pub fn part_1(input: &str) -> usize {
let lines = input.lines().collect::<Vec<&str>>(); let lines = input.lines().collect::<Vec<&str>>();
lines lines
@ -82,15 +97,108 @@ pub fn part_1(input: &str) -> usize {
|| has_symbol_on_the_top || has_symbol_on_the_top
|| has_symbol_on_the_bottom || has_symbol_on_the_bottom
}) })
.map(|matching_number| matching_number.value) .map(|number_position| number_position.value)
.sum::<usize>() .sum::<usize>()
}) })
.sum() .sum()
} }
// pub fn part_2(_input: &str) -> usize { pub fn part_2(input: &str) -> usize {
// 42 let lines = input.lines().collect::<Vec<&str>>();
// } let mut number_positions = vec![];
lines.iter().enumerate().for_each(|(index_line, &line)| {
get_numbers_positions_from_line(line)
.iter()
.for_each(|&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_gear_symbol);
if has_symbol_on_the_left {
let mut number_position = number_position.to_owned();
number_position.gear_position.index_line = index_line;
number_position.gear_position.index_character = index_start;
number_positions.push(number_position);
}
let has_symbol_on_the_right =
line.chars().nth(index_end).is_some_and(is_gear_symbol);
if has_symbol_on_the_right {
let mut number_position = number_position.to_owned();
number_position.gear_position.index_line = index_line;
number_position.gear_position.index_character = index_end;
number_positions.push(number_position);
}
let index_character_top =
lines.get(index_line.saturating_sub(1)).and_then(|&line| {
line.get(index_start..=index_end)
.and_then(|value| value.chars().position(is_gear_symbol))
});
if let Some(index_character_top) = index_character_top {
let mut number_position = number_position.to_owned();
number_position.gear_position.index_line = index_line.saturating_sub(1);
number_position.gear_position.index_character =
index_character_top + index_start;
number_positions.push(number_position);
}
let index_character_bottom = lines.get(index_line + 1).and_then(|&line| {
line.get(index_start..=index_end)
.and_then(|value| value.chars().position(is_gear_symbol))
});
if let Some(index_character_bottom) = index_character_bottom {
let mut number_position = number_position.to_owned();
number_position.gear_position.index_line = index_line + 1;
number_position.gear_position.index_character =
index_character_bottom + index_start;
number_positions.push(number_position);
}
});
});
// Key: "index_line-index_character"
// Value: usize
let mut gear_positions: HashMap<String, Vec<usize>> = HashMap::new();
number_positions.iter().for_each(|&number_position| {
let key = format!(
"{}-{}",
number_position.gear_position.index_line, number_position.gear_position.index_character,
);
match gear_positions.get_mut(&key) {
Some(gear_positions) => {
gear_positions.push(number_position.value);
}
None => {
gear_positions.insert(key, vec![number_position.value]);
}
}
});
let mut result = 0;
for (_, value) in gear_positions.iter() {
if value.len() != 2 {
continue;
}
let first_number = value.first();
let second_number = value.last();
if let (Some(first_number), Some(second_number)) = (first_number, second_number) {
result += first_number * second_number;
}
}
result
}
#[cfg(test)] #[cfg(test)]
mod day_3_tests { mod day_3_tests {
@ -101,8 +209,8 @@ mod day_3_tests {
assert_eq!(part_1(include_str!("../input_example_1.txt")), 4361); assert_eq!(part_1(include_str!("../input_example_1.txt")), 4361);
} }
// #[test] #[test]
// fn test_part_2_example() { fn test_part_2_example() {
// assert_eq!(part_2(include_str!("../input_example_1.txt")), 467835); assert_eq!(part_2(include_str!("../input_example_1.txt")), 467835);
// } }
} }

View File

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