This commit is contained in:
george
2023-12-03 22:54:20 +00:00
commit 51459c17c6
10 changed files with 362 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day03"
version = "0.1.0"
+8
View File
@@ -0,0 +1,8 @@
[package]
name = "day03"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+114
View File
@@ -0,0 +1,114 @@
use std::collections::HashMap;
use std::io::{stdin, BufRead};
type Point = (usize, usize);
const EMPTY_SYMBOL: char = '.';
const GEAR_SYMBOL: char = '*';
const DEFAULT_POINT: Point = (usize::MAX, usize::MAX);
fn main() {
let input = stdin()
.lock()
.lines()
.map(|l| l.unwrap().chars().collect::<Vec<_>>())
.collect::<Vec<_>>();
let mut sum = 0;
let mut gear_surrounding_nums: HashMap<Point, Vec<usize>> = HashMap::new();
for (y, row) in input.iter().enumerate() {
let mut current_num = String::new();
let mut valid = false;
let mut gear_pos = DEFAULT_POINT;
for (x, col) in row.iter().enumerate() {
if col.is_ascii_digit() {
current_num.push(*col);
let points = points_around(x, y);
for point in points {
if let Some(adjacent_symbol) = get_at_point(point.0, point.1, &input) {
if !adjacent_symbol.is_ascii_digit() && adjacent_symbol != &EMPTY_SYMBOL {
valid = true;
}
if adjacent_symbol == &GEAR_SYMBOL {
gear_pos = point;
}
}
}
} else if !current_num.is_empty() {
check_and_update_point(
valid,
&current_num,
&mut sum,
&gear_pos,
&mut gear_surrounding_nums,
);
gear_pos = DEFAULT_POINT;
valid = false;
current_num.clear();
}
}
check_and_update_point(
valid,
&current_num,
&mut sum,
&gear_pos,
&mut gear_surrounding_nums,
);
}
let part2 = gear_surrounding_nums
.iter()
.filter_map(|gear| match gear.1.len() == 2 {
true => Some(gear.1),
_ => None,
})
.fold(0, |total, gear_vals| {
total + gear_vals.iter().product::<usize>()
});
println!("P1: {} P2: {}", sum, part2);
}
fn check_and_update_point(
valid: bool,
current_num: &str,
sum: &mut usize,
gear_pos: &Point,
gear_surrounding_nums: &mut HashMap<Point, Vec<usize>>,
) {
if valid {
let numeric_val = current_num.parse::<usize>().unwrap();
*sum += numeric_val;
if *gear_pos != DEFAULT_POINT {
let gears = gear_surrounding_nums.get_mut(gear_pos);
if let Some(gear_vec) = gears {
gear_vec.push(numeric_val);
} else {
gear_surrounding_nums.insert(*gear_pos, vec![numeric_val]);
}
}
}
}
fn get_at_point(x: usize, y: usize, grid: &[Vec<char>]) -> Option<&char> {
if let Some(row) = grid.get(y) {
return row.get(x);
}
None
}
fn points_around(x: usize, y: usize) -> Vec<Point> {
let mut points = Vec::new();
for i in x.saturating_sub(1)..(x + 2) {
for j in y.saturating_sub(1)..(y + 2) {
if (i, j) == (x, y) {
continue;
}
points.push((i, j));
}
}
points
}