diff --git a/src/bin/day3.rs b/src/bin/day3.rs index 19f9ab3..5651ebe 100644 --- a/src/bin/day3.rs +++ b/src/bin/day3.rs @@ -4,7 +4,7 @@ use std::str::FromStr; #[derive(Debug)] enum Item { Digit(u32), - Symbol, + Symbol(bool), None, } @@ -30,25 +30,51 @@ impl Grid { } } - fn get_adjacent_items(&self, row: usize, start: usize, end: usize) -> Vec<&Item> { + fn get_adjacent_items(&self, row: usize, start: usize, end: usize) -> Vec<(&Item, usize, usize)> { // println!("\tget adj: r{} s{} e{}", row, start, end); - let row_start = if row > 0 { row - 1 } else { 0 }; - let col_start = if start > 0 { start - 1 } else { 0 }; - let mut items: Vec<&Item> = vec![]; - for row_i in row_start..=row + 1 { - for col_i in col_start..=end + 1 { + let row_start = if row > 0 { + row - 1 + } else { + 0 + }; + let col_start = if start > 0 { + start - 1 + } else { + 0 + }; + let mut items: Vec<(&Item, usize, usize)> = vec![]; + for row_i in row_start ..= row + 1 { + for col_i in col_start ..= end + 1 { if row_i != row || col_i < start || col_i > end { let item = self.get_item(row_i, col_i); // println!("\t\trow: {} col: {} item: {:?}", row_i, col_i, item); if let Some(item) = item { - items.push(item); + items.push((item, row_i, col_i)); } } } } return items; } + + fn get_adjacent_numbers(&self, row: usize, col: usize) -> Vec<&Number> { + let mut unique_numbers: Vec<&Number> = vec![]; + for item in self.get_adjacent_items(row, col, col) { + match item { + (Item::Digit(_), r, c) => { + if let Some(number_at) = + self.numbers.iter().find(|n| n.row_index == r && c >= n.char_start && c <= n.char_end) { + if unique_numbers.iter().all(|n| n.value != number_at.value) { + unique_numbers.push(number_at); + } + } + }, + _ => { }, + } + } + unique_numbers + } } impl FromStr for Grid { @@ -78,7 +104,7 @@ impl FromStr for Grid { row.push(Item::None); } else { // println!("Ended number seq, hit symbol after {:?} {}", num, char); - row.push(Item::Symbol) + row.push(Item::Symbol(char == '*')) } if let Some(value) = num { grid.numbers.push(Number { @@ -110,9 +136,8 @@ fn part1(input: String) -> Result { let grid: Grid = input.parse()?; let mut sum = 0; for number in grid.numbers.iter() { - let adjacent = - grid.get_adjacent_items(number.row_index, number.char_start, number.char_end); - let is_part_no = adjacent.iter().any(|item| matches!(item, Item::Symbol)); + let adjacent = grid.get_adjacent_items(number.row_index, number.char_start, number.char_end); + let is_part_no = adjacent.iter().any(|item| matches!(item, (Item::Symbol(_), _, _))); // ``` // println!( @@ -130,25 +155,41 @@ fn part1(input: String) -> Result { Ok(sum) } +fn part2(input: String) -> Result { + let grid: Grid = input.parse()?; + let mut sum = 0; + let mut used: Vec<(usize, usize)> = vec![]; + for number in grid.numbers.iter() { + let is_used = + used.iter().any(|(row, char_start)| number.row_index == *row && number.char_start == *char_start); + if !is_used { + let adjacent = grid.get_adjacent_items(number.row_index, number.char_start, number.char_end); + if let Some((_, row, col)) = adjacent.iter().find(|item| matches!(item.0, Item::Symbol(true))) { + let gear_nums = grid.get_adjacent_numbers(*row, *col); + if gear_nums.len() >= 2 { + // this is lazy.. adds duplicates but w/e + let power = gear_nums.iter().fold(1, |pow, gear| pow * gear.value); + gear_nums.iter().for_each(|g| { + // println!("GEAR FOUND: {}/{}", g.value, power); + used.push((g.row_index, g.char_start)) + }); + sum += power; + } + } + } + } + + // grid.print(); + Ok(sum) +} + #[tokio::main] async fn main() -> Result<()> { println!("Day 3"); println!("====="); let input = utils::aoc::get_puzzle_input(3).await?; - let input = "467..114.. -...*...... -..35..633. -......#... -617*...... -.....+.58. -..592..... -......755. -...$.*.... -.664.598.." - .to_owned(); let part_1 = part1(input.clone())?; - println!("part 1: {} == 520019 !! {}", part_1, part_1 == 520019); - - // println!("part 2: {}", part2(input.clone())?); + println!("part 1: {}", part_1); + println!("part 2: {}", part2(input.clone())?); Ok(()) }