Skip to content

Commit

Permalink
Day 20 puzzle 2
Browse files Browse the repository at this point in the history
  • Loading branch information
jhrcook committed Jan 16, 2024
1 parent ad415c5 commit b8f129d
Show file tree
Hide file tree
Showing 2 changed files with 101 additions and 16 deletions.
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
| 16 | [src/solutions/day16.rs](src/solutions/day16.rs) | ⭐️⭐️ |
| 17 | [src/solutions/day17.rs](src/solutions/day17.rs) | ⭐️⭐️ |
| 18 | [src/solutions/day18.rs](src/solutions/day18.rs) | ⭐️⭐️ |
| 19 | [src/solutions/day19.rs](src/solutions/day19.rs) | ⭐️ |
| 20 | [src/solutions/day20.rs](src/solutions/day20.rs) | ⭐️ |
| 19 | [src/solutions/day19.rs](src/solutions/day19.rs) | ⭐️ |
| 20 | [src/solutions/day20.rs](src/solutions/day20.rs) | ⭐️⭐️ |
<!-- | 21 | [src/solutions/day21.rs](src/solutions/day21.rs) | ⭐️⭐️ | -->
<!-- | 22 | [src/solutions/day22.rs](src/solutions/day22.rs) | ⭐️⭐️ | -->
<!-- | 23 | [src/solutions/day23.rs](src/solutions/day23.rs) | ⭐️⭐️ | -->
Expand All @@ -42,6 +42,9 @@ Used this Reddit post for Day 12 part 2: <https://www.reddit.com/r/adventofcode/

I implemented the algorithm described in this Reddit [post](https://www.reddit.com/r/adventofcode/comments/18k9ne5/comment/kdqp7jx/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button) for Day 17 ([Python code](https://topaz.github.io/paste/#XQAAAQCcAgAAAAAAAAAzHIoib6py7i/yVWhl9dSCjkM4GPHrtd8B89i40hrslkM0i9r9hxir+33uzZa01Y7HY/oCJMAoqvX6OLOsC224RKbiSlSU1U6sDn8KTPKvoKhtJCgPq4QDeXZl8oKQCyrAOP0g3rHGLO7gde4rqBUfOeNyypDl5CSgMF0ceJifzUGjB1OliVqXbO/Ydsmg77dYyTbWx89UvPTsZiijfyTYH7ybEz1UtsTx6VHFZ5zcAVDl7ClaQ7+4gn7tShBjy8XQ0s9XR6uWqgo3vPVBjj9Bf3UGCWSP8qYw9N4dZcLcnLbZQgRkBbK2s9a0Cl0XXD0ie4lmMxzz3pLE3i7GFFzUEv9/dNRee0hFwDsxRBK7ERsb8Xt+mYS+fyiltY71gJKfELcn9Eu3TJy2kI/k2o4YHLSGL20gXFLoE4CunCJ2f6iLMbyU/+WeeKUMZn4BQ72S3uZ4SAD9wV+H44NtZEq0I6qYBCrLX98ODOc6lTFAPjJWFmvpIv74Evkb))

I was lazy on part 2 of Day 20 and went looking for the answer without trying to really figure it out.
Used the logic described in this [notebook](https://github.com/derailed-dash/Advent-of-Code/blob/master/src/AoC_2023/Dazbo's_Advent_of_Code_2023.ipynb) to get the solution.

## Setup

```bash
Expand Down
110 changes: 96 additions & 14 deletions src/solutions/day20.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::data::load;
use crate::math_utils;
use std::collections::{HashMap, HashSet, VecDeque};
use thiserror::Error;

Expand All @@ -8,6 +9,8 @@ pub enum PuzzleErr {
ParseInputError,
#[error("Runtime error")]
RuntimeError,
#[error("An expectation required for Part 2 was violated")]
Part2ExpectationViolated,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -285,12 +288,13 @@ impl PulseCounter {
}

pub fn puzzle_1(input: &str, n_button_presses: u32) -> Result<u32, PuzzleErr> {
// Parse modules from input.
let mut modules = parse_input(input)?;
modules
.iter()
.for_each(|(name, module)| log::info!("{} -> {:?}", name, module));

// Tracker for the total number of pulses.
let mut pulse_counter = PulseCounter::new();

// Perform button presses.
for _ in 0..n_button_presses {
let mut pulses = VecDeque::from_iter([PulseMsg {
from: "button".to_string(),
Expand All @@ -300,25 +304,24 @@ pub fn puzzle_1(input: &str, n_button_presses: u32) -> Result<u32, PuzzleErr> {
pulse_counter.low += 1;
while !pulses.is_empty() {
let pulse = pulses.pop_front().unwrap();
log::debug!("PULSE: {:?}", pulse);
log::trace!("PULSE: {:?}", pulse);
if let Some(response) = match modules.get_mut(&pulse.to) {
Some(Module::B(b)) => b.receive(&pulse),
Some(Module::C(c)) => c.receive(&pulse),
Some(Module::F(f)) => f.receive(&pulse),
Some(Module::O(o)) => o.receive(&pulse),
None => None,
} {
log::debug!("Received {} responses.", response.len());
log::trace!("Received {} responses.", response.len());
response.into_iter().for_each(|r| {
log::trace!("RESPONSE: {:?}", r);
pulse_counter.track(&r);
pulses.push_back(r);
});
} else {
log::debug!("No responses.")
}
}
}

log::info!(
"Final counts: {} low, {} high",
pulse_counter.low,
Expand All @@ -327,12 +330,91 @@ pub fn puzzle_1(input: &str, n_button_presses: u32) -> Result<u32, PuzzleErr> {
Ok(pulse_counter.low * pulse_counter.high)
}

pub fn puzzle_2(input: &str) -> Result<u64, PuzzleErr> {
// Parse modules from input.
let mut modules = parse_input(input)?;

// Get the input module for "rx" module.
let rx_input = modules
.values()
.filter(|m| match m {
Module::C(c) => c.receivers.contains(&"rx".to_string()),
_ => false,
})
.collect::<Vec<_>>()
.first()
.cloned()
.unwrap();
log::info!("'rx' module input: {:?}", rx_input);

// Dict for the memory inputs of the "rx" input.
// Will count how many button presses until set "HIGH".
let rx_input_inputs = match rx_input {
Module::C(c) => Ok(c.memory.keys().cloned().collect::<HashSet<_>>()),
_ => Err(PuzzleErr::Part2ExpectationViolated),
}?;
log::info!("inputs to 'rx' input: {:?}", rx_input_inputs);
let mut rx_input_presses = HashMap::<String, u32>::new();

for num_presses in 1..u32::MAX {
let mut pulses = VecDeque::from_iter([PulseMsg {
from: "button".to_string(),
to: "broadcaster".to_string(),
pulse: Pulse::Low,
}]);
while !pulses.is_empty() {
let pulse = pulses.pop_front().unwrap();

// Record num. button presses for HIGH pulses from inputs to input of "rx".
if (pulse.pulse == Pulse::High)
& rx_input_inputs.contains(&pulse.from)
& !rx_input_presses.contains_key(&pulse.from)
{
log::info!(
"Recording {} presses for module {}",
num_presses,
pulse.from
);
rx_input_presses.insert(pulse.from.clone(), num_presses);
}

// All inputs to the input for "rx" found a HIGH pulse.
if rx_input_inputs
.iter()
.all(|i| rx_input_presses.contains_key(i))
{
log::info!(
"Found button presses for all 'rx' input inputs: {:?}.",
rx_input_presses
);
return Ok(math_utils::lcm(
rx_input_presses
.values()
.map(|x| *x as u64)
.collect::<Vec<_>>(),
));
}

// Send pulse and add responses to queue.
if let Some(response) = match modules.get_mut(&pulse.to) {
Some(Module::B(b)) => b.receive(&pulse),
Some(Module::C(c)) => c.receive(&pulse),
Some(Module::F(f)) => f.receive(&pulse),
Some(Module::O(o)) => o.receive(&pulse),
None => None,
} {
response.into_iter().for_each(|r| pulses.push_back(r));
}
}
}
unreachable!();
}

pub fn main(data_dir: &str) {
println!("Day 20: Pulse Propagation");
let data = load(data_dir, 20, None);

// Puzzle 1.
let _ = env_logger::try_init();
let answer_1 = puzzle_1(&data, 1000);
match answer_1 {
Ok(x) => println!(" Puzzle 1: {}", x),
Expand All @@ -341,10 +423,10 @@ pub fn main(data_dir: &str) {
assert_eq!(answer_1, Ok(944750144));

// Puzzle 2.
// let answer_2 = puzzle_2(&data);
// match answer_2 {
// Ok(x) => println!(" Puzzle 2: {}", x),
// Err(e) => panic!("No solution to puzzle 2: {}", e),
// }
// assert_eq!(answer_2, Ok(30449))
let answer_2 = puzzle_2(&data);
match answer_2 {
Ok(x) => println!(" Puzzle 2: {}", x),
Err(e) => panic!("No solution to puzzle 2: {}", e),
}
assert_eq!(answer_2, Ok(222718819437131))
}

0 comments on commit b8f129d

Please sign in to comment.