1use std::{collections::BTreeMap, str::FromStr};
2
3pub type Wires<T> = BTreeMap<String, T>;
4pub type Instructions<O> = Vec<LogicGate<O>>;
5
6#[derive(Debug)]
7pub struct LogicCircuit<T, O: Clone> {
8 pub wires: BTreeMap<String, T>,
9 instructions: Vec<LogicGate<O>>,
10 evaluated: BTreeMap<String, u16>, }
12
13#[derive(Debug, Clone, Copy)]
14pub enum Operand {
15 And,
16 RightShift,
17 Or,
18 LeftShift,
19 Not,
20}
21
22impl FromStr for Operand {
23 type Err = miette::Error;
24
25 fn from_str(s: &str) -> miette::Result<Self> {
26 match s {
27 "AND" => Ok(Self::And),
28 "RSHIFT" => Ok(Self::RightShift),
29 "OR" => Ok(Self::Or),
30 "LSHIFT" => Ok(Self::LeftShift),
31 "NOT" => Ok(Self::Not),
32 _ => Err(miette::miette!("Invalid operand: {s}")),
33 }
34 }
35}
36
37impl<O> LogicCircuit<String, O>
38where
39 O: Clone
40{
41 pub fn new(wires: BTreeMap<String, String>, instructions: Vec<LogicGate<O>>) -> Self {
42 Self {
43 wires,
44 instructions,
45 evaluated: BTreeMap::new(),
46 }
47 }
48
49 fn get_wire_value(&self, wire: &str) -> Option<u16> {
50 if let Some(&value) = self.evaluated.get(wire) {
52 return Some(value);
53 }
54
55 if let Ok(num) = wire.parse::<u16>() {
57 return Some(num);
58 }
59
60 if let Some(value) = self.wires.get(wire) {
62 if let Ok(num) = value.parse::<u16>() {
63 return Some(num);
64 }
65
66 return self.get_wire_value(value);
68 }
69
70 None
71 }
72}
73
74impl LogicCircuit<String, Operand> {
75 pub fn execute(&mut self) -> miette::Result<()> {
76 let mut pending = self.instructions.clone();
77 let mut progress = true;
78
79 for (wire, value) in &self.wires {
81 if let Ok(num) = value.parse::<u16>() {
82 self.evaluated.insert(wire.clone(), num);
83 }
84 }
85
86 while progress && !pending.is_empty() {
87 progress = false;
88
89 let (ready, still_pending): (Vec<_>, Vec<_>) = pending.into_iter()
90 .partition(|gate| {
91 match gate.operation {
92 Operand::Not => self.get_wire_value(&gate.left).is_some(),
93 Operand::RightShift | Operand::LeftShift =>
94 self.get_wire_value(&gate.left).is_some() && gate.right.parse::<u16>().is_ok(),
95 _ => self.get_wire_value(&gate.left).is_some() &&
96 self.get_wire_value(&gate.right).is_some()
97 }
98 });
99
100 pending = still_pending;
101
102 for gate in ready {
103 let left = self.get_wire_value(&gate.left).unwrap();
104
105 let result = match gate.operation {
106 Operand::Or => {
107 let right = self.get_wire_value(&gate.right).unwrap();
108 left | right
109 },
110 Operand::And => {
111 let right = self.get_wire_value(&gate.right).unwrap();
112 left & right
113 },
114 Operand::Not => !left,
115 Operand::RightShift => {
116 let shift = gate.right.parse::<u16>().unwrap();
117 left >> shift
118 },
119 Operand::LeftShift => {
120 let shift = gate.right.parse::<u16>().unwrap();
121 left << shift
122 },
123 };
124
125 self.evaluated.insert(gate.output, result);
126 progress = true;
127 }
128 }
129
130 Ok(())
131 }
132
133 pub fn resolve_wire(&self, wire: &str) -> miette::Result<u16> {
134 self.get_wire_value(wire)
135 .ok_or_else(|| miette::miette!("Unable to resolve wire: {wire}"))
136 }
137}
138
139
140#[derive(Debug, Clone)]
173pub struct LogicGate<O: Clone> {
174 pub left: String,
175 pub right: String,
176 pub operation: O,
177 pub output: String,
178}
179
180impl<O: Clone> LogicGate<O> {
181 pub fn new(left: String, right: String, operation: O, output: String) -> Self {
182 Self { left, right, operation, output }
183 }
184}