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