Add solution for 2015 day 09 part 2
This commit is contained in:
parent
579393e8fc
commit
203babcde2
@ -13,3 +13,20 @@ Visit all nodes with shortest path
|
|||||||
3. Set next node to current node
|
3. Set next node to current node
|
||||||
6. Otherwise:
|
6. Otherwise:
|
||||||
1. Return with current stack
|
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)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
mod graph;
|
mod graph;
|
||||||
mod utils;
|
mod utils;
|
||||||
mod part1;
|
mod part1;
|
||||||
|
mod part2;
|
||||||
|
|
||||||
type Graph = graph::Graph<Location, Distance>;
|
type Graph = graph::Graph<Location, Distance>;
|
||||||
type Node = graph::Node<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)?;
|
utils::write_dot(&directions, file_path)?;
|
||||||
|
|
||||||
println!("\tPart 1: {:?}", part1::solve(&directions));
|
println!("\tPart 1: {:?}", part1::solve(&directions));
|
||||||
|
println!("\tPart 2: {:?}", part2::solve(&directions));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
74
2015/day-09/src/part2.rs
Normal file
74
2015/day-09/src/part2.rs
Normal 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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user