mirror of
https://github.com/bertptrs/adventofcode.git
synced 2025-12-25 21:00:31 +01:00
Implement 2023 day 23 part 2
This commit is contained in:
@@ -12,6 +12,13 @@ enum Slope {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Slope {
|
impl Slope {
|
||||||
|
fn invert(self) -> Self {
|
||||||
|
match self {
|
||||||
|
Slope::Level => Self::Level,
|
||||||
|
Slope::Up => Self::Down,
|
||||||
|
Slope::Down => Self::Up,
|
||||||
|
}
|
||||||
|
}
|
||||||
fn combine(self, other: Self) -> Self {
|
fn combine(self, other: Self) -> Self {
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Slope::Level, next) | (next, Slope::Level) => next,
|
(Slope::Level, next) | (next, Slope::Level) => next,
|
||||||
@@ -25,7 +32,7 @@ impl Slope {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simplify_graph(input: &[u8]) -> anyhow::Result<Vec<Vec<(usize, u32)>>> {
|
fn simplify_graph(input: &[u8]) -> anyhow::Result<Vec<Vec<(Slope, usize, u32)>>> {
|
||||||
let map = Grid::new(input)?;
|
let map = Grid::new(input)?;
|
||||||
let width = map.width();
|
let width = map.width();
|
||||||
let height = map.height();
|
let height = map.height();
|
||||||
@@ -76,12 +83,8 @@ fn simplify_graph(input: &[u8]) -> anyhow::Result<Vec<Vec<(usize, u32)>>> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches!(slope, Slope::Down | Slope::Level) {
|
graph[id].push((slope, other, dist + 1));
|
||||||
graph[id].push((other, dist + 1));
|
graph[other].push((slope.invert(), id, dist + 1));
|
||||||
}
|
|
||||||
if matches!(slope, Slope::Up | Slope::Level) {
|
|
||||||
graph[other].push((id, dist + 1));
|
|
||||||
}
|
|
||||||
} else if visited.insert(x + y * width) {
|
} else if visited.insert(x + y * width) {
|
||||||
let tile_slope = if map[(y, x)] == up {
|
let tile_slope = if map[(y, x)] == up {
|
||||||
Slope::Up
|
Slope::Up
|
||||||
@@ -96,12 +99,8 @@ fn simplify_graph(input: &[u8]) -> anyhow::Result<Vec<Vec<(usize, u32)>>> {
|
|||||||
let new_id = graph.len();
|
let new_id = graph.len();
|
||||||
nodes.insert((x, y), new_id);
|
nodes.insert((x, y), new_id);
|
||||||
graph.push(Vec::new());
|
graph.push(Vec::new());
|
||||||
if matches!(slope, Slope::Down | Slope::Level) {
|
graph[id].push((slope, new_id, dist + 1));
|
||||||
graph[id].push((new_id, dist + 1));
|
graph[new_id].push((slope.invert(), id, dist + 1));
|
||||||
}
|
|
||||||
if matches!(slope, Slope::Up | Slope::Level) {
|
|
||||||
graph[new_id].push((id, dist + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
todo_junctions.push((new_id, x, y));
|
todo_junctions.push((new_id, x, y));
|
||||||
} else {
|
} else {
|
||||||
@@ -122,7 +121,7 @@ fn simplify_graph(input: &[u8]) -> anyhow::Result<Vec<Vec<(usize, u32)>>> {
|
|||||||
fn longest_path(
|
fn longest_path(
|
||||||
pos: usize,
|
pos: usize,
|
||||||
travelled: u32,
|
travelled: u32,
|
||||||
graph: &[Vec<(usize, u32)>],
|
graph: &[Vec<(Slope, usize, u32)>],
|
||||||
visited: &mut HashSet<usize>,
|
visited: &mut HashSet<usize>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
if pos == 1 {
|
if pos == 1 {
|
||||||
@@ -131,8 +130,8 @@ fn longest_path(
|
|||||||
|
|
||||||
let mut best = 0;
|
let mut best = 0;
|
||||||
|
|
||||||
for &(other, dist) in &graph[pos] {
|
for &(slope, other, dist) in &graph[pos] {
|
||||||
if visited.insert(other) {
|
if !matches!(slope, Slope::Up) && visited.insert(other) {
|
||||||
best = Ord::max(best, longest_path(other, travelled + dist, graph, visited));
|
best = Ord::max(best, longest_path(other, travelled + dist, graph, visited));
|
||||||
visited.remove(&other);
|
visited.remove(&other);
|
||||||
}
|
}
|
||||||
@@ -147,8 +146,35 @@ pub fn part1(input: &[u8]) -> anyhow::Result<String> {
|
|||||||
Ok(longest_path(0, 0, &graph, &mut HashSet::new()).to_string())
|
Ok(longest_path(0, 0, &graph, &mut HashSet::new()).to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn part2(_input: &[u8]) -> anyhow::Result<String> {
|
fn longer_longest_path(
|
||||||
anyhow::bail!("Not implemented")
|
pos: usize,
|
||||||
|
travelled: u32,
|
||||||
|
graph: &[Vec<(Slope, usize, u32)>],
|
||||||
|
visited: &mut HashSet<usize>,
|
||||||
|
) -> u32 {
|
||||||
|
if pos == 1 {
|
||||||
|
return travelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut best = 0;
|
||||||
|
|
||||||
|
for &(_, other, dist) in &graph[pos] {
|
||||||
|
if visited.insert(other) {
|
||||||
|
best = Ord::max(
|
||||||
|
best,
|
||||||
|
longer_longest_path(other, travelled + dist, graph, visited),
|
||||||
|
);
|
||||||
|
visited.remove(&other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
best
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn part2(input: &[u8]) -> anyhow::Result<String> {
|
||||||
|
let graph = simplify_graph(input)?;
|
||||||
|
|
||||||
|
Ok(longer_longest_path(0, 0, &graph, &mut HashSet::new()).to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -161,4 +187,9 @@ mod tests {
|
|||||||
fn sample_part1() {
|
fn sample_part1() {
|
||||||
assert_eq!("94", part1(SAMPLE).unwrap());
|
assert_eq!("94", part1(SAMPLE).unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sample_part2() {
|
||||||
|
assert_eq!("154", part2(SAMPLE).unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user