Clean up code for 2015 day 09
- Remove unnecessary path from DFS - Take filenames as command line arguments - Update notes
This commit is contained in:
parent
a7fd384bac
commit
c42cfea924
@ -24,9 +24,8 @@ Visit all nodes with longest path
|
||||
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
|
||||
5. Add edge weight to local length
|
||||
6. Recursively repeat steps 3 to 7 with outgoing nodes until all were visited
|
||||
7. 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)
|
||||
9. Reset local length for next node
|
||||
|
@ -9,14 +9,12 @@ type Node = graph::Node<Location, Distance>;
|
||||
type Location = String;
|
||||
type Distance = u64;
|
||||
|
||||
const FILE_PATHS: &[&str] = &[
|
||||
"inputs/test.txt",
|
||||
"inputs/puzzle.txt",
|
||||
];
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
for file_path in FILE_PATHS {
|
||||
println!("File: {}", file_path);
|
||||
use std::env;
|
||||
|
||||
let file_paths = env::args().skip(1).collect::<Vec<_>>();
|
||||
|
||||
for file_path in &file_paths {
|
||||
let locations = utils::parse_file(file_path)?;
|
||||
|
||||
let mut directions = Graph::default();
|
||||
@ -25,10 +23,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
directions.add_edge(location);
|
||||
}
|
||||
|
||||
utils::write_dot(&directions, file_path)?;
|
||||
utils::write_dot(&directions, &file_path)?;
|
||||
|
||||
println!("\tPart 1: {:?}", part1::solve(&directions));
|
||||
println!("\tPart 2: {:?}", part2::solve(&directions));
|
||||
println!("{} / solution 1 = {:?}", file_path, part1::solve(&directions));
|
||||
println!("{} / solution 2 = {:?}", file_path, part2::solve(&directions));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -3,6 +3,7 @@ use crate::{Distance, Graph, Node};
|
||||
|
||||
type NodeSet = HashSet<Node>;
|
||||
|
||||
// Only works with complete graphs (where each node leads to each other node)
|
||||
fn visit_all_shortest(start_node: &Node) -> Vec<(Node, Distance)> {
|
||||
let mut visited = NodeSet::new();
|
||||
let mut path = Vec::new();
|
||||
@ -45,7 +46,7 @@ fn visit_all_shortest(start_node: &Node) -> Vec<(Node, Distance)> {
|
||||
}
|
||||
|
||||
/// Find shortest path that connects two points and visits all locations.
|
||||
pub fn solve(directions: &Graph) -> Option<Distance> {
|
||||
pub fn solve(directions: &Graph) -> Distance {
|
||||
use std::cmp::min;
|
||||
|
||||
let mut shortest_distance = None;
|
||||
@ -64,5 +65,5 @@ pub fn solve(directions: &Graph) -> Option<Distance> {
|
||||
};
|
||||
}
|
||||
|
||||
shortest_distance
|
||||
shortest_distance.unwrap_or_default()
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ 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<'_>) {
|
||||
@ -17,15 +16,12 @@ fn depth_first_search(node: &Node, memo: Memo<'_>) {
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
|
||||
@ -37,37 +33,28 @@ fn depth_first_search(node: &Node, memo: Memo<'_>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_all_longest(start_node: &Node) -> Vec<(Node, Distance)> {
|
||||
fn visit_all_longest(start_node: &Node) -> Distance {
|
||||
let mut visited = NodeSet::new();
|
||||
let mut path = Vec::new();
|
||||
|
||||
let mut distance = 0;
|
||||
|
||||
depth_first_search(&start_node, Memo {
|
||||
max_dist: &mut 0,
|
||||
max_dist: &mut distance,
|
||||
prev_dist: 0,
|
||||
visited: &mut visited,
|
||||
path: &mut path
|
||||
});
|
||||
|
||||
path
|
||||
distance
|
||||
}
|
||||
|
||||
pub fn solve(directions: &Graph) -> Option<Distance> {
|
||||
pub fn solve(directions: &Graph) -> Distance {
|
||||
use std::cmp::max;
|
||||
|
||||
let mut longest_distance = None;
|
||||
let mut longest_distance = 0;
|
||||
|
||||
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)),
|
||||
};
|
||||
let distance = visit_all_longest(node);
|
||||
longest_distance = max(distance, longest_distance);
|
||||
}
|
||||
|
||||
longest_distance
|
||||
|
Loading…
Reference in New Issue
Block a user