This commit is contained in:
nora 2023-12-10 20:13:56 +01:00
parent c54bc78362
commit aa651ae78c
2 changed files with 107 additions and 25 deletions

View file

@ -59,6 +59,19 @@ enum Direction {
None, None,
} }
fn left(pos: usize, width: usize) -> Option<usize> {
(pos % width > 0).then(|| pos - 1)
}
fn right(pos: usize, width: usize) -> Option<usize> {
((pos % width) < (width - 1)).then(|| pos + 1)
}
fn top(pos: usize, width: usize) -> Option<usize> {
(pos >= width).then(|| pos - width)
}
fn bottom(pos: usize, len: usize, width: usize) -> Option<usize> {
(pos < (len - width)).then(|| pos + width)
}
impl Candidates<'_> { impl Candidates<'_> {
fn push(&mut self, new: Candidate) { fn push(&mut self, new: Candidate) {
match (new.came_from, self.bytes[new.pos]) { match (new.came_from, self.bytes[new.pos]) {
@ -71,39 +84,31 @@ impl Candidates<'_> {
} }
fn push_left(&mut self, from: Candidate) { fn push_left(&mut self, from: Candidate) {
if from.came_from != Direction::Left && from.pos % self.width > 0 { if from.came_from != Direction::Left {
self.push(Candidate::new( if let Some(left) = left(from.pos, self.width) {
from.count + 1, self.push(Candidate::new(from.count + 1, left, Direction::Right));
from.pos - 1, }
Direction::Right,
));
} }
} }
fn push_right(&mut self, from: Candidate) { fn push_right(&mut self, from: Candidate) {
if from.came_from != Direction::Right && (from.pos % self.width) < (self.width - 1) { if from.came_from != Direction::Right {
self.push(Candidate::new( if let Some(right) = right(from.pos, self.width) {
from.count + 1, self.push(Candidate::new(from.count + 1, right, Direction::Left));
from.pos + 1, }
Direction::Left,
));
} }
} }
fn push_top(&mut self, from: Candidate) { fn push_top(&mut self, from: Candidate) {
if from.came_from != Direction::Top && from.pos >= self.width { if from.came_from != Direction::Top {
self.push(Candidate::new( if let Some(top) = top(from.pos, self.width) {
from.count + 1, self.push(Candidate::new(from.count + 1, top, Direction::Bottom));
from.pos - self.width, }
Direction::Bottom,
));
} }
} }
fn push_bottom(&mut self, from: Candidate) { fn push_bottom(&mut self, from: Candidate) {
if from.came_from != Direction::Bottom && from.pos < (self.len - self.width) { if from.came_from != Direction::Bottom {
self.push(Candidate::new( if let Some(bottom) = bottom(from.pos, self.bytes.len(), self.width) {
from.count + 1, self.push(Candidate::new(from.count + 1, bottom, Direction::Top));
from.pos + self.width, }
Direction::Top,
));
} }
} }
} }
@ -247,12 +252,14 @@ fn part1(input: &str) -> u64 {
get_loop(input).highest_value get_loop(input).highest_value
} }
fn part2(_input: &str) -> u64 { fn part2(input: &str) -> u64 {
// Step 1: Find the loop // Step 1: Find the loop
// We do this by using the step-map from before, counting backwards from the target basically. // We do this by using the step-map from before, counting backwards from the target basically.
// Step 2: Cellular-automata-ish, start from the borders and start eating away // Step 2: Cellular-automata-ish, start from the borders and start eating away
// everything connected to that, only stopping at the main loop. // everything connected to that, only stopping at the main loop.
// Open question: How do we squeeze between main loop pipes? // Open question: How do we squeeze between main loop pipes?
let the_loop = get_loop(input);
let mut tiles = vec![0; the_loop.step_map.len()];
0 0
} }

75
file.rs Normal file
View file

@ -0,0 +1,75 @@
use std::ops::Add;
fn parse(input: &str, into: &mut Vec<i64>, mut line_callback: impl FnMut(&mut Vec<i64>)) {
let mut neg = false;
let mut acc = 0;
for byte in input.bytes() {
match byte {
b' ' => {
if neg {
acc = -acc
};
into.push(acc);
acc = 0;
neg = false;
}
b'-' => neg = true,
b'\n' => {
if neg {
acc = -acc
};
into.push(acc);
line_callback(into);
into.clear();
acc = 0;
neg = false;
}
// must be b'0'..=b'9'
_ => {
let value = byte - b'0';
acc = (acc * 10) + (value as i64);
}
}
}
}
fn execute(
input: &str,
last_or_first: impl Fn(&[i64]) -> i64,
fold: impl Fn(i64, i64) -> i64 + Copy,
) -> i64 {
let mut row1 = Vec::with_capacity(128);
let mut row2 = Vec::with_capacity(128);
let mut last_values = Vec::with_capacity(16);
let mut total = 0;
parse(input, &mut row1, |row1| {
row2.clone_from(&row1);
last_values.clear();
last_values.push(last_or_first(&row1));
while !row2.iter().all(|&n| n == 0) {
row1.clear();
row1.extend(row2.windows(2).map(|s| s[1] - s[0]));
last_values.push(last_or_first(&row1));
std::mem::swap(row1, &mut row2);
}
total += last_values.iter().copied().rev().fold(0, fold);
});
total
}
pub fn run(input: &str) -> u64 {
execute(input, |s| *s.last().unwrap(), Add::add) as u64
}
pub fn part2(input: &str) -> u64 {
execute(input, |s| *s.first().unwrap(), |a, b| b - a) as u64
}