aoc_ornaments/
bits.rs

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>,  // Cache for evaluated results
11}
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        // First check if we have already evaluated this wire
51        if let Some(&value) = self.evaluated.get(wire) {
52            return Some(value);
53        }
54
55        // Try parsing as direct number
56        if let Ok(num) = wire.parse::<u16>() {
57            return Some(num);
58        }
59
60        // Check if it's in initial wires and can be parsed as number
61        if let Some(value) = self.wires.get(wire) {
62            if let Ok(num) = value.parse::<u16>() {
63                return Some(num);
64            }
65
66            // If not a number, recursively resolve the referenced wire
67            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        // First pass - convert any pure number strings to u16
80        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// impl<T: Clone, O: Clone> LogicCircuit<T, O> {
141//     fn evaluate(mut self) -> miette::Result<Self> {
142//         let mut made_progress = true;
143//         let mut pending_gates = self.instructions.clone();
144
145//         while made_progress && !pending_gates.is_empty() {
146//             made_progress = false;
147
148//             let (ready, still_pending): (Vec<_>, Vec<_>) = pending_gates.drain(..)
149//                 .partition(|gate| {
150//                     self.wires.contains_key(&gate.left) && 
151//                     (!gate.operation.requires_right_operand() || 
152//                      gate.right.as_ref().map_or(true, |r| self.wires.contains_key(r)))
153//                 });
154
155//             pending_gates = still_pending;
156
157//             for gate in ready {
158//                 let left = self.wires[&gate.left].clone();
159//                 let right = gate.right.map(|r| self.wires[&r].clone());
160                
161//                 let result = gate.operation.evaluate(left, right);
162//                 self.wires.insert(gate.output, result);
163
164//                 made_progress = true;
165//             }
166//         }
167
168//         Ok(self)
169//     }
170// }
171
172#[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}