mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 18:29:55 +00:00
Day 6 part 2
This commit is contained in:
parent
69c072e211
commit
102a98fc82
1 changed files with 64 additions and 2 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue