day3 solution
parent
d2fdbae3ae
commit
428efcbfc1
|
@ -0,0 +1,133 @@
|
|||
use aoc_runner_derive::{aoc, aoc_generator};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
type PartList = BTreeMap<(usize, usize, char), Vec<u32>>;
|
||||
|
||||
fn parse(input: &str) -> Vec<Vec<char>> {
|
||||
input
|
||||
.lines()
|
||||
.filter_map(|line| {
|
||||
if !line.is_empty() {
|
||||
Some(line.chars().collect::<Vec<char>>())
|
||||
} 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<char> = 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::<Vec<String>>()
|
||||
.join("")
|
||||
.parse::<u32>()
|
||||
.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::<u32>();
|
||||
}
|
||||
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::<u32>();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
|
@ -2,5 +2,6 @@ use aoc_runner_derive::aoc_lib;
|
|||
|
||||
mod day01;
|
||||
mod day02;
|
||||
mod day03;
|
||||
|
||||
aoc_lib! { year = 2023 }
|
||||
|
|
Loading…
Reference in New Issue