Finished Day 3-2

This commit is contained in:
Dennis Brentjes
2023-12-05 09:35:22 +01:00
parent d5e580ad83
commit 891852d716
3 changed files with 125 additions and 9 deletions

View File

@@ -1,14 +1,54 @@
use std::{str::FromStr, path::Path, option::Option};
use itertools::Itertools;
use crate::input::{AdventError, read_into_vec};
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Number {
value: u32,
position: u8,
length: u8
}
#[derive(Debug, Clone)]
pub struct Symbol {
position: u8,
symbol: char,
}
impl From<u8> for Symbol {
fn from(value: u8) -> Self {
Symbol{position: value, symbol: ' '}
}
}
impl PartialEq for Symbol {
fn eq(&self, other: &Self) -> bool {
self.position == other.position
}
}
impl PartialOrd for Symbol {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
match self.position.partial_cmp(&other.position) {
Some(core::cmp::Ordering::Equal) => {}
ord => return ord,
}
self.symbol.partial_cmp(&other.symbol)
}
}
impl Eq for Symbol {
}
impl Ord for Symbol {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.position.cmp(&other.position)
}
}
impl FromStr for RowInfo {
type Err = AdventError;
@@ -25,7 +65,7 @@ impl FromStr for RowInfo {
struct RowInfo {
partial_start: Option<u8>,
partial_number: Option<String>,
pub symbol_positions: Vec<u8>,
pub symbols: Vec<Symbol>,
pub numbers: Vec<Number>,
}
@@ -34,13 +74,13 @@ impl RowInfo {
Self {
partial_start: None,
partial_number: None,
symbol_positions: Vec::<u8>::new(),
symbols: Vec::<Symbol>::new(),
numbers: Vec::<Number>::new()
}
}
fn add_symbol(&mut self, i: usize) -> Result<(), AdventError> {
self.symbol_positions.push(i as u8);
fn add_symbol(&mut self, b: u8, i: usize) -> Result<(), AdventError> {
self.symbols.push(Symbol {position: i as u8, symbol: b as char});
if self.partial_start != None {
self.finish_digit(i)?
}
@@ -61,7 +101,7 @@ impl RowInfo {
fn process(&mut self, i: usize, b: &u8) -> Result<(), AdventError> {
if b != &b'.' && !b.is_ascii_digit() {
self.add_symbol(i)?
self.add_symbol(*b, i)?
}
else if b.is_ascii_digit() {
if self.partial_start.is_none() {
@@ -92,7 +132,7 @@ impl Default for RowInfo {
}
}
pub fn gen_coords(y: usize, number: &Number) -> Vec<(u8, u8)> {
pub fn gen_coords_number(y: usize, number: &Number) -> Vec<(u8, u8)> {
let mut vec = Vec::<(u8, u8)>::new();
let min_x = if number.position == 0 {
0
@@ -112,17 +152,44 @@ pub fn gen_coords(y: usize, number: &Number) -> Vec<(u8, u8)> {
vec
}
pub fn gen_coords_symbol(y: usize, symbol: &Symbol) -> Vec<(u8,u8)> {
let mut vec = Vec::<(u8, u8)>::new();
let min_x = if symbol.position == 0 {
0
} else {
symbol.position - 1
};
let max_x = symbol.position + 1 + 1;
for x in min_x..max_x {
if y != 0 {
vec.push((x, y as u8 - 1));
}
if x < symbol.position || x > symbol.position {
vec.push((x, y as u8));
}
vec.push((x, y as u8 + 1));
}
vec
}
fn filter_gears(rows: &mut Vec<RowInfo>) -> &mut Vec<RowInfo> {
for row in rows.iter_mut() {
row.symbols = row.symbols.clone().into_iter().filter(|x| { x.symbol == '*' }).collect::<Vec<Symbol>>()
}
rows
}
pub fn one() -> Result<(), AdventError> {
let rows = read_into_vec::<RowInfo>(Path::new("resources/input3.txt"))?;
let mut sum: u32 = 0;
for (i, row) in rows.iter().enumerate() {
for number in row.numbers.iter() {
let coords = gen_coords(i, number);
let coords = gen_coords_number(i, number);
if coords.iter().any(|c| -> bool {
if c.1 as usize >= rows.len() {
false
} else {
rows[c.1 as usize].symbol_positions.binary_search(&c.0).is_ok()
rows[c.1 as usize].symbols.binary_search(&c.0.into()).is_ok()
}
}) {
sum += number.value;
@@ -134,5 +201,35 @@ pub fn one() -> Result<(), AdventError> {
}
pub fn two() -> Result<(), AdventError> {
let mut rows = read_into_vec::<RowInfo>(Path::new("resources/input3.txt"))?;
rows = filter_gears(&mut rows).clone();
let mut sum: u32 = 0;
for (i, row) in rows.iter().enumerate() {
for symbol in row.symbols.iter() {
let coords = gen_coords_symbol(i, symbol);
let numbers = coords.iter().map(|(x, y)| {
if *y as usize >= rows.len() {
None
} else {
let relevant_numbers = rows[*y as usize].numbers.clone().into_iter().filter(|number| {*x >= number.position && *x < number.position + number.length}).collect::<Vec<Number>>();
if relevant_numbers.len() == 1 {
Some(relevant_numbers[0].clone())
} else {
None
}
}
})
.filter(|x| {x.is_some()})
.map(|x| {x.unwrap()})
.unique()
.collect::<Vec<Number>>();
if numbers.len() == 2 {
sum += numbers[0].value * numbers[1].value;
}
}
}
println!("{}", sum);
Ok(())
}