Skip to content

Commit

Permalink
Solve 2023 day 03 part 2
Browse files Browse the repository at this point in the history
  • Loading branch information
rayhem committed Dec 4, 2023
1 parent febea00 commit 804a020
Showing 1 changed file with 107 additions and 51 deletions.
158 changes: 107 additions & 51 deletions src/lib/solutions/year_2023/day_03.rs
Original file line number Diff line number Diff line change
@@ -1,83 +1,132 @@
use crate::utils::solution::Solution;
use std::{collections::HashMap, str::FromStr};

pub struct Day03 {}

impl Solution for Day03 {
fn part_one(&self, input: &str) -> Option<String> {
Some(sum_part_adjacent_numbers(&char_grid(input)).to_string())
let parts = Engine::from_str(input).unwrap().parts();
Some(parts.part_total().to_string())
}

fn part_two(&self, _input: &str) -> Option<String> {
None
fn part_two(&self, input: &str) -> Option<String> {
let parts = Engine::from_str(input).unwrap().parts();
Some(parts.gear_total().to_string())
}
}

fn char_grid(s: &str) -> Vec<Vec<char>> {
s.lines().map(|line| line.chars().collect()).collect()
#[derive(Clone, Debug)]
struct Part {
symbol: char,
numbers: Vec<i32>,
}

fn sum_part_adjacent_numbers(char_grid: &Vec<Vec<char>>) -> i32 {
let num_cols = match char_grid.first() {
Some(row) => row.len(),
None => 0,
};
impl Part {
fn new(ch: char) -> Self {
Self {
symbol: ch,
numbers: Vec::new(),
}
}
}

let mut total = 0;
struct EngineParts(HashMap<(usize, usize), Part>);

for row_idx in 0..char_grid.len() {
let row = char_grid.get(row_idx).unwrap();
impl EngineParts {
fn part_total(&self) -> i32 {
self.0
.values()
.map(|part| part.numbers.iter().sum::<i32>())
.sum::<i32>()
}

let mut col_idx = 0;
fn gear_total(&self) -> i32 {
self.0
.values()
.filter(|part| part.symbol == '*' && part.numbers.len() == 2)
.map(|part| part.numbers[0] * part.numbers[1])
.sum::<i32>()
}
}

'columns: while (0..num_cols).contains(&col_idx) {
if !row[col_idx].is_numeric() {
col_idx += 1;
continue;
}
#[derive(Clone, Debug)]
struct Engine(Vec<Vec<char>>);

let mut word_len = 0;
while col_idx + word_len < row.len() && row[col_idx + word_len].is_numeric() {
word_len += 1;
}
impl Engine {
fn parts(&self) -> EngineParts {
let num_cols = match self.0.first() {
Some(row) => row.len(),
None => 0,
};

let lower_row = ((row_idx as i32) - 1).max(0) as usize;
let upper_row = (row_idx + 1).min(char_grid.len() - 1);
let mut parts: HashMap<(usize, usize), Part> = HashMap::new();

let lower_col = ((col_idx as i32) - 1).max(0) as usize;
let upper_col = (col_idx + word_len).min(num_cols - 1);
for row_idx in 0..self.0.len() {
let row = self.0.get(row_idx).unwrap();

for adjacent_row in lower_row..=upper_row {
for adjacent_col in lower_col..=upper_col {
if adjacent_row == row_idx
&& (col_idx..(col_idx + word_len)).contains(&adjacent_col)
{
continue;
}
let mut col_idx = 0;

let adjacent_char = char_grid[adjacent_row][adjacent_col];
let is_symbol = !adjacent_char.is_numeric() && adjacent_char != '.';
'columns: while (0..num_cols).contains(&col_idx) {
if !row[col_idx].is_numeric() {
col_idx += 1;
continue;
}

if !is_symbol {
continue;
}
let mut word_len = 0;
while col_idx + word_len < row.len() && row[col_idx + word_len].is_numeric() {
word_len += 1;
}

let number = char_grid[row_idx][col_idx..(col_idx + word_len)]
.iter()
.collect::<String>();
let lower_row = ((row_idx as i32) - 1).max(0) as usize;
let upper_row = (row_idx + 1).min(self.0.len() - 1);

println!("{number}");
let lower_col = ((col_idx as i32) - 1).max(0) as usize;
let upper_col = (col_idx + word_len).min(num_cols - 1);

total += number.parse::<i32>().expect("expected numeric string");
col_idx += word_len;
continue 'columns;
for adjacent_row in lower_row..=upper_row {
for adjacent_col in lower_col..=upper_col {
if adjacent_row == row_idx
&& (col_idx..(col_idx + word_len)).contains(&adjacent_col)
{
continue;
}

let adjacent_char = self.0[adjacent_row][adjacent_col];
let is_symbol = !adjacent_char.is_numeric() && adjacent_char != '.';

if !is_symbol {
continue;
}

let number = self.0[row_idx][col_idx..(col_idx + word_len)]
.iter()
.collect::<String>();

parts
.entry((adjacent_row, adjacent_col))
.or_insert(Part::new(adjacent_char))
.numbers
.push(number.parse::<i32>().expect("expected numeric string"));

col_idx += word_len;
continue 'columns;
}
}
}

col_idx += word_len + 1;
col_idx += word_len + 1;
}
}

EngineParts(parts)
}
}

impl FromStr for Engine {
type Err = &'static str;

total
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Self(s.lines().map(|line| line.chars().collect()).collect()))
}
}

#[cfg(test)]
Expand All @@ -97,8 +146,15 @@ mod tests {
...$.*....
.664.598..
";
assert_eq!(sum_part_adjacent_numbers(&char_grid(INPUT)), 4361);
let parts = Engine::from_str(INPUT).unwrap().parts();
assert_eq!(parts.part_total(), 4361);
assert_eq!(parts.gear_total(), 467835);
}
}

crate::verify!(Day03, crate::my_input!("2023", "Day03"), "", "");
crate::verify!(
Day03,
crate::my_input!("2023", "Day03"),
"535351",
"87287096"
);

0 comments on commit 804a020

Please sign in to comment.