diff --git a/2023/day3/src/main.rs b/2023/day3/src/main.rs index 6bb6c82..74879ba 100644 --- a/2023/day3/src/main.rs +++ b/2023/day3/src/main.rs @@ -1,10 +1,9 @@ -use crate::ValueType::Number; use std::collections::HashSet; use std::ops::Range; const FILE_STR: &'static str = include_str!("input.txt"); -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] struct NumberLocation { start: usize, end: usize, @@ -33,11 +32,12 @@ impl NumberLocation { #[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Eq, Hash)] enum ValueType { Number(usize), - Symbol, + Symbol(char), + Err(char), Empty, } -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] struct Grid { line_size: usize, numbers: Vec, @@ -46,11 +46,17 @@ struct Grid { impl Grid { pub fn parse(input_str: &str) -> Self { + use ValueType::*; + let len = input_str.split('\n').next().unwrap().len(); + let chars: Vec = input_str.replace("\n", "").chars().collect(); + let mut values: Vec = Vec::new(); let mut numbers: Vec = Vec::new(); - let chars: Vec = input_str.replace("\n", "").chars().collect(); - let mut prev = ValueType::Empty; + let mut prev = Empty; + + let symbols = vec!['%', '&', '/', '*', '=', '+', '#', '@', '-', '$']; + chars.iter().enumerate().for_each(|(i, ch)| { if ch.is_digit(10) { if let Number(_) = prev { @@ -63,9 +69,11 @@ impl Grid { prev = Number(numbers.len() - 1); } else if *ch == '.' { - prev = ValueType::Empty; + prev = Empty; + } else if symbols.contains(ch) { + prev = Symbol(*ch); } else { - prev = ValueType::Symbol; + prev = Err(*ch); } values.push(prev); @@ -102,16 +110,17 @@ impl Grid { return ind; } + let (col, row) = self.idx_xy(i); + // Forwards/backwards - if i > 0 { - ind.insert(i - 1); + if col > 0 { + ind.insert(self.xy_idx(col - 1, row)); } - if i + 1 < self.values.len() { - ind.insert(i + 1); + if col + 1 < self.num_cols() { + ind.insert(self.xy_idx(col + 1, row)); } // Row above/below - let (col, row) = self.idx_xy(i); if row + 1 < self.num_rows() { ind.insert(self.xy_idx(col, row + 1)); } @@ -149,7 +158,11 @@ impl Grid { } fn is_part_number(&self, r: Range) -> bool { - self.find_adjacent(r).contains(&ValueType::Symbol) + use ValueType::*; + self.find_adjacent(r).into_iter().any(|t| match t { + Symbol(_) => true, + _ => false, + }) } fn get_part_numbers(&self) -> Vec { @@ -163,15 +176,12 @@ impl Grid { .collect() } + fn get_unique_part_numbers(&self) -> HashSet { + HashSet::from_iter(self.get_part_numbers().iter().cloned()) + } + fn get_part_number_sum(&self) -> usize { - self.numbers - .iter() - .filter(|nl| { - let range = nl.start..nl.end; - self.is_part_number(range) - }) - .map(|nl| nl.to_number()) - .sum() + self.get_unique_part_numbers().iter().sum() } } @@ -189,10 +199,16 @@ fn main() { #[cfg(test)] mod tests { - use std::iter::FromIterator; - const EXAMPLE_FILE_STR: &'static str = include_str!("example_input.txt"); use super::*; + use std::iter::FromIterator; + use ValueType::*; + + #[test] + fn test_get_part_number_sum_part_1() { + let grid = Grid::parse(FILE_STR); + assert!(grid.get_part_number_sum() < 1645975); + } #[test] fn test_adjacent_index() { @@ -205,7 +221,7 @@ mod tests { let grid = Grid::parse(EXAMPLE_FILE_STR); let adjacent = grid.find_adjacent(5..6); let hadj = HashSet::from_iter(adjacent.iter().cloned()); - assert_eq!(hadj, HashSet::from([ValueType::Empty, Number(1)])); + assert_eq!(hadj, HashSet::from([Empty, Number(1)])); } #[test]