Add solution for 2015 day 09 part 2

This commit is contained in:
Patrick Auernig 2021-02-12 21:08:32 +01:00
parent 579393e8fc
commit 203babcde2
3 changed files with 93 additions and 0 deletions

View File

@ -13,3 +13,20 @@ Visit all nodes with shortest path
3. Set next node to current node
6. Otherwise:
1. Return with current stack
## Search Algorithm 2 (Depth First Search)
`O(n^2)`
Visit all nodes with longest path
1. Create a set for visited nodes
2. Begin search at start node
3. Mark current node as visited
4. Iterate through all outgoing nodes that are not marked as visited
5. Push node onto path
6. Add edge weight to local length
7. Recursively repeat steps 3 to 7 with outgoing nodes until all were visited
8. When encountering a visited node compare max distance with local distance
1. Replace max distance with local distance if max distance is smaller
10. Reset local length for next node (only necessary if not a complete graph)

View File

@ -1,6 +1,7 @@
mod graph;
mod utils;
mod part1;
mod part2;
type Graph = graph::Graph<Location, Distance>;
type Node = graph::Node<Location, Distance>;
@ -27,6 +28,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
utils::write_dot(&directions, file_path)?;
println!("\tPart 1: {:?}", part1::solve(&directions));
println!("\tPart 2: {:?}", part2::solve(&directions));
}
Ok(())

74
2015/day-09/src/part2.rs Normal file
View File

@ -0,0 +1,74 @@
use std::collections::HashSet;
use crate::{Distance, Graph, Node};
type NodeSet = HashSet<Node>;
struct Memo<'a> {
max_dist: &'a mut Distance,
prev_dist: Distance,
visited: &'a mut NodeSet,
path: &'a mut Vec<(Node, Distance)>,
}
fn depth_first_search(node: &Node, memo: Memo<'_>) {
memo.visited.insert(node.clone());
let mut distance = 0;
for (out_node, out_weight) in &node.borrow().outgoing {
if !memo.visited.contains(&out_node) {
memo.path.push((out_node.clone(), *out_weight));
distance = memo.prev_dist + out_weight;
depth_first_search(&out_node, Memo {
max_dist: &mut *memo.max_dist,
prev_dist: distance,
visited: &mut *memo.visited,
path: &mut *memo.path
});
}
if *memo.max_dist < distance {
*memo.max_dist = distance;
}
distance = 0
}
}
fn visit_all_longest(start_node: &Node) -> Vec<(Node, Distance)> {
let mut visited = NodeSet::new();
let mut path = Vec::new();
depth_first_search(&start_node, Memo {
max_dist: &mut 0,
prev_dist: 0,
visited: &mut visited,
path: &mut path
});
path
}
pub fn solve(directions: &Graph) -> Option<Distance> {
use std::cmp::max;
let mut longest_distance = None;
for node in &directions.nodes {
let path = visit_all_longest(node);
if path.is_empty() {
continue;
}
let distance = path.iter().map(|p| p.1).sum();
longest_distance = match longest_distance {
None => Some(distance),
Some(d) => Some(max(distance, d)),
};
}
longest_distance
}