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
|
2. Begin search at start node
|
||||||
3. Mark current node as visited
|
3. Mark current node as visited
|
||||||
4. Iterate through all outgoing nodes that are not marked as visited
|
4. Iterate through all outgoing nodes that are not marked as visited
|
||||||
5. Push node onto path
|
5. Add edge weight to local length
|
||||||
6. Add edge weight to local length
|
6. Recursively repeat steps 3 to 7 with outgoing nodes until all were visited
|
||||||
7. 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
|
||||||
8. When encountering a visited node compare max distance with local distance
|
|
||||||
1. Replace max distance with local distance if max distance is smaller
|
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 Location = String;
|
||||||
type Distance = u64;
|
type Distance = u64;
|
||||||
|
|
||||||
const FILE_PATHS: &[&str] = &[
|
|
||||||
"inputs/test.txt",
|
|
||||||
"inputs/puzzle.txt",
|
|
||||||
];
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
for file_path in FILE_PATHS {
|
use std::env;
|
||||||
println!("File: {}", file_path);
|
|
||||||
|
let file_paths = env::args().skip(1).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
for file_path in &file_paths {
|
||||||
let locations = utils::parse_file(file_path)?;
|
let locations = utils::parse_file(file_path)?;
|
||||||
|
|
||||||
let mut directions = Graph::default();
|
let mut directions = Graph::default();
|
||||||
@ -25,10 +23,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
directions.add_edge(location);
|
directions.add_edge(location);
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::write_dot(&directions, file_path)?;
|
utils::write_dot(&directions, &file_path)?;
|
||||||
|
|
||||||
println!("\tPart 1: {:?}", part1::solve(&directions));
|
println!("{} / solution 1 = {:?}", file_path, part1::solve(&directions));
|
||||||
println!("\tPart 2: {:?}", part2::solve(&directions));
|
println!("{} / solution 2 = {:?}", file_path, part2::solve(&directions));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -3,6 +3,7 @@ use crate::{Distance, Graph, Node};
|
|||||||
|
|
||||||
type NodeSet = HashSet<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)> {
|
fn visit_all_shortest(start_node: &Node) -> Vec<(Node, Distance)> {
|
||||||
let mut visited = NodeSet::new();
|
let mut visited = NodeSet::new();
|
||||||
let mut path = Vec::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.
|
/// 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;
|
use std::cmp::min;
|
||||||
|
|
||||||
let mut shortest_distance = None;
|
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,
|
max_dist: &'a mut Distance,
|
||||||
prev_dist: Distance,
|
prev_dist: Distance,
|
||||||
visited: &'a mut NodeSet,
|
visited: &'a mut NodeSet,
|
||||||
path: &'a mut Vec<(Node, Distance)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn depth_first_search(node: &Node, memo: Memo<'_>) {
|
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 {
|
for (out_node, out_weight) in &node.borrow().outgoing {
|
||||||
if !memo.visited.contains(&out_node) {
|
if !memo.visited.contains(&out_node) {
|
||||||
memo.path.push((out_node.clone(), *out_weight));
|
|
||||||
|
|
||||||
distance = memo.prev_dist + out_weight;
|
distance = memo.prev_dist + out_weight;
|
||||||
|
|
||||||
depth_first_search(&out_node, Memo {
|
depth_first_search(&out_node, Memo {
|
||||||
max_dist: &mut *memo.max_dist,
|
max_dist: &mut *memo.max_dist,
|
||||||
prev_dist: distance,
|
prev_dist: distance,
|
||||||
visited: &mut *memo.visited,
|
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 visited = NodeSet::new();
|
||||||
let mut path = Vec::new();
|
|
||||||
|
let mut distance = 0;
|
||||||
|
|
||||||
depth_first_search(&start_node, Memo {
|
depth_first_search(&start_node, Memo {
|
||||||
max_dist: &mut 0,
|
max_dist: &mut distance,
|
||||||
prev_dist: 0,
|
prev_dist: 0,
|
||||||
visited: &mut visited,
|
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;
|
use std::cmp::max;
|
||||||
|
|
||||||
let mut longest_distance = None;
|
let mut longest_distance = 0;
|
||||||
|
|
||||||
for node in &directions.nodes {
|
for node in &directions.nodes {
|
||||||
let path = visit_all_longest(node);
|
let distance = visit_all_longest(node);
|
||||||
|
longest_distance = max(distance, longest_distance);
|
||||||
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
|
longest_distance
|
||||||
|
Loading…
Reference in New Issue
Block a user