summaryrefslogtreecommitdiff
path: root/day24/main.go
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-24 23:57:15 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2024-12-24 23:57:15 +0100
commit46859764ad4073da2c910ebd321320e1edb9b8c6 (patch)
treeb0b4cccb96547eb25a2953ff62572f2c61e3de83 /day24/main.go
parentc6ca510a5ccf232cbf0677a77453addb8d5d70be (diff)
Fucking day 24
Diffstat (limited to 'day24/main.go')
-rw-r--r--day24/main.go256
1 files changed, 256 insertions, 0 deletions
diff --git a/day24/main.go b/day24/main.go
new file mode 100644
index 0000000..3d5e89a
--- /dev/null
+++ b/day24/main.go
@@ -0,0 +1,256 @@
+package main
+
+import (
+ "bufio"
+ "fmt"
+ "os"
+ "sort"
+ "strings"
+)
+
+func main() {
+ fmt.Println(part1(readData("example_simple.txt")), 4)
+ fmt.Println(part1(readData("example.txt")), 2024)
+ fmt.Println(part1(readData("data.txt")), 49574189473968)
+ // fmt.Println(part2(readData("data.txt").gates))
+ fmt.Println(part2(readData("data-2.txt").gates))
+
+}
+
+const (
+ AND = "AND"
+ OR = "OR"
+ XOR = "XOR"
+)
+
+type Gate struct {
+ op string
+ a, b string
+}
+
+type Circuit struct {
+ values map[string]bool
+ gates map[string]Gate
+}
+
+func part1(input Circuit) (result uint64) {
+ queue := []string{}
+ for output := range input.gates {
+ queue = append(queue, output)
+ }
+
+ for len(queue) > 0 {
+ output := queue[len(queue)-1]
+ if _, alreadyComputed := input.values[output]; alreadyComputed {
+ queue = queue[:len(queue)-1]
+ continue
+ }
+
+ gate := input.gates[output]
+ valueA, okA := input.values[gate.a]
+ valueB, okB := input.values[gate.b]
+
+ if !okA || !okB {
+ if !okA {
+ queue = append(queue, gate.a)
+ }
+ if !okB {
+ queue = append(queue, gate.b)
+ }
+ } else {
+ input.values[output] = evaluate(gate.op, valueA, valueB)
+ queue = queue[:len(queue)-1]
+ }
+ }
+
+ zWires := []string{}
+ for wire := range input.values {
+ if wire[0] == 'z' {
+ zWires = append(zWires, wire)
+ }
+ }
+
+ sort.Sort(sort.Reverse(sort.StringSlice(zWires)))
+
+ for _, w := range zWires {
+ if input.values[w] {
+ result = result<<1 | 1
+ } else {
+ result = result << 1
+ }
+ }
+
+ return
+}
+
+func evaluate(op string, a, b bool) bool {
+ switch op {
+ case AND:
+ return a && b
+ case OR:
+ return a || b
+ case XOR:
+ return a != b
+ default:
+ panic("unknown operator")
+ }
+}
+
+func name(prefix byte, num int) string {
+ a := byte(num%10 + '0')
+ b := byte(num/10 + '0')
+ return string([]byte{prefix, b, a})
+}
+
+func evaluateAdder(gates map[string]Gate, a, b uint64) uint64 {
+ circuit := Circuit{gates: gates, values: make(map[string]bool)}
+ for i := range 50 {
+ x := a&(uint64(1)<<i) != 0
+ y := b&(uint64(1)<<i) != 0
+ circuit.values[name('x', i)] = x
+ circuit.values[name('y', i)] = y
+ }
+ return part1(circuit)
+}
+
+func printAround(w string, prefix string, gates map[string]Gate, depth int) {
+ if depth == 0 {
+ return
+ }
+ if g, ok := gates[w]; ok {
+ fmt.Println(prefix, w, g)
+ printAround(g.a, prefix+" ", gates, depth-1)
+ printAround(g.b, prefix+" ", gates, depth-1)
+ }
+}
+
+func part2(gates map[string]Gate) string {
+ // ckb-z39
+ // tqq-z20
+ // ksv-z06
+ // kbs-nbd
+ // ckb,kbs,ksv,nbd,tqq,z06,z20,z39
+
+ // fmt.Println("z without xor")
+ // for out, g := range gates {
+ // if out[0] == 'z' && g.op != XOR && out != "z45" {
+ // fmt.Println(out, g)
+ // }
+ // }
+ // z39 {0 cmj hpp} DONE
+ // z20 {1 tsm dnc} DONE
+
+ // z06 {AND x06 y06} DONE
+ // nsp {XOR x06 y06}
+ // ksv {XOR qtf nsp}
+
+ // printAround("z06", gates, 3)
+ // fmt.Println("")
+ // for out, g := range gates {
+ // if g.a == "nsp" || g.b == "nsp" {
+ // fmt.Println(out, g)
+ // }
+ // }
+ // fmt.Println("xor without x or y")
+ // for out, g := range gates {
+ // if g.op == XOR && (g.a[0] != 'x' && g.a[0] != 'y' && g.b[0] != 'x' && g.b[0] != 'y' && out[0] != 'z') {
+ // fmt.Println(out, g)
+ // }
+ // }
+ // ckb {2 hpp cmj} DONE
+ // tqq {2 bnp mtq} DONE
+ // ksv {2 qtf nsp} DONE
+
+ // for i := range uint64(50) {
+ // x := uint64(1) << i - 1
+ // res1 := evaluateAdder(gates, x, 1)
+ // res2 := x + 1
+ // if res1 != res2 {
+ // fmt.Println(i, res1, res2)
+ // }
+ // }
+ // Issue at 11
+ // printAround("z11", "", gates, 4)
+ // printAround("z10", "", gates, 4)
+ // z11 {XOR jsv pjk}
+ // jsv {OR jvr kbs}
+ // jvr {AND nbd dnn}
+ // nbd {AND x10 y10}
+ // dnn {OR jwh gcp}
+ // kbs {XOR y10 x10}
+ // pjk {XOR y11 x11}
+ //
+ // z10 {XOR dnn nbd}
+ // dnn {OR jwh gcp}
+ // jwh {AND tnc gbw}
+ // tnc {OR tjd vsw}
+ // gbw {XOR x09 y09}
+ // gcp {AND x09 y09}
+ // nbd {AND x10 y10}
+
+ // findGate := func(gate Gate) string {
+ // for output, g := range gates {
+ // if g.op == gate.op && ((g.a == gate.a && g.b == gate.b) || (g.a == gate.b && g.b == gate.a)) {
+ // return output
+ // }
+ // }
+ // return ""
+ // }
+
+ // carry := make([]string, 100)
+ // carry[0] = findGate(Gate{AND, "x00", "y00"})
+ // if carry[0] == "" {
+ // panic("Oh no")
+ // }
+
+ // for i := 1; i < 2; i++ {
+ // if tmpz0 := findGate(Gate{XOR, name('x', i), name('y', i)}); tmpz0 != "" {
+ // fmt.Println("tmpz0", i, name('x', i), name('y', i), "->", tmpz0)
+ // z := findGate(Gate{XOR, tmpz0, carry[i-1]})
+ // if z[0] == 'z' {
+ // fmt.Println("z", i, tmpz0, carry[i-1], "->", z)
+ // } else {
+ // fmt.Println("oh no")
+ // }
+ // } else if tmpz0 := findGate(Gate{XOR, name('x', i), carry[i-1]}); tmpz0 != "" {
+ // fmt.Println("tmpz0", i, name('x', i), carry[i-1], "->", tmpz0)
+ // } else if tmpz0 := findGate(Gate{XOR, name('y', i), carry[i-1]}); tmpz0 != "" {
+ // fmt.Println("tmpz0", i, name('y', i), carry[i-1], "->", tmpz0)
+ // }
+ // }
+
+ // // for output, g := range gates {
+
+ // // }
+
+ return ""
+}
+
+func readData(fileName string) (data Circuit) {
+ data = Circuit{
+ values: make(map[string]bool),
+ gates: make(map[string]Gate),
+ }
+
+ fp, _ := os.Open(fileName)
+ scanner := bufio.NewScanner(fp)
+
+ for scanner.Scan() {
+ line := strings.TrimSpace(scanner.Text())
+ if len(line) == 0 {
+ break
+ }
+
+ wire := line[0:3]
+ value := line[5] == '1'
+
+ data.values[wire] = value
+ }
+
+ for scanner.Scan() {
+ line := strings.Split(strings.TrimSpace(scanner.Text()), " ")
+ data.gates[line[4]] = Gate{line[1], line[0], line[2]}
+ }
+
+ return
+}