diff options
| -rw-r--r-- | inputs/day7 | 339 | ||||
| -rw-r--r-- | src/bin/day7.rs | 178 |
2 files changed, 517 insertions, 0 deletions
diff --git a/inputs/day7 b/inputs/day7 new file mode 100644 index 0000000..0fd2859 --- /dev/null +++ b/inputs/day7 @@ -0,0 +1,339 @@ +lf AND lq -> ls +iu RSHIFT 1 -> jn +bo OR bu -> bv +gj RSHIFT 1 -> hc +et RSHIFT 2 -> eu +bv AND bx -> by +is OR it -> iu +b OR n -> o +gf OR ge -> gg +NOT kt -> ku +ea AND eb -> ed +kl OR kr -> ks +hi AND hk -> hl +au AND av -> ax +lf RSHIFT 2 -> lg +dd RSHIFT 3 -> df +eu AND fa -> fc +df AND dg -> di +ip LSHIFT 15 -> it +NOT el -> em +et OR fe -> ff +fj LSHIFT 15 -> fn +t OR s -> u +ly OR lz -> ma +ko AND kq -> kr +NOT fx -> fy +et RSHIFT 1 -> fm +eu OR fa -> fb +dd RSHIFT 2 -> de +NOT go -> gp +kb AND kd -> ke +hg OR hh -> hi +jm LSHIFT 1 -> kg +NOT cn -> co +jp RSHIFT 2 -> jq +jp RSHIFT 5 -> js +1 AND io -> ip +eo LSHIFT 15 -> es +1 AND jj -> jk +g AND i -> j +ci RSHIFT 3 -> ck +gn AND gp -> gq +fs AND fu -> fv +lj AND ll -> lm +jk LSHIFT 15 -> jo +iu RSHIFT 3 -> iw +NOT ii -> ij +1 AND cc -> cd +bn RSHIFT 3 -> bp +NOT gw -> gx +NOT ft -> fu +jn OR jo -> jp +iv OR jb -> jc +hv OR hu -> hw +19138 -> b +gj RSHIFT 5 -> gm +hq AND hs -> ht +dy RSHIFT 1 -> er +ao OR an -> ap +ld OR le -> lf +bk LSHIFT 1 -> ce +bz AND cb -> cc +bi LSHIFT 15 -> bm +il AND in -> io +af AND ah -> ai +as RSHIFT 1 -> bl +lf RSHIFT 3 -> lh +er OR es -> et +NOT ax -> ay +ci RSHIFT 1 -> db +et AND fe -> fg +lg OR lm -> ln +k AND m -> n +hz RSHIFT 2 -> ia +kh LSHIFT 1 -> lb +NOT ey -> ez +NOT di -> dj +dz OR ef -> eg +lx -> a +NOT iz -> ja +gz LSHIFT 15 -> hd +ce OR cd -> cf +fq AND fr -> ft +at AND az -> bb +ha OR gz -> hb +fp AND fv -> fx +NOT gb -> gc +ia AND ig -> ii +gl OR gm -> gn +0 -> c +NOT ca -> cb +bn RSHIFT 1 -> cg +c LSHIFT 1 -> t +iw OR ix -> iy +kg OR kf -> kh +dy OR ej -> ek +km AND kn -> kp +NOT fc -> fd +hz RSHIFT 3 -> ib +NOT dq -> dr +NOT fg -> fh +dy RSHIFT 2 -> dz +kk RSHIFT 2 -> kl +1 AND fi -> fj +NOT hr -> hs +jp RSHIFT 1 -> ki +bl OR bm -> bn +1 AND gy -> gz +gr AND gt -> gu +db OR dc -> dd +de OR dk -> dl +as RSHIFT 5 -> av +lf RSHIFT 5 -> li +hm AND ho -> hp +cg OR ch -> ci +gj AND gu -> gw +ge LSHIFT 15 -> gi +e OR f -> g +fp OR fv -> fw +fb AND fd -> fe +cd LSHIFT 15 -> ch +b RSHIFT 1 -> v +at OR az -> ba +bn RSHIFT 2 -> bo +lh AND li -> lk +dl AND dn -> do +eg AND ei -> ej +ex AND ez -> fa +NOT kp -> kq +NOT lk -> ll +x AND ai -> ak +jp OR ka -> kb +NOT jd -> je +iy AND ja -> jb +jp RSHIFT 3 -> jr +fo OR fz -> ga +df OR dg -> dh +gj RSHIFT 2 -> gk +gj OR gu -> gv +NOT jh -> ji +ap LSHIFT 1 -> bj +NOT ls -> lt +ir LSHIFT 1 -> jl +bn AND by -> ca +lv LSHIFT 15 -> lz +ba AND bc -> bd +cy LSHIFT 15 -> dc +ln AND lp -> lq +x RSHIFT 1 -> aq +gk OR gq -> gr +NOT kx -> ky +jg AND ji -> jj +bn OR by -> bz +fl LSHIFT 1 -> gf +bp OR bq -> br +he OR hp -> hq +et RSHIFT 5 -> ew +iu RSHIFT 2 -> iv +gl AND gm -> go +x OR ai -> aj +hc OR hd -> he +lg AND lm -> lo +lh OR li -> lj +da LSHIFT 1 -> du +fo RSHIFT 2 -> fp +gk AND gq -> gs +bj OR bi -> bk +lf OR lq -> lr +cj AND cp -> cr +hu LSHIFT 15 -> hy +1 AND bh -> bi +fo RSHIFT 3 -> fq +NOT lo -> lp +hw LSHIFT 1 -> iq +dd RSHIFT 1 -> dw +dt LSHIFT 15 -> dx +dy AND ej -> el +an LSHIFT 15 -> ar +aq OR ar -> as +1 AND r -> s +fw AND fy -> fz +NOT im -> in +et RSHIFT 3 -> ev +1 AND ds -> dt +ec AND ee -> ef +NOT ak -> al +jl OR jk -> jm +1 AND en -> eo +lb OR la -> lc +iu AND jf -> jh +iu RSHIFT 5 -> ix +bo AND bu -> bw +cz OR cy -> da +iv AND jb -> jd +iw AND ix -> iz +lf RSHIFT 1 -> ly +iu OR jf -> jg +NOT dm -> dn +lw OR lv -> lx +gg LSHIFT 1 -> ha +lr AND lt -> lu +fm OR fn -> fo +he RSHIFT 3 -> hg +aj AND al -> am +1 AND kz -> la +dy RSHIFT 5 -> eb +jc AND je -> jf +cm AND co -> cp +gv AND gx -> gy +ev OR ew -> ex +jp AND ka -> kc +fk OR fj -> fl +dy RSHIFT 3 -> ea +NOT bs -> bt +NOT ag -> ah +dz AND ef -> eh +cf LSHIFT 1 -> cz +NOT cv -> cw +1 AND cx -> cy +de AND dk -> dm +ck AND cl -> cn +x RSHIFT 5 -> aa +dv LSHIFT 1 -> ep +he RSHIFT 2 -> hf +NOT bw -> bx +ck OR cl -> cm +bp AND bq -> bs +as OR bd -> be +he AND hp -> hr +ev AND ew -> ey +1 AND lu -> lv +kk RSHIFT 3 -> km +b AND n -> p +NOT kc -> kd +lc LSHIFT 1 -> lw +km OR kn -> ko +id AND if -> ig +ih AND ij -> ik +jr AND js -> ju +ci RSHIFT 5 -> cl +hz RSHIFT 1 -> is +1 AND ke -> kf +NOT gs -> gt +aw AND ay -> az +x RSHIFT 2 -> y +ab AND ad -> ae +ff AND fh -> fi +ci AND ct -> cv +eq LSHIFT 1 -> fk +gj RSHIFT 3 -> gl +u LSHIFT 1 -> ao +NOT bb -> bc +NOT hj -> hk +kw AND ky -> kz +as AND bd -> bf +dw OR dx -> dy +br AND bt -> bu +kk AND kv -> kx +ep OR eo -> eq +he RSHIFT 1 -> hx +ki OR kj -> kk +NOT ju -> jv +ek AND em -> en +kk RSHIFT 5 -> kn +NOT eh -> ei +hx OR hy -> hz +ea OR eb -> ec +s LSHIFT 15 -> w +fo RSHIFT 1 -> gh +kk OR kv -> kw +bn RSHIFT 5 -> bq +NOT ed -> ee +1 AND ht -> hu +cu AND cw -> cx +b RSHIFT 5 -> f +kl AND kr -> kt +iq OR ip -> ir +ci RSHIFT 2 -> cj +cj OR cp -> cq +o AND q -> r +dd RSHIFT 5 -> dg +b RSHIFT 2 -> d +ks AND ku -> kv +b RSHIFT 3 -> e +d OR j -> k +NOT p -> q +NOT cr -> cs +du OR dt -> dv +kf LSHIFT 15 -> kj +NOT ac -> ad +fo RSHIFT 5 -> fr +hz OR ik -> il +jx AND jz -> ka +gh OR gi -> gj +kk RSHIFT 1 -> ld +hz RSHIFT 5 -> ic +as RSHIFT 2 -> at +NOT jy -> jz +1 AND am -> an +ci OR ct -> cu +hg AND hh -> hj +jq OR jw -> jx +v OR w -> x +la LSHIFT 15 -> le +dh AND dj -> dk +dp AND dr -> ds +jq AND jw -> jy +au OR av -> aw +NOT bf -> bg +z OR aa -> ab +ga AND gc -> gd +hz AND ik -> im +jt AND jv -> jw +z AND aa -> ac +jr OR js -> jt +hb LSHIFT 1 -> hv +hf OR hl -> hm +ib OR ic -> id +fq OR fr -> fs +cq AND cs -> ct +ia OR ig -> ih +dd OR do -> dp +d AND j -> l +ib AND ic -> ie +as RSHIFT 3 -> au +be AND bg -> bh +dd AND do -> dq +NOT l -> m +1 AND gd -> ge +y AND ae -> ag +fo AND fz -> gb +NOT ie -> if +e AND f -> h +x RSHIFT 3 -> z +y OR ae -> af +hf AND hl -> hn +NOT h -> i +NOT hn -> ho +he RSHIFT 5 -> hh diff --git a/src/bin/day7.rs b/src/bin/day7.rs new file mode 100644 index 0000000..3bc4a81 --- /dev/null +++ b/src/bin/day7.rs @@ -0,0 +1,178 @@ +use std::collections::HashMap; +use regex::Regex; + +fn main() { + let input = advent::read_lines(7); + + let mut circuit = Circuit::new(&input); + let signal_a = circuit.lookup_signal("a"); + println!("7a: {}", signal_a); + + let mut circuit = Circuit::new(&input); + circuit.instructions.insert("b".to_string(), Operation::Direct(Signal::Raw(signal_a))); + let signal_a = circuit.lookup_signal("a"); + println!("7b: {}", signal_a); +} + +#[derive(Clone)] +enum Signal { + Raw(u16), + Wire(String), +} + +impl Signal { + fn new(input: &str) -> Signal { + match input.parse::<u16>() { + Ok(val) => Signal::Raw(val), + Err(_) => Signal::Wire(input.to_string()), + } + } +} + +#[derive(Clone)] +enum Operation { + And(Signal, Signal), + Or(Signal, Signal), + Lshift(Signal, u8), + Rshift(Signal, u8), + Not(Signal), + Direct(Signal), +} + +struct Circuit { + instructions: HashMap<String, Operation>, +} + +impl Circuit { + fn new<T: AsRef<str>>(input: &[T]) -> Circuit { + let re_and = Regex::new(r"^([a-z0-9]+) AND ([a-z0-9]+) -> ([a-z0-9]+)").unwrap(); + let re_or = Regex::new(r"^([a-z0-9]+) OR ([a-z0-9]+) -> ([a-z0-9]+)").unwrap(); + let re_lshift = Regex::new(r"^([a-z0-9]+) LSHIFT ([0-9]+) -> ([a-z0-9]+)").unwrap(); + let re_rshift = Regex::new(r"^([a-z0-9]+) RSHIFT ([0-9]+) -> ([a-z0-9]+)").unwrap(); + let re_not = Regex::new(r"^NOT ([a-z0-9]+) -> ([a-z0-9]+)").unwrap(); + let re_direct = Regex::new(r"^([a-z0-9]+) -> ([a-z0-9]+)").unwrap(); + + let mut instructions = HashMap::new(); + + for line in input { + let (out, operation) = if let Some(cap) = re_and.captures(line.as_ref()) { + let s1 = Signal::new(&cap[1]); + let s2 = Signal::new(&cap[2]); + let out = cap[3].to_string(); + (out, Operation::And(s1, s2)) + } else if let Some(cap) = re_or.captures(line.as_ref()) { + let s1 = Signal::new(&cap[1]); + let s2 = Signal::new(&cap[2]); + let out = cap[3].to_string(); + (out, Operation::Or(s1, s2)) + } else if let Some(cap) = re_lshift.captures(line.as_ref()) { + let s1 = Signal::new(&cap[1]); + let val = cap[2].parse::<u8>().unwrap(); + let out = cap[3].to_string(); + (out, Operation::Lshift(s1, val)) + } else if let Some(cap) = re_rshift.captures(line.as_ref()) { + let s1 = Signal::new(&cap[1]); + let val = cap[2].parse::<u8>().unwrap(); + let out = cap[3].to_string(); + (out, Operation::Rshift(s1, val)) + } else if let Some(cap) = re_not.captures(line.as_ref()) { + let s1 = Signal::new(&cap[1]); + let out = cap[2].to_string(); + (out, Operation::Not(s1)) + } else if let Some(cap) = re_direct.captures(line.as_ref()) { + let s1 = Signal::new(&cap[1]); + let out = cap[2].to_string(); + (out, Operation::Direct(s1)) + } else { + panic!("invalid instruction: {}", line.as_ref()); + }; + instructions.insert(out, operation); + } + + Circuit { instructions } + } + + fn lookup_signal(&mut self, wire: &str) -> u16 { + let res = match self.instructions.get(wire).unwrap().clone() { + Operation::Direct(s) => { + match s { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + } + }, + Operation::And(s1, s2) => { + let val1 = match s1 { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + let val2 = match s2 { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + val1 & val2 + }, + Operation::Or(s1, s2) => { + let val1 = match s1 { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + let val2 = match s2 { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + val1 | val2 + }, + Operation::Lshift(s, amnt) => { + let val = match s { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + val << amnt + }, + Operation::Rshift(s, amnt) => { + let val = match s { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + val >> amnt + }, + Operation::Not(s) => { + let val = match s { + Signal::Raw(i) => i, + Signal::Wire(w) => self.lookup_signal(&w), + }; + val ^ 0xffff + }, + }; + self.instructions.insert(wire.to_string(), Operation::Direct(Signal::Raw(res))); + res + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test() { + let input = [ + "123 -> x", + "456 -> y", + "x AND y -> d", + "x OR y -> e", + "x LSHIFT 2 -> f", + "y RSHIFT 2 -> g", + "NOT x -> h", + "NOT y -> i", + ]; + let mut circuit = Circuit::new(&input); + assert_eq!(circuit.lookup_signal("d"), 72); + assert_eq!(circuit.lookup_signal("e"), 507); + assert_eq!(circuit.lookup_signal("f"), 492); + assert_eq!(circuit.lookup_signal("g"), 114); + assert_eq!(circuit.lookup_signal("h"), 65412); + assert_eq!(circuit.lookup_signal("i"), 65079); + assert_eq!(circuit.lookup_signal("x"), 123); + assert_eq!(circuit.lookup_signal("y"), 456); + } +} |
