Add another part 2 solution that needs massive optimization
This commit is contained in:
parent
38b84d497e
commit
ca251d9352
@ -47,3 +47,49 @@ ZZZ = (ZZZ, ZZZ)
|
||||
```
|
||||
|
||||
Starting at AAA, follow the left/right instructions. **How many steps are required to reach ZZZ**?
|
||||
|
||||
## Part 2
|
||||
|
||||
The sandstorm is upon you and you aren't any closer to escaping the wasteland. You had the camel follow the
|
||||
instructions, but you've barely left your starting position. It's going to take **significantly more steps** to escape!
|
||||
|
||||
What if the map isn't for people - what if the map is for **ghosts?** Are ghosts even bound by the laws of spacetime?
|
||||
Only one way to find out.
|
||||
|
||||
After examining the maps a bit longer, your attention is drawn to a curious fact: the number of nodes with names
|
||||
ending in A is equal to the number ending in Z! If you were a ghost, you'd probably just **start at every node that
|
||||
ends with A** and follow all of the paths at the same time until they all simultaneously end up at nodes that end with
|
||||
`Z`.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)
|
||||
```
|
||||
|
||||
Here, there are two starting nodes, 11A and 22A (because they both end with A). As you follow each left/right
|
||||
instruction, use that instruction to **simultaneously** navigate away from both nodes you're currently on. Repeat this
|
||||
process until **all** of the nodes you're currently on end with Z. (If only some of the nodes you're on end with Z, they
|
||||
act like any other node and you continue as normal.) In this example, you would proceed as follows:
|
||||
|
||||
- Step 0: You are at `11A` and `22A`.`
|
||||
- Step 1: You choose all of the **left** paths, leading you to `11B` and `22B`.
|
||||
- Step 2: You choose all of the **right** paths, leading you to **11Z** and `22C`.
|
||||
- Step 3: You choose all of the left paths, leading you to `11B` and **22Z**.
|
||||
- Step 4: You choose all of the right paths, leading you to **11Z** and `22B`.
|
||||
- Step 5: You choose all of the left paths, leading you to `11B` and `22C`.
|
||||
- Step 6: You choose all of the right paths, leading you to **11Z** and **22Z**.
|
||||
|
||||
So, in this example, you end up entirely on nodes that end in Z after **6** steps.
|
||||
|
||||
Simultaneously start on every node that ends with A.
|
||||
**How many steps does it take before you're only on nodes that end with `Z`?**
|
||||
|
10
2023/day8/src/example-input2.txt
Normal file
10
2023/day8/src/example-input2.txt
Normal file
@ -0,0 +1,10 @@
|
||||
LR
|
||||
|
||||
11A = (11B, XXX)
|
||||
11B = (XXX, 11Z)
|
||||
11Z = (11B, XXX)
|
||||
22A = (22B, XXX)
|
||||
22B = (22C, 22C)
|
||||
22C = (22Z, 22Z)
|
||||
22Z = (22B, 22B)
|
||||
XXX = (XXX, XXX)
|
@ -86,6 +86,37 @@ impl Network {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn count_steps_part_two(&self) -> usize {
|
||||
let mut count = 0usize;
|
||||
let mut next_keys: Vec<_> = self.map.keys().filter(|k| k.ends_with('A')).collect();
|
||||
let mut current: Vec<_> = next_keys
|
||||
.iter()
|
||||
.map(|k| self.map.get(*k).unwrap())
|
||||
.collect();
|
||||
|
||||
loop {
|
||||
for x in self.direction_list.iter() {
|
||||
count += 1;
|
||||
next_keys = current
|
||||
.iter()
|
||||
.map(|c| match x {
|
||||
Direction::Left => &c.0,
|
||||
Direction::Right => &c.1,
|
||||
})
|
||||
.collect();
|
||||
|
||||
if next_keys.iter().all(|k| k.ends_with('Z')) {
|
||||
return count;
|
||||
}
|
||||
|
||||
current = next_keys
|
||||
.iter()
|
||||
.map(|k| self.map.get(*k).unwrap())
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn part_one() {
|
||||
@ -95,18 +126,36 @@ fn part_one() {
|
||||
println!("Part 1: Step count from AAA to ZZZ {}", step_count);
|
||||
}
|
||||
|
||||
fn part_two() {
|
||||
let network = Network::parse(FILE_STR);
|
||||
let step_count = network.count_steps_part_two();
|
||||
|
||||
println!(
|
||||
"Part 2: Step count for steps to locations ending in Z {}",
|
||||
step_count
|
||||
);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
part_one();
|
||||
part_two();
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
const EXAMPLE_FILE_STR: &str = include_str!("example-input.txt");
|
||||
const EXAMPLE2_FILE_STR: &str = include_str!("example-input2.txt");
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn first_example() {
|
||||
fn part_one_example() {
|
||||
let network = Network::parse(EXAMPLE_FILE_STR);
|
||||
assert_eq!(6, network.count_steps());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn part_two_example() {
|
||||
let network = Network::parse(EXAMPLE2_FILE_STR);
|
||||
assert_eq!(6, network.count_steps_part_two());
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user