part1
This commit is contained in:
parent
3b27d3b309
commit
6dbab8bf54
146
20/day20.rs
Normal file
146
20/day20.rs
Normal file
@ -0,0 +1,146 @@
|
||||
use std::io::{self, BufRead};
|
||||
use std::convert::TryInto;
|
||||
// use num::Integer;
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
|
||||
type Pulse = u8;
|
||||
const LOW: Pulse = 0;
|
||||
const HIGH: Pulse = 1;
|
||||
|
||||
trait Module {
|
||||
fn get_pulse(&mut self, from: u16, pulse: Pulse) -> Option<Pulse>;
|
||||
fn add_input(&mut self, input: u16) {}
|
||||
fn get_connections(&self) -> &Vec<u16>;
|
||||
}
|
||||
#[derive(Clone)]
|
||||
struct FlipFlop {
|
||||
name: u16,
|
||||
modules: Vec<u16>,
|
||||
state: Pulse,
|
||||
}
|
||||
impl Module for FlipFlop {
|
||||
fn get_pulse(&mut self, from: u16, pulse: Pulse) -> Option<Pulse> {
|
||||
if pulse == LOW {
|
||||
self.state ^= HIGH;
|
||||
return Some(self.state);
|
||||
}
|
||||
None
|
||||
}
|
||||
fn get_connections(&self) -> &Vec<u16> { return &self.modules; }
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Conjunction {
|
||||
name: u16,
|
||||
modules: Vec<u16>,
|
||||
state: Pulse,
|
||||
last_inputs: HashMap<u16, Pulse>,
|
||||
}
|
||||
impl Module for Conjunction {
|
||||
fn get_pulse(&mut self, from: u16, pulse: Pulse) -> Option<Pulse> {
|
||||
self.last_inputs.iter().for_each(|(k, v)| print!("{}: {},", k, v));
|
||||
println!();
|
||||
if !self.last_inputs.contains_key(&from) {
|
||||
panic!("Conjunction got unexpected impulse from {}", from);
|
||||
}
|
||||
*self.last_inputs.get_mut(&from).unwrap() = pulse;
|
||||
if self.last_inputs.iter().all(|(k,v)| *v == HIGH) { self.state = LOW; }
|
||||
else { self.state = HIGH; }
|
||||
return Some(self.state)
|
||||
}
|
||||
fn add_input(&mut self, input: u16) {
|
||||
self.last_inputs.insert(input, LOW);
|
||||
}
|
||||
fn get_connections(&self) -> &Vec<u16> { return &self.modules; }
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Start {
|
||||
name: u16,
|
||||
modules: Vec<u16>,
|
||||
state: Pulse,
|
||||
}
|
||||
impl Module for Start {
|
||||
fn get_pulse(&mut self, from: u16, pulse: Pulse) -> Option<Pulse> {
|
||||
self.state = pulse;
|
||||
return Some(self.state)
|
||||
}
|
||||
fn get_connections(&self) -> &Vec<u16> { return &self.modules; }
|
||||
}
|
||||
|
||||
|
||||
fn make_index(s: &str) -> u16 {
|
||||
println!("{}", s);
|
||||
if s.len() == 2 {
|
||||
let mut t: u16 = 0;
|
||||
s.as_bytes().iter().enumerate().for_each(|(i, c)| t |= (*c as u16) << i*8);
|
||||
return t;
|
||||
}
|
||||
return 0
|
||||
}
|
||||
fn from_index(i: u16) -> char {
|
||||
if i == 0 { return 'B' }
|
||||
let mut c: u8 = i as u8;
|
||||
c |= i.overflowing_shr(8).0 as u8;
|
||||
return c as char
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = "input.txt";
|
||||
// let input = "example.txt";
|
||||
// let input = "example2.txt";
|
||||
let mut lines = read_lines(&input);
|
||||
let mut modules = HashMap::<u16, Box<dyn Module>>::new();
|
||||
for line in lines.map(|r| r.ok().unwrap()) {
|
||||
let dash = line.find('-').unwrap();
|
||||
let module = make_index(&line[1..dash-1]);
|
||||
println!("{module}");
|
||||
let connected_modules = line[dash+2..].split(',').map(|s| make_index(&s[1..])).collect();
|
||||
let _ = match line.chars().next().unwrap() {
|
||||
'&' => modules.insert(module, Box::new(Conjunction{name:module, modules: connected_modules, state: LOW, last_inputs: HashMap::new()})),
|
||||
'%' => modules.insert(module, Box::new(FlipFlop{name:module, modules: connected_modules, state: LOW})),
|
||||
_ => modules.insert(module, Box::new(Start{name:module, modules: connected_modules, state: LOW})),
|
||||
};
|
||||
}
|
||||
let keys = modules.keys().map(|k| *k).collect::<Vec<u16>>().clone();
|
||||
for n in keys.iter() {
|
||||
let connected_modules = modules[n].get_connections().clone().iter().filter(|c| modules.contains_key(c)).map(|c| *c).collect::<Vec<u16>>();
|
||||
for c in connected_modules.iter() {
|
||||
let m = modules.get_mut(c).unwrap();
|
||||
m.add_input(*n);
|
||||
}
|
||||
}
|
||||
let mut modules2 = modules.clone();
|
||||
let mut queue: VecDeque::<(u16, Pulse)> = VecDeque::new();
|
||||
let mut lows: usize = 0;
|
||||
let mut highs: usize = 0;
|
||||
for i in 0..1000 {
|
||||
println!("{i}");
|
||||
queue.push_back((0, LOW));
|
||||
lows += 1;
|
||||
while !queue.is_empty() {
|
||||
let (from, pulse) = queue.pop_front().unwrap();
|
||||
if !modules.contains_key(&from) { continue; }
|
||||
for m in modules[&from].get_connections().clone().iter() {
|
||||
println!("{:6} -{} -> {}", from_index(from), pulse, from_index(*m));
|
||||
if pulse == LOW { lows += 1 } else { highs += 1 }
|
||||
if !modules.contains_key(m) { continue; }
|
||||
if let Some(new_pulse) = modules.get_mut(&m).unwrap().get_pulse(from, pulse) {
|
||||
queue.push_back((*m, new_pulse));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
println!("lows: {}, highs: {}", lows, highs);
|
||||
println!("lows * highs (1): {}", lows * highs);
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn read_lines<P>(filename: P) -> io::Lines<io::BufReader<std::fs::File>>
|
||||
where P: AsRef<std::path::Path>, {
|
||||
return match std::fs::File::open(filename) {
|
||||
Err(why) => panic!("Could not open file. {}", why),
|
||||
Ok(file) => std::io::BufReader::new(file).lines()
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user