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:
Patrick Auernig 2021-02-13 03:28:35 +01:00
parent a7fd384bac
commit c42cfea924
4 changed files with 24 additions and 39 deletions

View File

@ -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

View File

@ -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(())

View File

@ -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()
}

View File

@ -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