generated from janezicmatej/aoc-template
	wip: part 1 debugging
This commit is contained in:
		| @@ -0,0 +1,5 @@ | ||||
| broadcaster -> a, b, c | ||||
| %a -> b | ||||
| %b -> c | ||||
| %c -> inv | ||||
| &inv -> a | ||||
|   | ||||
							
								
								
									
										149
									
								
								src/bin/20.rs
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								src/bin/20.rs
									
									
									
									
									
								
							| @@ -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)] | ||||
| enum Module { | ||||
|     Broadcaster, | ||||
|     FlipFlop, | ||||
|     FlipFlop(bool), | ||||
|     Conjuction, | ||||
| } | ||||
|  | ||||
| @@ -14,7 +19,7 @@ impl FromStr for Module { | ||||
|     type Err = ParseModuleError; | ||||
|     fn from_str(s: &str) -> Result<Self, Self::Err> { | ||||
|         Ok(match s { | ||||
|             "%" => Module::FlipFlop, | ||||
|             "%" => Module::FlipFlop(false), | ||||
|             "&" => Module::Conjuction, | ||||
|             _ => Module::Broadcaster, | ||||
|         }) | ||||
| @@ -22,16 +27,37 @@ impl FromStr for Module { | ||||
| } | ||||
|  | ||||
| #[derive(Debug)] | ||||
| struct Location { | ||||
| struct Node { | ||||
|     index: usize, | ||||
|     module: Module, | ||||
|     inputs: HashMap<String, Option<bool>>, | ||||
|     outputs: Vec<String>, | ||||
|     inputs: Vec<usize>, | ||||
|     outputs: Vec<usize>, | ||||
| } | ||||
|  | ||||
| fn parse_input(input: &str) -> (Vec<Location>, HashMap<String, usize>) { | ||||
|     let mut locations = Vec::new(); | ||||
| fn parse_input(input: &str) -> Vec<Node> { | ||||
|     let mut nodes = Vec::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() { | ||||
|         let (from, to) = line.split_once(" -> ").unwrap(); | ||||
|         let (module, mut name) = from.split_at(1); | ||||
| @@ -40,53 +66,96 @@ fn parse_input(input: &str) -> (Vec<Location>, HashMap<String, usize>) { | ||||
|             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]; | ||||
|             locations[index] | ||||
|                 .inputs | ||||
|                 .entry(destination.to_string()) | ||||
|                 .or_default(); | ||||
|         for destination in to.split(", ") { | ||||
|             let to_index = mapper[destination]; | ||||
|             nodes[index].outputs.push(to_index); | ||||
|             nodes[to_index].inputs.push(index); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     (locations, mapper) | ||||
|     nodes | ||||
| } | ||||
|  | ||||
| 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 low = 0; | ||||
|     let mut graph = vec![vec![None; input.len()]; input.len()]; | ||||
|  | ||||
|     let mut highs = 0; | ||||
|     let mut lows = 0; | ||||
|  | ||||
|     let broadcaster = nodes | ||||
|         .iter() | ||||
|         .find(|x| x.module == Module::Broadcaster)? | ||||
|         .index; | ||||
|  | ||||
|     for _ in 0..1000 { | ||||
|         let mut stack = vec!["broadcaster".to_string()]; | ||||
|         let mut stack = VecDeque::from([broadcaster]); | ||||
|         while !stack.is_empty() { | ||||
|             let mut new_stack = Vec::new(); | ||||
|             let mut new_stack = VecDeque::new(); | ||||
|  | ||||
|             while let Some(s) = stack.pop() { | ||||
|                 let index = mapper[&s]; | ||||
|                 let loc = &locations[index]; | ||||
|             while let Some(index) = stack.pop_front() { | ||||
|                 let node = &nodes[index]; | ||||
|                 let mut new_module = None; | ||||
|  | ||||
|                 match loc.module { | ||||
|                 match node.module { | ||||
|                     Module::Broadcaster => { | ||||
|                         for dest in loc.outputs.iter() { | ||||
|                             let index = mapper[dest]; | ||||
|                             let loc = &locations[index]; | ||||
|                         for dest_index in node.outputs.iter() { | ||||
|                             graph[index][*dest_index] = Some(false); | ||||
|                             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> { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user