wip: part 1 debugging

This commit is contained in:
Matej Janezic 2023-12-20 12:30:22 +01:00
parent 0000037022
commit 00000380c1
Signed by: janezicmatej
GPG Key ID: 4298E230ED37B2C0
2 changed files with 114 additions and 40 deletions

View File

@ -0,0 +1,5 @@
broadcaster -> a, b, c
%a -> b
%b -> c
%c -> inv
&inv -> a

View File

@ -1,9 +1,14 @@
use std::{collections::HashMap, str::FromStr}; use std::{
collections::{HashMap, VecDeque},
mem::swap,
process::Output,
str::FromStr,
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
enum Module { enum Module {
Broadcaster, Broadcaster,
FlipFlop, FlipFlop(bool),
Conjuction, Conjuction,
} }
@ -14,7 +19,7 @@ impl FromStr for Module {
type Err = ParseModuleError; type Err = ParseModuleError;
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s { Ok(match s {
"%" => Module::FlipFlop, "%" => Module::FlipFlop(false),
"&" => Module::Conjuction, "&" => Module::Conjuction,
_ => Module::Broadcaster, _ => Module::Broadcaster,
}) })
@ -22,16 +27,37 @@ impl FromStr for Module {
} }
#[derive(Debug)] #[derive(Debug)]
struct Location { struct Node {
index: usize,
module: Module, module: Module,
inputs: HashMap<String, Option<bool>>, inputs: Vec<usize>,
outputs: Vec<String>, outputs: Vec<usize>,
} }
fn parse_input(input: &str) -> (Vec<Location>, HashMap<String, usize>) { fn parse_input(input: &str) -> Vec<Node> {
let mut locations = Vec::new(); let mut nodes = Vec::new();
let mut mapper: HashMap<String, usize> = HashMap::new(); let mut mapper: HashMap<String, usize> = HashMap::new();
for line in input.lines() {
let (from, _) = line.split_once(" -> ").unwrap();
let (module, mut name) = from.split_at(1);
let module: Module = module.parse().unwrap();
if module == Module::Broadcaster {
name = from;
}
*mapper.entry(name.to_string()).or_default() = nodes.len();
let l = Node {
module,
index: nodes.len(),
inputs: Vec::new(),
outputs: Vec::new(),
};
nodes.push(l);
}
for line in input.lines() { for line in input.lines() {
let (from, to) = line.split_once(" -> ").unwrap(); let (from, to) = line.split_once(" -> ").unwrap();
let (module, mut name) = from.split_at(1); let (module, mut name) = from.split_at(1);
@ -40,53 +66,96 @@ fn parse_input(input: &str) -> (Vec<Location>, HashMap<String, usize>) {
name = from; name = from;
} }
let l = Location {
module,
inputs: HashMap::new(),
outputs: to.split(", ").map(String::from).collect(),
};
locations.push(l);
*mapper.entry(name.to_string()).or_default() = locations.len() - 1;
}
for line in input.lines() {
let (from, to) = line.split_once(" -> ").unwrap();
let (_, name) = from.split_at(1);
for destination in to.split(", ") {
let index = mapper[name]; let index = mapper[name];
locations[index] for destination in to.split(", ") {
.inputs let to_index = mapper[destination];
.entry(destination.to_string()) nodes[index].outputs.push(to_index);
.or_default(); nodes[to_index].inputs.push(index);
} }
} }
(locations, mapper) nodes
} }
pub fn part_one(input: &str) -> Option<usize> { pub fn part_one(input: &str) -> Option<usize> {
let (locations, mapper) = parse_input(input); let mut nodes = parse_input(input);
let mut high = 0; let mut graph = vec![vec![None; input.len()]; input.len()];
let mut low = 0;
let mut highs = 0;
let mut lows = 0;
let broadcaster = nodes
.iter()
.find(|x| x.module == Module::Broadcaster)?
.index;
for _ in 0..1000 { for _ in 0..1000 {
let mut stack = vec!["broadcaster".to_string()]; let mut stack = VecDeque::from([broadcaster]);
while !stack.is_empty() { while !stack.is_empty() {
let mut new_stack = Vec::new(); let mut new_stack = VecDeque::new();
while let Some(s) = stack.pop() { while let Some(index) = stack.pop_front() {
let index = mapper[&s]; let node = &nodes[index];
let loc = &locations[index]; let mut new_module = None;
match loc.module { match node.module {
Module::Broadcaster => { Module::Broadcaster => {
for dest in loc.outputs.iter() { for dest_index in node.outputs.iter() {
let index = mapper[dest]; graph[index][*dest_index] = Some(false);
let loc = &locations[index]; new_stack.push_back(*dest_index);
lows += 1;
} }
} }
Module::FlipFlop(high) => {
let mut swapper = None;
for in_index in nodes[index].inputs.iter() {
let value = &mut graph[*in_index][index];
if value.is_some() {
debug_assert!(swapper.is_none());
swap(&mut swapper, value);
}
}
if !swapper.unwrap() {
let signal = !high;
for dest_index in nodes[index].outputs.iter() {
graph[index][*dest_index] = Some(signal);
new_stack.push_back(*dest_index);
if signal {
highs += 1;
} else {
lows += 1;
}
}
new_module = Some(Module::FlipFlop(signal));
}
}
Module::Conjuction => {
let mut all = true;
for in_index in nodes[index].inputs.iter() {
let value = graph[*in_index][index];
all &= value.unwrap_or(false);
}
for dest_index in nodes[index].outputs.iter() {
graph[index][*dest_index] = Some(!all);
new_stack.push_back(*dest_index);
if !all {
highs += 1;
} else {
lows += 1;
}
}
}
}
let node = &mut nodes[index];
if let Some(module) = new_module {
node.module = module;
} }
} }
@ -94,7 +163,7 @@ pub fn part_one(input: &str) -> Option<usize> {
} }
} }
Some(high * low) Some(highs * lows)
} }
pub fn part_two(input: &str) -> Option<u32> { pub fn part_two(input: &str) -> Option<u32> {