diff --git a/2023/src/day03.rs b/2023/src/day03.rs new file mode 100644 index 0000000..eb78864 --- /dev/null +++ b/2023/src/day03.rs @@ -0,0 +1,133 @@ +use aoc_runner_derive::{aoc, aoc_generator}; +use std::collections::BTreeMap; + +type PartList = BTreeMap<(usize, usize, char), Vec>; + +fn parse(input: &str) -> Vec> { + input + .lines() + .filter_map(|line| { + if !line.is_empty() { + Some(line.chars().collect::>()) + } else { + None + } + }) + .collect() +} + +#[aoc_generator(day3)] +fn associate_parts(input: &str) -> PartList { + let parsed_input = parse(input); + let mut result: PartList = BTreeMap::new(); + for (line_index, line) in parsed_input.iter().enumerate() { + let mut parse_end = 0; + for (index, c) in line.iter().enumerate() { + if index < parse_end { + continue; + } + if c.is_ascii_digit() { + let mut n: Vec = vec![]; + n.push(*c); + if index + 1 < line.len() && line[index + 1].is_ascii_digit() { + n.push(line[index + 1]); + if index + 2 < line.len() && line[index + 2].is_ascii_digit() { + n.push(line[index + 2]); + } + } + let part_num = n + .iter() + .map(|x| x.to_string()) + .collect::>() + .join("") + .parse::() + .unwrap(); + let mut adjacent: Vec<(usize, usize)> = vec![]; + let mut left_side = index; + if index > 1 { + left_side -= 1; + } + let mut right_side = index + n.len() - 1; + if right_side < line.len() - 1 { + right_side += 1; + } + parse_end = right_side; + let mut top_side = line_index; + if top_side > 1 { + top_side -= 1; + } + let mut bottom_side = line_index; + if bottom_side + 1 <= parsed_input.len() - 1 { + bottom_side += 1; + } + adjacent.push((line_index, left_side)); + adjacent.push((line_index, right_side)); + for col in left_side..=right_side { + adjacent.push((top_side, col)); + adjacent.push((bottom_side, col)); + } + if let Some(part_coord) = adjacent.iter().find(|coord| { + !parsed_input[coord.0][coord.1].is_ascii_digit() + && parsed_input[coord.0][coord.1] != '.' + }) { + let hash_key = ( + part_coord.0, + part_coord.1, + parsed_input[part_coord.0][part_coord.1], + ); + if !result.contains_key(&hash_key) { + result.insert(hash_key, vec![]); + } + let plist = result.get_mut(&hash_key).unwrap(); + plist.push(part_num); + } + } + } + } + // println!("{:?}", result); + result +} + +#[aoc(day3, part1)] +fn part1(input: &PartList) -> u32 { + let mut sum: u32 = 0; + for (_coord, plist) in input.iter() { + sum += plist.iter().sum::(); + } + sum +} + +#[aoc(day3, part2)] +fn part2(input: &PartList) -> u32 { + let mut sum: u32 = 0; + for (coord, plist) in input.iter() { + if coord.2 == '*' && plist.len() == 2 { + sum += plist.iter().product::(); + } + } + sum +} + +#[cfg(test)] +mod tests { + use super::*; + + const SAMPLE_DATA: &'static str = r#"467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.. +"#; + + #[test] + fn sample_data() { + let parts = associate_parts(&SAMPLE_DATA); + assert_eq!(part1(&parts), 4361); + assert_eq!(part2(&parts), 467835); + } +} diff --git a/2023/src/lib.rs b/2023/src/lib.rs index e1cfc0b..8f30b5d 100644 --- a/2023/src/lib.rs +++ b/2023/src/lib.rs @@ -2,5 +2,6 @@ use aoc_runner_derive::aoc_lib; mod day01; mod day02; +mod day03; aoc_lib! { year = 2023 }