commit 3dbffcd9e45cb9f629131725bf5ad2e3b2b8fb47
parent dd2922f82a453544355fe683e3bd66bc0c21b4ee
Author: Louis Burda <quent.burda@gmail.com>
Date: Sat, 15 Apr 2023 01:32:23 -0400
[Day 16] Use enums fields
Diffstat:
M | src/16/src/main.rs | | | 146 | +++++++++++++++++++++++++++++++++---------------------------------------------- |
1 file changed, 60 insertions(+), 86 deletions(-)
diff --git a/src/16/src/main.rs b/src/16/src/main.rs
@@ -1,6 +1,18 @@
-use std::mem::ManuallyDrop;
+enum PacketSizeType {
+ Count(usize),
+ Len(usize)
+}
+
+struct LiteralPacket {
+ val: usize
+}
-#[derive(PartialEq,Eq,Copy,Clone,num_derive::FromPrimitive)]
+struct OperatorPacket {
+ subsz: PacketSizeType,
+ sub: Vec<usize>
+}
+
+#[derive(Copy,Clone,PartialEq,num_derive::FromPrimitive)]
enum PacketType {
Sum = 0,
Product = 1,
@@ -12,51 +24,15 @@ enum PacketType {
EqualTo = 7
}
-#[derive(PartialEq,Eq,Clone)]
-enum PacketSizeType {
- Count,
- Len
-}
-
-#[derive(Clone)]
-struct LiteralPacket {
- val: usize
-}
-
-#[derive(Clone,Copy)]
-union PacketSize {
- cnt: usize,
- len: usize
-}
-
-#[derive(Clone)]
-struct OperatorPacket {
- sztype: PacketSizeType,
- size: PacketSize,
- sub: Vec<usize>
-}
-
-union PacketUnion {
- lit: ManuallyDrop<LiteralPacket>,
- op: ManuallyDrop<OperatorPacket>
+enum PacketClass {
+ Literal(LiteralPacket),
+ Operator(OperatorPacket)
}
struct Packet {
ver: u8,
typ: PacketType,
- u: PacketUnion,
-}
-
-impl Clone for Packet {
- fn clone(&self) -> Self {
- let pkt_u: PacketUnion;
- if self.typ == PacketType::Literal {
- pkt_u = PacketUnion { lit: unsafe { self.u.lit.clone() } };
- } else {
- pkt_u = PacketUnion { op: unsafe { self.u.op.clone() } };
- }
- return Packet { ver: self.ver, typ: self.typ, u: pkt_u };
- }
+ c: PacketClass
}
struct ParseState {
@@ -80,8 +56,8 @@ fn decode_packet(bitstr: &str) -> (Packet, usize) {
aoc::debugln!("{}", bitstr);
let pver = u8::from_str_radix(&bitstr[0..3], 2).unwrap();
let ptype_val = u8::from_str_radix(&bitstr[3..6], 2).unwrap();
- let pu: PacketUnion;
let mut cnt: usize = 0;
+ let pc : PacketClass;
let ptype: PacketType = num::FromPrimitive::from_u8(ptype_val).unwrap();
if ptype == PacketType::Literal {
let mut imm: usize = 0;
@@ -92,27 +68,22 @@ fn decode_packet(bitstr: &str) -> (Packet, usize) {
break;
}
}
- let lit = ManuallyDrop::new(LiteralPacket { val: imm });
- pu = PacketUnion { lit };
+ pc = PacketClass::Literal(LiteralPacket { val: imm });
} else {
let szbit = bitstr[6..].chars().next().unwrap();
- let sztype: PacketSizeType;
- let size: PacketSize;
+ let subsz: PacketSizeType;
if szbit == '1' {
- sztype = PacketSizeType::Count;
- let imm = usize::from_str_radix(&bitstr[7..7+11], 2).unwrap();
- size = PacketSize { cnt: imm };
+ let val = usize::from_str_radix(&bitstr[7..7+11], 2).unwrap();
+ subsz = PacketSizeType::Count(val);
cnt = 18;
} else {
- sztype = PacketSizeType::Len;
- let imm = usize::from_str_radix(&bitstr[7..7+15], 2).unwrap();
- size = PacketSize { len: imm };
+ let val = usize::from_str_radix(&bitstr[7..7+15], 2).unwrap();
+ subsz = PacketSizeType::Len(val);
cnt = 22;
}
- let op = ManuallyDrop::new(OperatorPacket { sztype, size, sub: Vec::new() });
- pu = PacketUnion { op };
+ pc = PacketClass::Operator(OperatorPacket { subsz, sub: Vec::new() });
}
- return (Packet { ver: pver, typ: ptype, u: pu }, cnt);
+ return (Packet { ver: pver, typ: ptype, c: pc }, cnt);
}
fn decode_packets(input: &str) -> Vec<Packet> {
@@ -124,16 +95,16 @@ fn decode_packets(input: &str) -> Vec<Packet> {
while !stack.is_empty() || pos + 8 <= bits.len() {
if !stack.is_empty() {
let state = stack.last_mut().unwrap();
- let op = unsafe { &*packets.get_mut(state.pkt).unwrap().u.op };
- let done = op.sztype == PacketSizeType::Count
- && state.idx >= unsafe { op.size.cnt }
- || op.sztype == PacketSizeType::Len
- && pos - state.start >= unsafe { op.size.len };
+ let pkt = packets.get_mut(state.pkt).unwrap();
+ let op = match &pkt.c {
+ PacketClass::Operator(op) => op,
+ PacketClass::Literal(_) => { unreachable!(); }
+ };
+ let done = match op.subsz {
+ PacketSizeType::Len(len) => pos - state.start >= len,
+ PacketSizeType::Count(cnt) => state.idx >= cnt
+ };
if done {
- assert!(op.sztype == PacketSizeType::Count
- && state.idx == unsafe { op.size.cnt }
- || op.sztype == PacketSizeType::Len
- && pos - state.start == unsafe { op.size.len });
stack.pop();
continue;
}
@@ -155,8 +126,10 @@ fn decode_packets(input: &str) -> Vec<Packet> {
* soon as this state is at the top of the stack again */
state.idx += 1;
let pkt = packets.get_mut(state.pkt).unwrap();
- assert!(pkt.typ != PacketType::Literal);
- let op = unsafe { &mut pkt.u.op };
+ let op = match &mut pkt.c {
+ PacketClass::Literal(_) => { unreachable!(); },
+ PacketClass::Operator(op) => op
+ };
op.sub.push(pkt_idx);
}
@@ -191,27 +164,28 @@ fn eval_packets(packets: &Vec<Packet>) -> usize {
while !stack.is_empty() {
let top = stack.last().unwrap();
let pkt = packets.get(top.pkt).unwrap();
- aoc::debugln!("packet {}", pkt.typ as u8);
- if pkt.typ == PacketType::Literal {
- stack.pop();
- assert!(!stack.is_empty());
- let top = stack.last_mut().unwrap();
- top.ins.push(unsafe { pkt.u.lit.val });
- } else {
- let op = unsafe { &pkt.u.op };
- let len = op.sub.len();
- let idx = top.ins.len();
- aoc::debugln!("=> op {} {}", idx, len);
- assert!(len != 0);
- if idx < len {
- let child = *op.sub.get(idx).unwrap();
- stack.push(EvalState { pkt: child, ins: Vec::new() });
- } else {
- let res = eval_packet(pkt.typ, &top.ins);
+ match &pkt.c {
+ PacketClass::Literal(lit) => {
stack.pop();
- if stack.is_empty() { return res; }
+ assert!(!stack.is_empty());
let top = stack.last_mut().unwrap();
- top.ins.push(res);
+ top.ins.push(lit.val);
+ },
+ PacketClass::Operator(op) => {
+ let len = op.sub.len();
+ let idx = top.ins.len();
+ aoc::debugln!("=> op {} {}", idx, len);
+ assert!(len != 0);
+ if idx < len {
+ let child = *op.sub.get(idx).unwrap();
+ stack.push(EvalState { pkt: child, ins: Vec::new() });
+ } else {
+ let res = eval_packet(pkt.typ, &top.ins);
+ stack.pop();
+ if stack.is_empty() { return res; }
+ let top = stack.last_mut().unwrap();
+ top.ins.push(res);
+ }
}
}
}