From 039c0d2c92ed3bd853222e5569c5e85c03e463f8 Mon Sep 17 00:00:00 2001 From: Thomas Ruggeri Date: Fri, 3 Jan 2025 20:25:54 -0800 Subject: [PATCH] feat: Solving day 24 --- docs/day24.md | 137 ++++++++++++++ src/day24/day24.go | 97 ++++++++++ src/day24/day24_test.go | 394 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 628 insertions(+) create mode 100644 docs/day24.md create mode 100644 src/day24/day24.go create mode 100644 src/day24/day24_test.go diff --git a/docs/day24.md b/docs/day24.md new file mode 100644 index 0000000..5dbe7b9 --- /dev/null +++ b/docs/day24.md @@ -0,0 +1,137 @@ +--- +url: "https://adventofcode.com/2024/day/24" +--- + +# Day 24: Crossed Wires + +You and The Historians arrive at the edge of a large grove somewhere in the jungle. After the last incident, the Elves installed a small device that monitors the fruit. While The Historians search the grove, one of them asks if you can take a look at the monitoring device; apparently, it's been malfunctioning recently. + +The device seems to be trying to produce a number through some boolean logic gates. Each gate has two inputs and one output. The gates all operate on values that are either true (`1`) or false (`0`). + +* `AND` gates output `1` if both inputs are `1`; if either input is `0`, these gates output `0`. +* `OR` gates output `1` if one or both inputs is `1`; if both inputs are `0`, these gates output `0`. +* `XOR` gates output `1` if the inputs are different; if the inputs are the same, these gates output `0`. + +Gates wait until both inputs are received before producing output; wires can carry `0`, `1` or no value at all. There are no loops; once a gate has determined its output, the output will not change until the whole system is reset. Each wire is connected to at most one gate output, but can be connected to many gate inputs. + +Rather than risk getting shocked while tinkering with the live system, you write down all of the gate connections and initial wire values (your puzzle input) so you can consider them in relative safety. For example: + +```txt +x00: 1 +x01: 1 +x02: 1 +y00: 0 +y01: 1 +y02: 0 + +x00 AND y00 -> z00 +x01 XOR y01 -> z01 +x02 OR y02 -> z02 +``` + +Because gates wait for input, some wires need to start with a value (as inputs to the entire system). The first section specifies these values. For example, `x00: 1` means that the wire named `x00` starts with the value 1 (as if a gate is already outputting that value onto that wire). + +The second section lists all of the gates and the wires connected to them. For example, `x00 AND y00 -> z00` describes an instance of an `AND` gate which has wires `x00` and `y00` connected to its inputs and which will write its output to wire `z00`. + +In this example, simulating these gates eventually causes `0` to appear on wire `z00`, `0` to appear on wire `z01`, and `1` to appear on wire `z02`. + +Ultimately, the system is trying to produce a number by combining the bits on all wires starting with `z`. `z00` is the least significant bit, then `z01`, then `z02`, and so on. + +In this example, the three output bits form the binary number 100 which is equal to the decimal number `4`. + +Here's a larger example: + +```txt +x00: 1 +x01: 0 +x02: 1 +x03: 1 +x04: 0 +y00: 1 +y01: 1 +y02: 1 +y03: 1 +y04: 1 + +ntg XOR fgs -> mjb +y02 OR x01 -> tnw +kwq OR kpj -> z05 +x00 OR x03 -> fst +tgd XOR rvg -> z01 +vdt OR tnw -> bfw +bfw AND frj -> z10 +ffh OR nrd -> bqk +y00 AND y03 -> djm +y03 OR y00 -> psh +bqk OR frj -> z08 +tnw OR fst -> frj +gnj AND tgd -> z11 +bfw XOR mjb -> z00 +x03 OR x00 -> vdt +gnj AND wpb -> z02 +x04 AND y00 -> kjc +djm OR pbm -> qhw +nrd AND vdt -> hwm +kjc AND fst -> rvg +y04 OR y02 -> fgs +y01 AND x02 -> pbm +ntg OR kjc -> kwq +psh XOR fgs -> tgd +qhw XOR tgd -> z09 +pbm OR djm -> kpj +x03 XOR y03 -> ffh +x00 XOR y04 -> ntg +bfw OR bqk -> z06 +nrd XOR fgs -> wpb +frj XOR qhw -> z04 +bqk OR frj -> z07 +y03 OR x01 -> nrd +hwm AND bqk -> z03 +tgd XOR rvg -> z12 +tnw OR pbm -> gnj +``` + +After waiting for values on all wires starting with `z`, the wires in this system have the following values: + +```txt +bfw: 1 +bqk: 1 +djm: 1 +ffh: 0 +fgs: 1 +frj: 1 +fst: 1 +gnj: 1 +hwm: 1 +kjc: 0 +kpj: 1 +kwq: 0 +mjb: 1 +nrd: 1 +ntg: 0 +pbm: 1 +psh: 1 +qhw: 1 +rvg: 0 +tgd: 0 +tnw: 1 +vdt: 1 +wpb: 0 +z00: 0 +z01: 0 +z02: 0 +z03: 1 +z04: 0 +z05: 1 +z06: 1 +z07: 1 +z08: 1 +z09: 1 +z10: 1 +z11: 0 +z12: 0 +``` + +Combining the bits from all wires starting with `z` produces the binary number `0011111101000`. Converting this number to decimal produces `2024`. + +Simulate the system of gates and wires. What decimal number does it output on the wires starting with `z`? diff --git a/src/day24/day24.go b/src/day24/day24.go new file mode 100644 index 0000000..bf67937 --- /dev/null +++ b/src/day24/day24.go @@ -0,0 +1,97 @@ +package day24 + +import ( + "strconv" + "strings" +) + +const OUTPUT_WIRE_PREFIX = 'z' + +type gate struct { + typ string + left, right string +} + +func (g gate) eval(left, right uint8) uint8 { + switch g.typ { + case "AND": + return left & right + case "OR": + return left | right + case "XOR": + return left ^ right + default: + panic("Gate type could not be determined") + } +} + +func Solve(input string) uint { + wires, gates := parseInput(input) + for { + if len(gates) == 0 { + break + } + + updates := 0 + for k, g := range gates { + left, okL := wires[g.left] + right, okR := wires[g.right] + if okL && okR { + wires[k] = g.eval(left, right) + delete(gates, k) + updates++ + } + } + + if updates == 0 { + panic("Iterated through gates and could not make forward progress") + } + } + return outputWire(wires) +} + +func parseInput(input string) (map[string]uint8, map[string]gate) { + wires := make(map[string]uint8) + gates := make(map[string]gate) + parseGates := false + for _, line := range strings.Split(input, "\n") { + if line == "" { + parseGates = true + continue + } + + if parseGates { + d := strings.Split(line, " ") + if len(d) != 5 || d[3] != "->" { + continue + } + + gates[d[4]] = gate{typ: d[1], left: d[0], right: d[2]} + } else { + d := strings.Split(line, ": ") + if len(d) != 2 { + continue + } + + var v uint8 + if d[1] == "1" { + v = 1 + } + wires[d[0]] = v + } + } + return wires, gates +} + +func outputWire(wires map[string]uint8) uint { + var result uint + for k, w := range wires { + if k[0] != OUTPUT_WIRE_PREFIX { + continue + } + + pos, _ := strconv.Atoi(k[1:]) + result = result | uint(w)< z00 +x01 XOR y01 -> z01 +x02 OR y02 -> z02` + result := Solve(input) + if result != 4 { + t.Errorf("Calculated solution (%d) was not expected", result) + } +} + +func TestLargeSample(t *testing.T) { + input := `x00: 1 +x01: 0 +x02: 1 +x03: 1 +x04: 0 +y00: 1 +y01: 1 +y02: 1 +y03: 1 +y04: 1 + +ntg XOR fgs -> mjb +y02 OR x01 -> tnw +kwq OR kpj -> z05 +x00 OR x03 -> fst +tgd XOR rvg -> z01 +vdt OR tnw -> bfw +bfw AND frj -> z10 +ffh OR nrd -> bqk +y00 AND y03 -> djm +y03 OR y00 -> psh +bqk OR frj -> z08 +tnw OR fst -> frj +gnj AND tgd -> z11 +bfw XOR mjb -> z00 +x03 OR x00 -> vdt +gnj AND wpb -> z02 +x04 AND y00 -> kjc +djm OR pbm -> qhw +nrd AND vdt -> hwm +kjc AND fst -> rvg +y04 OR y02 -> fgs +y01 AND x02 -> pbm +ntg OR kjc -> kwq +psh XOR fgs -> tgd +qhw XOR tgd -> z09 +pbm OR djm -> kpj +x03 XOR y03 -> ffh +x00 XOR y04 -> ntg +bfw OR bqk -> z06 +nrd XOR fgs -> wpb +frj XOR qhw -> z04 +bqk OR frj -> z07 +y03 OR x01 -> nrd +hwm AND bqk -> z03 +tgd XOR rvg -> z12 +tnw OR pbm -> gnj` + result := Solve(input) + if result != 2024 { + t.Errorf("Calculated solution (%d) was not expected", result) + } +} + +func TestPart1(t *testing.T) { + input := `x00: 1 +x01: 1 +x02: 1 +x03: 1 +x04: 0 +x05: 1 +x06: 0 +x07: 1 +x08: 0 +x09: 1 +x10: 1 +x11: 1 +x12: 1 +x13: 0 +x14: 1 +x15: 1 +x16: 1 +x17: 1 +x18: 0 +x19: 1 +x20: 0 +x21: 1 +x22: 0 +x23: 1 +x24: 1 +x25: 0 +x26: 1 +x27: 1 +x28: 0 +x29: 0 +x30: 0 +x31: 0 +x32: 0 +x33: 1 +x34: 0 +x35: 0 +x36: 1 +x37: 1 +x38: 0 +x39: 1 +x40: 1 +x41: 0 +x42: 1 +x43: 0 +x44: 1 +y00: 1 +y01: 1 +y02: 1 +y03: 1 +y04: 1 +y05: 0 +y06: 0 +y07: 0 +y08: 0 +y09: 0 +y10: 1 +y11: 0 +y12: 0 +y13: 0 +y14: 1 +y15: 0 +y16: 0 +y17: 1 +y18: 1 +y19: 1 +y20: 0 +y21: 0 +y22: 1 +y23: 0 +y24: 1 +y25: 1 +y26: 1 +y27: 1 +y28: 1 +y29: 1 +y30: 0 +y31: 1 +y32: 1 +y33: 0 +y34: 0 +y35: 0 +y36: 1 +y37: 0 +y38: 0 +y39: 0 +y40: 0 +y41: 0 +y42: 1 +y43: 0 +y44: 1 + +vgh OR dhk -> kfp +qpb OR tdt -> z45 +njd XOR hwt -> z33 +y38 AND x38 -> srk +y25 AND x25 -> sth +jrw OR tmm -> htw +qkn AND dvc -> kff +x08 AND y08 -> kmm +dcj AND wrr -> jkm +mmc XOR mdv -> z05 +x35 AND y35 -> vss +x14 AND y14 -> nvj +fks OR mgs -> fww +jnh OR njq -> z24 +mfk XOR pwh -> z12 +rbc OR kgg -> jqw +cbm OR jjn -> nfn +x30 AND y30 -> fqm +x18 AND y18 -> kgg +x23 XOR y23 -> smg +y36 XOR x36 -> sfh +kvb AND fhp -> dhk +y24 AND x24 -> njq +x20 AND y20 -> hkt +x36 AND y36 -> dcq +y17 AND x17 -> wvs +y09 XOR x09 -> wpr +tjp OR tdk -> trq +gkq XOR qbf -> z08 +fmw AND ffk -> twt +y38 XOR x38 -> ccw +vss OR nkn -> bbq +x02 AND y02 -> rfb +wwj OR pjn -> njd +csn XOR jqw -> z19 +y06 XOR x06 -> fwp +tms AND wbm -> nkn +tff AND nbm -> jgd +y13 AND x13 -> vgh +y19 AND x19 -> dwn +nfn AND nsk -> jwb +smg XOR hrk -> z23 +kkp AND tnm -> jnh +x03 AND y03 -> tjp +qbf AND gkq -> thk +x16 AND y16 -> gjg +mfk AND pwh -> wpw +y06 AND x06 -> jdp +x22 AND y22 -> cnp +bwv OR fwb -> mpd +mpd AND wnw -> hmk +y21 XOR x21 -> hvt +fmd XOR qcw -> z26 +tcs XOR hwg -> z10 +fwp AND fww -> qjk +x29 AND y29 -> nfp +cmj AND htw -> fpt +x10 AND y10 -> psb +mkr OR tqp -> fhf +bqn XOR kmr -> z15 +qkq AND stj -> z20 +cnp OR dbc -> hrk +vcg AND qgb -> rss +bqs OR qnq -> qbf +sth OR rss -> qcw +sfh AND bbq -> stg +stj XOR qkq -> jgb +wsq OR wvs -> hrn +y05 XOR x05 -> mdv +y27 XOR x27 -> wnw +nsm XOR mfq -> z32 +njd AND hwt -> ppm +csn AND jqw -> skp +y39 AND x39 -> bnj +rkf OR hvk -> tcs +y41 XOR x41 -> nsk +hmk OR tqj -> tff +hrn XOR pfb -> z18 +x32 XOR y32 -> mfq +wmj AND djn -> gsj +tnm XOR kkp -> vcg +x00 AND y00 -> mjh +srk OR rtf -> rsg +x04 XOR y04 -> hcs +y33 AND x33 -> fjr +y27 AND x27 -> tqj +psb OR pjf -> whj +jnn AND wpr -> hvk +y42 XOR x42 -> dvc +x18 XOR y18 -> pfb +x25 XOR y25 -> qgb +x03 XOR y03 -> csd +y40 XOR x40 -> qbn +kbq AND csd -> tdk +rdj AND mjh -> tqp +fhp XOR kvb -> z13 +y10 XOR x10 -> hwg +x01 AND y01 -> mkr +vpc OR mqg -> wbm +csf XOR rrs -> z31 +wmj XOR djn -> z37 +mpd XOR wnw -> z27 +fwg XOR rvj -> z07 +csd XOR kbq -> z03 +dwn OR skp -> stj +vfd XOR pjw -> z44 +psg OR jgd -> dcj +x15 XOR y15 -> kmr +nbm XOR tff -> z28 +x07 XOR y07 -> rvj +rsp AND fsf -> wsq +x16 XOR y16 -> cmj +y05 AND x05 -> mgs +y11 XOR x11 -> bcw +y40 AND x40 -> cbm +bvn OR jwb -> qkn +tkv AND npv -> wkn +grc OR jwd -> mmc +ffk XOR fmw -> z30 +ghk OR grb -> pwh +x30 XOR y30 -> fmw +ppm OR fjr -> fsn +khg OR wkn -> pjw +x17 XOR y17 -> fsf +y44 XOR x44 -> vfd +x13 XOR y13 -> fhp +y28 AND x28 -> psg +pcp OR kff -> tkv +bhs XOR fsn -> z34 +dvc XOR qkn -> z42 +pst AND qbn -> jjn +bcw XOR whj -> z11 +kmr AND bqn -> jrw +pfb AND hrn -> rbc +x37 XOR y37 -> djn +x31 AND y31 -> rrs +csf AND rrs -> pgq +tms XOR wbm -> z35 +khb AND qtq -> dbc +fsn AND bhs -> vpc +y14 XOR x14 -> rvd +x22 XOR y22 -> khb +rdj XOR mjh -> z01 +hvt AND bfp -> shc +rfb OR qtr -> kbq +y26 AND x26 -> bwv +y37 AND x37 -> trf +x12 AND y12 -> qcg +x23 AND y23 -> knh +qcg OR wpw -> kvb +gsj OR trf -> wqq +fmd AND qcw -> fwb +x41 AND y41 -> bvn +nsk XOR nfn -> z41 +rvc OR pgq -> nsm +y32 AND x32 -> pjn +vfd AND pjw -> qpb +mfq AND nsm -> wwj +cmj XOR htw -> z16 +jkm OR nfp -> ffk +x42 AND y42 -> pcp +fsf XOR rsp -> z17 +rvj AND fwg -> bqs +y28 XOR x28 -> nbm +tcs AND hwg -> pjf +x08 XOR y08 -> gkq +qgb XOR vcg -> z25 +hcs XOR trq -> z04 +jgb OR hkt -> bfp +rvd XOR kfp -> z14 +wqq AND ccw -> rtf +y20 XOR x20 -> qkq +kfp AND rvd -> qmp +x04 AND y04 -> grc +qbn XOR pst -> z40 +fqm OR twt -> csf +khb XOR qtq -> z22 +y00 XOR x00 -> z00 +y34 AND x34 -> mqg +x11 AND y11 -> grb +y34 XOR x34 -> bhs +y09 AND x09 -> z09 +hrk AND smg -> vvb +x12 XOR y12 -> mfk +gjg OR fpt -> rsp +y39 XOR x39 -> hkr +x31 XOR y31 -> rvc +kmm OR thk -> jnn +rsg XOR hkr -> z39 +fht XOR fhf -> z02 +hkr AND rsg -> mhh +bfp XOR hvt -> z21 +shc OR nvr -> qtq +y01 XOR x01 -> rdj +trq AND hcs -> jwd +y07 AND x07 -> qnq +qmp OR nvj -> bqn +x29 XOR y29 -> wrr +y33 XOR x33 -> hwt +x19 XOR y19 -> csn +whj AND bcw -> ghk +y24 XOR x24 -> tnm +dcq OR stg -> wmj +tkv XOR npv -> z43 +mhh OR bnj -> pst +mmc AND mdv -> fks +x02 XOR y02 -> fht +y44 AND x44 -> tdt +x43 AND y43 -> khg +jnn XOR wpr -> rkf +knh OR vvb -> kkp +y15 AND x15 -> tmm +x35 XOR y35 -> tms +fht AND fhf -> qtr +dcj XOR wrr -> z29 +fww XOR fwp -> z06 +y21 AND x21 -> nvr +y43 XOR x43 -> npv +sfh XOR bbq -> z36 +qjk OR jdp -> fwg +y26 XOR x26 -> fmd +wqq XOR ccw -> z38` + result := Solve(input) + if result != 45923082839246 { + t.Errorf("Calculated solution (%d) was not expected", result) + } +}