Created
December 3, 2023 14:02
-
-
Save typester/29ff2ce835f14f89503456af0677997c to your computer and use it in GitHub Desktop.
2023 Advent of Code Day 3
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::collections::HashMap; | |
const INPUT: &str = "..snip.."; | |
#[derive(Debug)] | |
struct Info { | |
symbol_map: Vec<Vec<bool>>, | |
numbers: Vec<Number>, | |
} | |
enum SymbolType { | |
Any, | |
Gear, | |
} | |
#[derive(Debug)] | |
struct Number { | |
num: u32, | |
x: usize, | |
y: usize, | |
len: usize, | |
} | |
fn main() { | |
let info = parse_input(INPUT, SymbolType::Any); | |
let sum: u32 = info.numbers.iter().fold(0, |mut acc, n| { | |
if n.has_symbol(&info.symbol_map) { | |
acc += n.num; | |
} | |
acc | |
}); | |
println!("part1: {}", sum); | |
let info = parse_input(INPUT, SymbolType::Gear); | |
let gear_map: HashMap<String, Vec<u32>> = info.numbers.iter().fold(HashMap::new(), |mut acc, n| { | |
for gear_addr in n.symbol_addrs(&info.symbol_map).iter() { | |
acc.entry(gear_addr.into()).or_insert(vec![]).push(n.num); | |
} | |
acc | |
}); | |
let sum = gear_map.iter().fold(0, |mut acc, (_addr, nums)| { | |
if nums.len() == 2 { | |
acc += nums[0] * nums[1]; | |
} | |
acc | |
}); | |
println!("part2: {}", sum); | |
} | |
fn parse_input(input: &str, symbol_type: SymbolType) -> Info { | |
#[derive(Debug, Default)] | |
struct ParseInfo { | |
symbol_map: Vec<Vec<bool>>, | |
numbers: Vec<Number>, | |
x: usize, | |
y: usize, | |
number_buf: String, | |
number_x: usize, | |
number_y: usize, | |
} | |
let parse_info = input.lines().fold(ParseInfo::default(), |mut acc, line| { | |
acc.symbol_map.push(vec![]); | |
acc.x = 0; | |
for c in line.chars() { | |
if c.is_numeric() { | |
if acc.number_buf == "" { | |
acc.number_x = acc.x; | |
acc.number_y = acc.symbol_map.len() - 1; | |
} | |
acc.number_buf.push(c); | |
acc.symbol_map[acc.y].push(false); | |
} else { | |
if acc.number_buf != "" { | |
let n = Number { | |
num: acc.number_buf.parse::<u32>().unwrap(), | |
x: acc.number_x, | |
y: acc.number_y, | |
len: acc.number_buf.len(), | |
}; | |
acc.numbers.push(n); | |
acc.number_buf.clear() | |
} | |
match symbol_type { | |
SymbolType::Any => | |
acc.symbol_map[acc.y].push(c != '.'), | |
SymbolType::Gear => | |
acc.symbol_map[acc.y].push(c == '*'), | |
} | |
} | |
acc.x += 1; | |
} | |
acc.y += 1; | |
acc | |
}); | |
Info { | |
symbol_map: parse_info.symbol_map, | |
numbers: parse_info.numbers, | |
} | |
} | |
impl Number { | |
fn has_symbol(&self, symbol_map: &Vec<Vec<bool>>) -> bool { | |
let start_y = if self.y > 0 { self.y - 1 } else { self.y }; | |
let start_x = if self.x > 0 { self.x - 1 } else { self.x }; | |
for y in start_y ..= self.y + 1 { | |
if symbol_map.len() <= y { continue } | |
for x in start_x ..= self.x + self.len { | |
if symbol_map[y].len() <= x { continue } | |
if symbol_map[y][x] { | |
return true | |
} | |
} | |
} | |
false | |
} | |
fn symbol_addrs(&self, symbol_map: &Vec<Vec<bool>>) -> Vec<String> { | |
let mut addrs: Vec<String> = vec![]; | |
let start_y = if self.y > 0 { self.y - 1 } else { self.y }; | |
let start_x = if self.x > 0 { self.x - 1 } else { self.x }; | |
for y in start_y ..= self.y + 1 { | |
if symbol_map.len() <= y { continue } | |
for x in start_x ..= self.x + self.len { | |
if symbol_map[y].len() <= x { continue } | |
if symbol_map[y][x] { | |
addrs.push(format!("{}-{}", y, x)); | |
} | |
} | |
} | |
addrs | |
} | |
} | |
#[cfg(test)] | |
mod tests { | |
use crate::parse_input; | |
#[test] | |
fn test_parser() { | |
let input = "467..114.. | |
...*...... | |
..35..633. | |
......#... | |
617*...... | |
.....+.58. | |
..592..... | |
......755. | |
...$.*.... | |
.664.598.."; | |
let info = parse_input(&input, crate::SymbolType::Any); | |
println!("info: {:?}", info); | |
for n in info.numbers.iter() { | |
println!("n={}, {}", n.num, n.has_symbol(&info.symbol_map)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment