adventofcode23/src/day3.rs
2023-12-12 04:07:01 +01:00

109 lines
2.6 KiB
Rust

//! Day 3: Gear Ratios
use std::collections::{HashMap, HashSet};
use itertools::Itertools;
use once_cell::sync::Lazy;
use regex::Regex;
use crate::util::grid::{NeighborsCfg, Pos};
pub const DAY: u8 = 3;
pub const TITLE: &str = "Gear Ratios";
const NCFG: NeighborsCfg = NeighborsCfg {
diag: true,
tl: Some(Pos::usize(0, 0)),
br: None,
};
static NUMBERS: Lazy<Regex> = Lazy::new(|| Regex::new(r"\d+").unwrap());
pub fn part1(input: Vec<String>) -> String {
let mut symbol_neighbors = HashSet::new();
for (y, line) in input.iter().enumerate() {
for (x, c) in line.chars().enumerate() {
if c != '.' && c.is_ascii_punctuation() {
let p = Pos::usize(x, y);
p.neighbors(&NCFG).for_each(|p| {
symbol_neighbors.insert(p);
});
}
}
}
let mut sum = 0;
for (y, line) in input.iter().enumerate() {
for m in NUMBERS.captures_iter(line) {
let m = m.get(0).unwrap();
for x in m.range() {
let p = Pos::usize(x, y);
if symbol_neighbors.contains(&p) {
sum += m.as_str().parse::<u64>().unwrap();
break;
}
}
}
}
sum.to_string()
}
pub fn part2(input: Vec<String>) -> String {
let mut numbers = HashMap::new();
for (y, line) in input.iter().enumerate() {
for m in NUMBERS.captures_iter(line) {
let m = m.get(0).unwrap();
let n = m.as_str().parse::<u64>().unwrap();
for x in m.range() {
let p = Pos::usize(x, y);
numbers.insert(p, n);
}
}
}
let mut gears = 0;
for (y, line) in input.iter().enumerate() {
for (x, c) in line.chars().enumerate() {
if c == '*' {
let p = Pos::usize(x, y);
let nx = p
.neighbors(&NCFG)
.filter_map(|p| numbers.get(&p))
.dedup()
.collect_vec();
if nx.len() == 2 {
gears += nx[0] * nx[1];
}
}
}
}
gears.to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn t_example1() {
assert_eq!(part1(crate::read_example(DAY, 1)), "4361");
}
#[test]
fn t_part1() {
assert_eq!(part1(crate::read_input(DAY)), "520135");
}
#[test]
fn t_example2() {
assert_eq!(part2(crate::read_example(DAY, 2)), "467835");
}
#[test]
fn t_part2() {
assert_eq!(part2(crate::read_input(DAY)), "72514855");
}
}