From 1895f386a308037146527896a2c35768a2d21b9c Mon Sep 17 00:00:00 2001 From: Joey Pollack Date: Tue, 5 Dec 2023 17:49:57 -0500 Subject: [PATCH] Day 3 complete --- day_3/src/main.rs | 230 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 222 insertions(+), 8 deletions(-) diff --git a/day_3/src/main.rs b/day_3/src/main.rs index 0a2b590..0c7a720 100644 --- a/day_3/src/main.rs +++ b/day_3/src/main.rs @@ -7,6 +7,7 @@ enum TokenType { Empty, Number, + NumberRef, // This spot is taken up by a number but the number doesn't begin in this spot Symbol, } @@ -16,7 +17,8 @@ struct Token ttype: TokenType, length: u32, value: i32, - symbol: u8 + symbol: u8, + id: u32, } @@ -25,27 +27,238 @@ fn main() let data = load_data("data/input"); let schematic = parse_schematic(&data); + // PART 1 let mut sum = 0; + let mut gear_ratio_sum = 0; for (row_idx, row) in schematic.iter().enumerate() { for (col_idx, token) in row.iter().enumerate() { + + // PART 1 if token.ttype == TokenType::Number && has_symbol_neighbor(row_idx, col_idx, &schematic) { sum += token.value; } + // else + // { + // if token.ttype == TokenType::Number + // { + // println!("DEBUG: Num does not have neighbor: {}", token.value); + // } + // } + + // PART 2 + if token.symbol == b'*' + { + let gear_ratio = get_gear_ratio(row_idx, col_idx, &schematic); + gear_ratio_sum += gear_ratio; + // println!("DEBUG: Running gear ratio: {}", gear_ratio_sum); + } + } + } + + println!("PART 1: Sum: {}", sum); + println!("PART 2: Sum of Gear Ratios: {}", gear_ratio_sum); +} + +fn get_gear_ratio(row: usize, col: usize, schematic: &Vec>) -> i32 +{ + + let mut first_part_num = 0; + let mut first_num_id = 0; + + let mut offset_row = -1; + while offset_row < 2 + { + let mut offset_col = - 1; + while offset_col < 2 + { + let r_idx: isize = offset_row + (row as isize); + let c_idx: isize = offset_col + (col as isize); + if r_idx >= 0 && r_idx < schematic.len() as isize + && c_idx >= 0 && c_idx < schematic[r_idx as usize].len() as isize + && (schematic[r_idx as usize][c_idx as usize].ttype == TokenType::Number + || schematic[r_idx as usize][c_idx as usize].ttype == TokenType::NumberRef) + { + if first_part_num == 0 + { + first_part_num = schematic[r_idx as usize][c_idx as usize].value; + first_num_id = schematic[r_idx as usize][c_idx as usize].id; + } + else + { + if first_num_id != schematic[r_idx as usize][c_idx as usize].id + { + return first_part_num * schematic[r_idx as usize][c_idx as usize].value; + } + } + } + + offset_col += 1; + } + + offset_row += 1; + } + + 0 +} + +#[allow(dead_code, non_snake_case)] +fn get_gear_ratio_OLD(row: usize, col: usize, schematic: &Vec>) -> i32 +{ + let mut first_part_num = 0; + let mut second_part_num = 0; + + // TODO: Find part nums + + // TOP ROW + if row as isize - 1 >= 0 + { + // TOP LEFT + if col as isize - 1 > 0 && schematic[row - 1][col - 1].ttype == TokenType::Number || schematic[row - 1][col - 1].ttype == TokenType::NumberRef + { + if first_part_num == 0 + { + first_part_num = schematic[row - 1][col - 1].value; + } + else + { + // This is to try to avoid using the same part num twice + // since numbers take up multiple columns. + // It's assuming a gear will never be connected to two different + // part nums with the same value though. It will break if that happens! + if first_part_num != schematic[row - 1][col - 1].value + { + return first_part_num * schematic[row - 1][col - 1].value; + } + } + } + + // TOP CENTER + if schematic[row - 1][col].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row - 1][col].value; + } + else + { + if first_part_num != schematic[row - 1][col].value + { + return first_part_num * schematic[row - 1][col].value; + } + } + } + + // TOP RIGHT + if col + 1 < schematic[row - 1].len() && schematic[row - 1][col + 1].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row - 1][col + 1].value; + } + else + { + if first_part_num != schematic[row - 1][col + 1].value + { + return first_part_num * schematic[row - 1][col + 1].value; + } + } + } + + } + + // BOTTOM ROW + if row + 1 < schematic.len() + { + // BOTTOM LEFT + if col as isize - 1 > 0 && schematic[row + 1][col - 1].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row + 1][col - 1].value; + } else { - if token.ttype == TokenType::Number + if first_part_num != schematic[row + 1][col - 1].value { - println!("DEBUG: Num does not have neighbor: {}", token.value); + return first_part_num * schematic[row + 1][col - 1].value; } } } + + // BOTTOM CENTER + if schematic[row + 1][col].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row + 1][col].value; + } + else + { + if first_part_num != schematic[row + 1][col].value + { + return first_part_num * schematic[row + 1][col].value; + } + } + } + + // BOTTOM RIGHT + if col + 1 < schematic[row + 1].len() && schematic[row + 1][col + 1].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row + 1][col + 1].value; + } + else + { + if first_part_num != schematic[row + 1][col + 1].value + { + return first_part_num * schematic[row + 1][col + 1].value; + } + } + } + + } + + // CENTER ROW + + // CENTER LEFT + if col as isize - 1 > 0 && schematic[row][col - 1].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row][col - 1].value; + } + else + { + if first_part_num != schematic[row][col - 1].value + { + return first_part_num * schematic[row][col - 1].value; + } + } + } + + + // BOTTOM RIGHT + if col + 1 < schematic[row].len() && schematic[row + 1][col + 1].ttype == TokenType::Number + { + if first_part_num == 0 + { + first_part_num = schematic[row][col + 1].value; + } + else + { + if first_part_num != schematic[row][col + 1].value + { + return first_part_num * schematic[row][col + 1].value; + } + } } - println!("Sum: {}", sum); + return 0; } fn has_symbol_neighbor(row: usize, col: usize, schematic: &Vec>) -> bool @@ -125,13 +338,14 @@ fn parse_schematic(input: &str) -> Vec> } // EMPTY - b'.' => parsed[row].push(Token { ttype: TokenType::Empty, length: 1, value: 0, symbol: b'.' }), + b'.' => parsed[row].push(Token { ttype: TokenType::Empty, length: 1, value: 0, symbol: b'.', id: idx as u32 }), // NUMBER b'0'..=b'9' => { let mut num: String = String::new(); let mut len = 0; + let id = idx as u32; while bytes[idx] >= b'0' && bytes[idx] <= b'9' { @@ -145,19 +359,19 @@ fn parse_schematic(input: &str) -> Vec> idx -= 1; let num = num.parse::().expect(&format!("Failed to parse number: {} on line: {}", num, row)); - parsed[row].push(Token { ttype: TokenType::Number, length: len, value: num, symbol: bytes[idx] }); + parsed[row].push(Token { ttype: TokenType::Number, length: len, value: num, symbol: bytes[idx], id }); // Pad out the grid with extra empties to account for the digits being // squished into 1 grid space for i in 1..len { - parsed[row].push(Token { ttype: TokenType::Empty, length: 1, value: 0, symbol: b'.'}); + parsed[row].push(Token { ttype: TokenType::NumberRef, length: 1, value: num, symbol: b'0', id}); } } // SYMBOL - _ => parsed[row].push(Token { ttype: TokenType::Symbol, length: 1, value: 0, symbol: bytes[idx] }), + _ => parsed[row].push(Token { ttype: TokenType::Symbol, length: 1, value: 0, symbol: bytes[idx], id: idx as u32 }), } idx += 1;