Skip to content

Commit

Permalink
Complete day 20
Browse files Browse the repository at this point in the history
  • Loading branch information
Riari committed Dec 21, 2023
1 parent 9b11e8f commit 670f135
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 21 deletions.
2 changes: 1 addition & 1 deletion data/examples/20.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ broadcaster -> a
%a -> inv, con
&inv -> b
%b -> con
&con -> output
&con -> rx
15 changes: 13 additions & 2 deletions data/puzzles/20.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,19 @@ In the second example, after pushing the button `1000` times, `4250` low pulses

Consult your module configuration; determine the number of low pulses and high pulses that would be sent after pushing the button `1000` times, waiting for all pulses to be fully handled after each push of the button. *What do you get if you multiply the total number of low pulses sent by the total number of high pulses sent?*

To begin, [get your puzzle input](20/input).
Your puzzle answer was `839775244`.

The first half of this puzzle is complete! It provides one gold star: \*

\--- Part Two ---
----------

The final machine responsible for moving the sand down to Island Island has a module attached named `rx`. The machine turns on when a *single low pulse* is sent to `rx`.

Reset all modules to their default states. Waiting for all pulses to be fully handled after each button press, *what is the fewest number of button presses required to deliver a single low pulse to the module named `rx`?*

Answer:

You can also [Shareon [Twitter](https://twitter.com/intent/tweet?text=%22Pulse+Propagation%22+%2D+Day+20+%2D+Advent+of+Code+2023&url=https%3A%2F%2Fadventofcode%2Ecom%2F2023%2Fday%2F20&related=ericwastl&hashtags=AdventOfCode) [Mastodon](javascript:void(0);)] this puzzle.
Although it hasn't changed, you can still [get your puzzle input](20/input).

You can also [Shareon [Twitter](https://twitter.com/intent/tweet?text=I%27ve+completed+Part+One+of+%22Pulse+Propagation%22+%2D+Day+20+%2D+Advent+of+Code+2023&url=https%3A%2F%2Fadventofcode%2Ecom%2F2023%2Fday%2F20&related=ericwastl&hashtags=AdventOfCode) [Mastodon](javascript:void(0);)] this puzzle.
77 changes: 59 additions & 18 deletions src/bin/20.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use std::collections::{HashMap, HashSet, VecDeque};
use itertools::Itertools;
use advent_of_code::lcm_of_vec;

advent_of_code::solution!(20);

Expand Down Expand Up @@ -27,7 +29,7 @@ impl Module for FlipFlop {
if input == HI {
return false;
}

self.state = if self.state == LO { HI } else { LO };
true
}
Expand Down Expand Up @@ -58,7 +60,7 @@ impl Module for Conjunction {
self.lo_senders.insert(module.clone());
self.hi_senders.remove(module);
}

self.output = if self.hi_senders.len() == self.inputs.len() { LO } else { HI };
true
}
Expand Down Expand Up @@ -120,7 +122,7 @@ fn parse(input: &str) -> (ModuleMap, ConnectionMap) {
identifier.to_string(),
Box::new(Broadcast {
output: LO
}));
}));
connections.insert(identifier.to_string(), outputs);
} else {
panic!("Unknown module type: {}", identifier);
Expand All @@ -130,7 +132,6 @@ fn parse(input: &str) -> (ModuleMap, ConnectionMap) {
for (from, to) in connections.clone() {
for to_id in to {
if let Some(to_module) = modules.get_mut(&to_id) {
println!("Enabling {} to {}", from, to_id);
to_module.enable_input(&from);
}
}
Expand All @@ -139,44 +140,84 @@ fn parse(input: &str) -> (ModuleMap, ConnectionMap) {
(modules, connections)
}

pub fn part_one(input: &str) -> Option<u64> {
fn solve(input: &str, is_p2: bool) -> Option<u64> {
let (mut modules, connections) = parse(input);


let sender_to_rx: &String;
let mut cycle_map: HashMap<String, u64> = HashMap::new();
if is_p2 {
// The solution for part 2 assumes the following:
// - There is a single conjunction module that sends to rx
// - There are four conjunction modules that send to the one that sends to rx
// Therefore the solution can be solved by finding the LCM of the cycle counts of those four
// antepenultimate modules.

// sender_to_rx is the module that sends to rx
(sender_to_rx, _) = connections
.iter()
.find(|(_, outputs)| outputs.contains(&"rx".to_string()))
.unwrap();

// cycle_map is the map from each module that sends to sender-to-rx to the number of
// button presses it requires to send a high pulse
cycle_map = connections
.iter()
.filter(|(_, outputs)| outputs.contains(sender_to_rx))
.map(|(sender, _)| (sender.clone(), 0 as u64))
.collect();
}

// Queue of sending module, receiving module, value sent
let mut queue: VecDeque<(String, String, u8)> = VecDeque::new();

let mut hi_sent = 0;
let mut lo_sent = 0;
for _ in 0..1000 {
let end = if !is_p2 { 1000 } else { 1_000_000_000 };
let mut button_pushes = 0; // min number of button pushes before rx receives LO
for _ in 0..end {
queue.push_back(("button".to_string(), "broadcaster".to_string(), LO));
button_pushes += 1;
while !queue.is_empty() {
let (sender, receiver, value) = queue.pop_front().unwrap();
if value == HI {
hi_sent += 1;
} else {
lo_sent += 1;
}

if is_p2 {
if cycle_map.contains_key(&sender) && cycle_map[&sender] == 0 && value == HI {
cycle_map.insert(sender.clone(), button_pushes);
}

if !cycle_map.values().contains(&0) {
let cycles = cycle_map.values().cloned().collect_vec();
return Some(lcm_of_vec(cycles));
}
}

if let Some(module) = modules.get_mut(&receiver) {
if module.receive(&sender, value) {
let output = module.get_output();
for destination in connections.get(&receiver).unwrap() {
if value == HI {
hi_sent += 1;
} else {
lo_sent += 1;
}

queue.push_back((receiver.clone(), destination.clone(), output));
}
}
} else {
// println!("Unknown module: {}", sender);
}
}
}

dbg!(hi_sent, lo_sent);

// Part 1 output
Some(hi_sent * lo_sent)
}

pub fn part_one(input: &str) -> Option<u64> {
solve(input, false)
}

pub fn part_two(input: &str) -> Option<u64> {
None
solve(input, true)
}

#[cfg(test)]
Expand All @@ -192,6 +233,6 @@ mod tests {
#[test]
fn test_part_two() {
let result = part_two(&advent_of_code::template::read_file("examples", DAY));
assert_eq!(result, None);
assert_eq!(result, Some(1));
}
}

0 comments on commit 670f135

Please sign in to comment.