day(03): refactor the solution
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
ea6275d9e5
commit
45b6f64a3e
1 changed files with 67 additions and 83 deletions
150
src/bin/day03.rs
150
src/bin/day03.rs
|
@ -5,19 +5,33 @@ use aoc_2023::*;
|
|||
type Output1 = i32;
|
||||
type Output2 = Output1;
|
||||
|
||||
struct Number {
|
||||
y: usize,
|
||||
x_min: usize,
|
||||
x_max: usize,
|
||||
value: i32,
|
||||
}
|
||||
|
||||
impl Number {
|
||||
fn new(y: usize, x_min: usize, x_max: usize, value: i32) -> Number {
|
||||
Number {
|
||||
y,
|
||||
x_min,
|
||||
x_max,
|
||||
value,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Day03 {
|
||||
lines: Vec<String>,
|
||||
symbols: HashMap<(usize, usize), char>,
|
||||
numbers: Vec<Number>,
|
||||
}
|
||||
impl Solution<Output1, Output2> for Day03 {
|
||||
fn new<P: AsRef<Path>>(pathname: P) -> Self {
|
||||
Self {
|
||||
lines: file_to_lines(pathname),
|
||||
}
|
||||
}
|
||||
let lines = file_to_lines(pathname);
|
||||
|
||||
fn part_1(&mut self) -> Output1 {
|
||||
let symbols = self
|
||||
.lines
|
||||
let symbols = lines
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
|
@ -30,72 +44,8 @@ impl Solution<Output1, Output2> for Day03 {
|
|||
})
|
||||
})
|
||||
.collect::<HashMap<(usize, usize), char>>();
|
||||
let numbers = self
|
||||
.lines
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
let mut nums = vec![];
|
||||
|
||||
let mut start = line.len();
|
||||
let mut num = 0;
|
||||
for (x, c) in line.chars().enumerate() {
|
||||
if c.is_ascii_digit() {
|
||||
start = cmp::min(start, x);
|
||||
num = num * 10 + c.to_digit(10).unwrap() as i32;
|
||||
} else {
|
||||
nums.push((y + 1, start + 1, x + 1, num));
|
||||
|
||||
start = line.len();
|
||||
num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if start != line.len() {
|
||||
nums.push((y + 1, start + 1, line.len() + 1, num));
|
||||
}
|
||||
|
||||
nums
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
numbers
|
||||
.iter()
|
||||
.filter_map(|(y, start, x, num)| {
|
||||
if symbols.contains_key(&(*y, start - 1))
|
||||
|| symbols.contains_key(&(*y, *x))
|
||||
|| (*start - 1..=*x).any(|xx| {
|
||||
symbols.contains_key(&(y - 1, xx)) || symbols.contains_key(&(y + 1, xx))
|
||||
})
|
||||
{
|
||||
Some(*num)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part_2(&mut self) -> Output2 {
|
||||
let symbols = self
|
||||
.lines
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
line.chars().enumerate().filter_map(move |(x, c)| {
|
||||
if c == '*' {
|
||||
Some(((y + 1, x + 1), c))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect::<HashMap<(usize, usize), char>>();
|
||||
|
||||
let mut symbol_counters: HashMap<(usize, usize), Vec<i32>> = HashMap::new();
|
||||
|
||||
let numbers = self
|
||||
.lines
|
||||
let numbers = lines
|
||||
.iter()
|
||||
.enumerate()
|
||||
.flat_map(|(y, line)| {
|
||||
|
@ -108,7 +58,7 @@ impl Solution<Output1, Output2> for Day03 {
|
|||
start = cmp::min(start, x);
|
||||
num = num * 10 + c.to_digit(10).unwrap() as i32;
|
||||
} else if start != line.len() {
|
||||
nums.push((y + 1, start + 1, x + 1, num));
|
||||
nums.push(Number::new(y + 1, start + 1, x + 1, num));
|
||||
|
||||
start = line.len();
|
||||
num = 0;
|
||||
|
@ -116,25 +66,59 @@ impl Solution<Output1, Output2> for Day03 {
|
|||
}
|
||||
|
||||
if start != line.len() {
|
||||
nums.push((y + 1, start + 1, line.len() + 1, num));
|
||||
nums.push(Number::new(y + 1, start + 1, line.len() + 1, num));
|
||||
}
|
||||
|
||||
nums
|
||||
})
|
||||
.collect_vec();
|
||||
|
||||
numbers.iter().for_each(|(y, start, x, num)| {
|
||||
let mut possible_gears = vec![(*y, start - 1), (*y, *x)];
|
||||
Self { symbols, numbers }
|
||||
}
|
||||
|
||||
(*start - 1..=*x).for_each(|xx: usize| {
|
||||
possible_gears.push((y - 1, xx));
|
||||
possible_gears.push((y + 1, xx));
|
||||
fn part_1(&mut self) -> Output1 {
|
||||
self.numbers
|
||||
.iter()
|
||||
.filter_map(|n| {
|
||||
if self.symbols.contains_key(&(n.y, n.x_min - 1))
|
||||
|| self.symbols.contains_key(&(n.y, n.x_max))
|
||||
|| (n.x_min - 1..=n.x_max).any(|xx| {
|
||||
self.symbols.contains_key(&(n.y - 1, xx))
|
||||
|| self.symbols.contains_key(&(n.y + 1, xx))
|
||||
})
|
||||
{
|
||||
Some(n.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.sum()
|
||||
}
|
||||
|
||||
fn part_2(&mut self) -> Output2 {
|
||||
let mut symbol_counters: HashMap<(usize, usize), Vec<i32>> = self
|
||||
.symbols
|
||||
.iter()
|
||||
.filter_map(|((y, x), s)| {
|
||||
if *s == '*' {
|
||||
Some(((*y, *x), vec![]))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.numbers.iter().for_each(|n| {
|
||||
let mut possible_gears = vec![(n.y, n.x_min - 1), (n.y, n.x_max)];
|
||||
|
||||
(n.x_min - 1..=n.x_max).for_each(|xx: usize| {
|
||||
possible_gears.push((n.y - 1, xx));
|
||||
possible_gears.push((n.y + 1, xx));
|
||||
});
|
||||
|
||||
for (y, x) in possible_gears {
|
||||
if symbols.contains_key(&(y, x)) {
|
||||
symbol_counters.entry((y, x)).or_default().push(*num);
|
||||
break;
|
||||
if let Some(nums) = symbol_counters.get_mut(&(y, x)) {
|
||||
nums.push(n.value);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue