Day 6 part 2

This commit is contained in:
Wesley Moore 2019-12-07 16:43:18 +11:00
parent 69c072e211
commit 102a98fc82
No known key found for this signature in database
GPG key ID: BF67766C0BC2D0EE

View file

@ -14,6 +14,7 @@ fn main() -> io::Result<()> {
let orbits = parse_input(&input);
println!("Part 1: {}", number_of_orbits(&orbits));
println!("Part 2: {}", orbital_transfers(&orbits, "YOU", "SAN"));
Ok(())
}
@ -36,6 +37,32 @@ fn number_of_orbits(input: &[Orbit<'_>]) -> usize {
.sum()
}
fn orbital_transfers(input: &[Orbit<'_>], from: &str, to: &str) -> usize {
let nodes = build_tree(input);
// Find the to and from nodes
let from = nodes
.iter()
.find(|node| node.name == from)
.expect("unable to find from node");
let to = nodes
.iter()
.find(|node| node.name == to)
.expect("unable to find to node");
// Find the longest shared path they have on the way to COM and then the two remaining parts
// give the path between them.
let from_nodes_to_com = nodes_to_com(&nodes, from, Vec::new());
let to_nodes_to_com = nodes_to_com(&nodes, to, Vec::new());
let mut i = 0;
while from_nodes_to_com[i].name == to_nodes_to_com[i].name {
i += 1;
}
// - 2 since we don't count the path from 'from' to the object it's orbiting. Same for 'to'.
from_nodes_to_com[i..].len() + to_nodes_to_com[i..].len() - 2
}
fn build_tree<'a>(input: &'a [Orbit<'a>]) -> Vec<Node<'a>> {
// Build the tree from the input
let mut nodes: Vec<Node<'_>> = Vec::with_capacity(input.len());
@ -85,11 +112,25 @@ fn count_orbits(nodes: &[Node], node_index: usize, count: usize) -> usize {
}
}
fn nodes_to_com<'a>(
nodes: &'a [Node],
current_node: &'a Node,
mut path: Vec<&'a Node<'a>>,
) -> Vec<&'a Node<'a>> {
path.push(current_node);
if let Some(parent_index) = current_node.parent {
nodes_to_com(nodes, &nodes[parent_index], path)
} else {
path.reverse();
path
}
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_INPUT: &str = "B)C
const TEST_INPUT1: &str = "B)C
COM)B
C)D
D)E
@ -100,11 +141,32 @@ D)I
E)J
J)K
K)L
";
const TEST_INPUT2: &str = "COM)B
B)C
C)D
D)E
E)F
B)G
G)H
D)I
E)J
J)K
K)L
K)YOU
I)SAN
";
#[test]
fn test_number_of_orbits() {
let orbits = parse_input(TEST_INPUT);
let orbits = parse_input(TEST_INPUT1);
assert_eq!(number_of_orbits(&orbits), 42);
}
#[test]
fn test_orbital_transfers() {
let orbits = parse_input(TEST_INPUT2);
assert_eq!(orbital_transfers(&orbits, "YOU", "SAN"), 4);
}
}