diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-24 23:57:15 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2024-12-24 23:57:15 +0100 |
commit | 46859764ad4073da2c910ebd321320e1edb9b8c6 (patch) | |
tree | b0b4cccb96547eb25a2953ff62572f2c61e3de83 /day24/main.go | |
parent | c6ca510a5ccf232cbf0677a77453addb8d5d70be (diff) |
Fucking day 24
Diffstat (limited to 'day24/main.go')
-rw-r--r-- | day24/main.go | 256 |
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 +} |