1
0
Fork 0

day(03): refactor the solution

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2023-12-03 13:13:03 +01:00
parent ea6275d9e5
commit 45b6f64a3e
Signed by: mfocko
GPG key ID: 7C47D46246790496

View file

@ -5,19 +5,33 @@ use aoc_2023::*;
type Output1 = i32; type Output1 = i32;
type Output2 = Output1; type Output2 = Output1;
struct Day03 { struct Number {
lines: Vec<String>, 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,
} }
impl Solution<Output1, Output2> for Day03 {
fn new<P: AsRef<Path>>(pathname: P) -> Self {
Self {
lines: file_to_lines(pathname),
} }
} }
fn part_1(&mut self) -> Output1 { struct Day03 {
let symbols = self symbols: HashMap<(usize, usize), char>,
.lines numbers: Vec<Number>,
}
impl Solution<Output1, Output2> for Day03 {
fn new<P: AsRef<Path>>(pathname: P) -> Self {
let lines = file_to_lines(pathname);
let symbols = lines
.iter() .iter()
.enumerate() .enumerate()
.flat_map(|(y, line)| { .flat_map(|(y, line)| {
@ -30,72 +44,8 @@ impl Solution<Output1, Output2> for Day03 {
}) })
}) })
.collect::<HashMap<(usize, usize), char>>(); .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 numbers = lines
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
.iter() .iter()
.enumerate() .enumerate()
.flat_map(|(y, line)| { .flat_map(|(y, line)| {
@ -108,7 +58,7 @@ impl Solution<Output1, Output2> for Day03 {
start = cmp::min(start, x); start = cmp::min(start, x);
num = num * 10 + c.to_digit(10).unwrap() as i32; num = num * 10 + c.to_digit(10).unwrap() as i32;
} else if start != line.len() { } 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(); start = line.len();
num = 0; num = 0;
@ -116,25 +66,59 @@ impl Solution<Output1, Output2> for Day03 {
} }
if start != line.len() { 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 nums
}) })
.collect_vec(); .collect_vec();
numbers.iter().for_each(|(y, start, x, num)| { Self { symbols, numbers }
let mut possible_gears = vec![(*y, start - 1), (*y, *x)]; }
(*start - 1..=*x).for_each(|xx: usize| { fn part_1(&mut self) -> Output1 {
possible_gears.push((y - 1, xx)); self.numbers
possible_gears.push((y + 1, xx)); .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 { for (y, x) in possible_gears {
if symbols.contains_key(&(y, x)) { if let Some(nums) = symbol_counters.get_mut(&(y, x)) {
symbol_counters.entry((y, x)).or_default().push(*num); nums.push(n.value);
break;
} }
} }
}); });