fix(day3): Vec of Vec optimization
parent
def7d4cf3f
commit
f09b4154f2
|
@ -1,3 +1,4 @@
|
|||
use std::cmp::min;
|
||||
use std::fmt::Debug;
|
||||
|
||||
use adventofcode2023::utils::get_puzzle;
|
||||
|
@ -6,17 +7,18 @@ use adventofcode2023::utils::get_puzzle;
|
|||
struct PartNumber {
|
||||
number: u32,
|
||||
range: std::ops::Range<usize>,
|
||||
line_index: usize,
|
||||
valid: bool,
|
||||
}
|
||||
|
||||
type PartsLine = Vec<PartNumber>;
|
||||
|
||||
trait SymbolCheckable {
|
||||
fn is_symbol(&self) -> bool;
|
||||
}
|
||||
|
||||
impl SymbolCheckable for char {
|
||||
fn is_symbol(&self) -> bool {
|
||||
*self != '.' && !self.is_ascii_punctuation()
|
||||
*self != '.' && !self.is_alphanumeric()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,62 +31,65 @@ fn parse_number(line: &str) -> (u32, usize) {
|
|||
(number, number_str.len())
|
||||
}
|
||||
|
||||
fn parse_parts(puzzle: &str) -> Vec<PartNumber> {
|
||||
let mut part_numbers = Vec::new();
|
||||
for (line_index, line) in puzzle.lines().enumerate() {
|
||||
let mut i = 0;
|
||||
while i < line.len() {
|
||||
let c = line.chars().nth(i).unwrap();
|
||||
if c.is_ascii_digit() {
|
||||
let (number, number_len) = parse_number(&line[i..]);
|
||||
let part_number = PartNumber {
|
||||
number,
|
||||
range: i.saturating_sub(1)..i + number_len + 1,
|
||||
line_index,
|
||||
valid: false,
|
||||
};
|
||||
i = part_number.range.end;
|
||||
part_numbers.push(part_number);
|
||||
} else {
|
||||
i += 1;
|
||||
fn parse_parts(puzzle: &str) -> Vec<PartsLine> {
|
||||
puzzle
|
||||
.lines()
|
||||
.map(|line| {
|
||||
let mut part_numbers = Vec::new();
|
||||
let mut i = 0;
|
||||
while i < line.len() {
|
||||
let c = line.chars().nth(i).unwrap();
|
||||
if c.is_ascii_digit() {
|
||||
let (number, number_len) = parse_number(&line[i..]);
|
||||
let part_number = PartNumber {
|
||||
number,
|
||||
range: i.saturating_sub(1)..i + number_len + 1,
|
||||
valid: false,
|
||||
};
|
||||
i = part_number.range.end;
|
||||
part_numbers.push(part_number);
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
part_numbers
|
||||
part_numbers
|
||||
})
|
||||
.collect::<Vec<PartsLine>>()
|
||||
}
|
||||
|
||||
fn compute_part_numbers_sum(puzzle: &str) -> u32 {
|
||||
let mut part_numbers = parse_parts(puzzle);
|
||||
let mut part_lines = parse_parts(puzzle);
|
||||
let line_range_max = part_lines.len() - 1;
|
||||
for (line_index, line) in puzzle.lines().enumerate() {
|
||||
for (i, c) in line.chars().enumerate() {
|
||||
if c.is_symbol() {
|
||||
let line_range = line_index.saturating_sub(1)..=line_index + 1;
|
||||
part_numbers
|
||||
let line_range = line_index.saturating_sub(1)..=min(line_index + 1, line_range_max);
|
||||
part_lines[line_range]
|
||||
.iter_mut()
|
||||
.filter(|part_number| {
|
||||
!part_number.valid && line_range.contains(&part_number.line_index)
|
||||
})
|
||||
.filter(|part_number| part_number.range.contains(&i))
|
||||
.for_each(|part_number: &mut PartNumber| part_number.valid = true);
|
||||
.flat_map(|v| v.iter_mut())
|
||||
.filter(|part_number| !part_number.valid)
|
||||
.for_each(|part_number| part_number.valid = part_number.range.contains(&i));
|
||||
}
|
||||
}
|
||||
}
|
||||
part_numbers
|
||||
part_lines
|
||||
.iter()
|
||||
.flat_map(|v| v.iter())
|
||||
.filter(|part_number| part_number.valid)
|
||||
.fold(0, |acc, part_number| acc + part_number.number)
|
||||
}
|
||||
|
||||
fn compute_gear_ratios_sum(puzzle: &str) -> u32 {
|
||||
let part_numbers = parse_parts(puzzle);
|
||||
let part_lines = parse_parts(puzzle);
|
||||
let line_range_max = part_lines.len() - 1;
|
||||
let mut gear_ratios_sum = 0;
|
||||
for (line_index, line) in puzzle.lines().enumerate() {
|
||||
for (i, c) in line.chars().enumerate() {
|
||||
if c == '*' {
|
||||
let line_range = line_index.saturating_sub(1)..=line_index + 1;
|
||||
let gear_parts = part_numbers
|
||||
let line_range = line_index.saturating_sub(1)..=min(line_index + 1, line_range_max);
|
||||
let gear_parts = part_lines[line_range]
|
||||
.iter()
|
||||
.filter(|part_number| line_range.contains(&part_number.line_index))
|
||||
.flat_map(|v| v.iter())
|
||||
.filter_map(|part_number| match part_number.range.contains(&i) {
|
||||
true => Some(part_number.number),
|
||||
false => None,
|
||||
|
|
Loading…
Reference in New Issue