day(03): add solution
Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
parent
673c9299d5
commit
ea6275d9e5
2 changed files with 169 additions and 0 deletions
10
samples/day03.txt
Normal file
10
samples/day03.txt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
467..114..
|
||||||
|
...*......
|
||||||
|
..35..633.
|
||||||
|
......#...
|
||||||
|
617*......
|
||||||
|
.....+.58.
|
||||||
|
..592.....
|
||||||
|
......755.
|
||||||
|
...$.*....
|
||||||
|
.664.598..
|
159
src/bin/day03.rs
Normal file
159
src/bin/day03.rs
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
use std::{cmp, collections::HashMap};
|
||||||
|
|
||||||
|
use aoc_2023::*;
|
||||||
|
|
||||||
|
type Output1 = i32;
|
||||||
|
type Output2 = Output1;
|
||||||
|
|
||||||
|
struct Day03 {
|
||||||
|
lines: Vec<String>,
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
let symbols = self
|
||||||
|
.lines
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.flat_map(|(y, line)| {
|
||||||
|
line.chars().enumerate().filter_map(move |(x, c)| {
|
||||||
|
if c != '.' && !c.is_ascii_digit() {
|
||||||
|
Some(((y + 1, x + 1), c))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.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
|
||||||
|
.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 if start != line.len() {
|
||||||
|
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().for_each(|(y, start, x, num)| {
|
||||||
|
let mut possible_gears = vec![(*y, start - 1), (*y, *x)];
|
||||||
|
|
||||||
|
(*start - 1..=*x).for_each(|xx: usize| {
|
||||||
|
possible_gears.push((y - 1, xx));
|
||||||
|
possible_gears.push((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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
symbol_counters
|
||||||
|
.values()
|
||||||
|
.filter_map(|nums| {
|
||||||
|
if nums.len() == 2 {
|
||||||
|
Some(nums.iter().product1::<i32>().unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.sum()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
Day03::main()
|
||||||
|
}
|
||||||
|
|
||||||
|
test_sample!(day_03, Day03, 4361, 467835);
|
Loading…
Reference in a new issue