From c42cfea92444fdb7b8d0b8c65eca9b6568c9298f Mon Sep 17 00:00:00 2001 From: Patrick Auernig Date: Sat, 13 Feb 2021 03:28:35 +0100 Subject: [PATCH] Clean up code for 2015 day 09 - Remove unnecessary path from DFS - Take filenames as command line arguments - Update notes --- 2015/day-09/notes.md | 9 ++++----- 2015/day-09/src/main.rs | 18 ++++++++---------- 2015/day-09/src/part1.rs | 5 +++-- 2015/day-09/src/part2.rs | 31 +++++++++---------------------- 4 files changed, 24 insertions(+), 39 deletions(-) diff --git a/2015/day-09/notes.md b/2015/day-09/notes.md index 5718feb..8f47748 100644 --- a/2015/day-09/notes.md +++ b/2015/day-09/notes.md @@ -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 diff --git a/2015/day-09/src/main.rs b/2015/day-09/src/main.rs index fcabb73..e002e89 100644 --- a/2015/day-09/src/main.rs +++ b/2015/day-09/src/main.rs @@ -9,14 +9,12 @@ type Node = graph::Node; type Location = String; type Distance = u64; -const FILE_PATHS: &[&str] = &[ - "inputs/test.txt", - "inputs/puzzle.txt", -]; - fn main() -> Result<(), Box> { - for file_path in FILE_PATHS { - println!("File: {}", file_path); + use std::env; + + let file_paths = env::args().skip(1).collect::>(); + + 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> { 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(()) diff --git a/2015/day-09/src/part1.rs b/2015/day-09/src/part1.rs index a601216..f6ce59d 100644 --- a/2015/day-09/src/part1.rs +++ b/2015/day-09/src/part1.rs @@ -3,6 +3,7 @@ use crate::{Distance, Graph, Node}; type NodeSet = HashSet; +// 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 { +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 { }; } - shortest_distance + shortest_distance.unwrap_or_default() } diff --git a/2015/day-09/src/part2.rs b/2015/day-09/src/part2.rs index 503968e..d5dbc1a 100644 --- a/2015/day-09/src/part2.rs +++ b/2015/day-09/src/part2.rs @@ -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 { +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