Skip to content

Commit 34c5664

Browse files
committed
Solution for 2024, day 24
1 parent 89002db commit 34c5664

File tree

4 files changed

+206
-0
lines changed

4 files changed

+206
-0
lines changed

2024/24/Makefile

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
input:
2+
http "https://adventofcode.com/2024/day/24/input" "Cookie:session=${AOC_SESSION};" >input
3+
4+
main1:
5+
go build -o main1 main1.go common.go
6+
7+
main2:
8+
go build -o main2 main2.go common.go
9+
10+
.PHONY: run1 run2 clean
11+
12+
run1: main1 input
13+
./main1 <input
14+
15+
run2: main2 input
16+
./main2 <input
17+
18+
clean:
19+
rm -f main1 main2 input
20+

2024/24/common.go

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package main
2+
3+
import (
4+
"bufio"
5+
"fmt"
6+
"os"
7+
"strings"
8+
)
9+
10+
type Rule struct {
11+
Left, Op, Right string
12+
}
13+
14+
func parseInput() (map[string]bool, map[string]Rule) {
15+
var facts = map[string]bool{}
16+
scanner := bufio.NewScanner(os.Stdin)
17+
for scanner.Scan() {
18+
line := scanner.Text()
19+
if line == "" {
20+
break
21+
}
22+
ff := strings.Split(line, ": ")
23+
facts[ff[0]] = ff[1] == "1"
24+
}
25+
26+
var rules = map[string]Rule{}
27+
for scanner.Scan() {
28+
ff := strings.Fields(scanner.Text())
29+
rules[ff[4]] = Rule{ff[0], ff[1], ff[2]}
30+
}
31+
32+
return facts, rules
33+
}
34+
35+
func GetNumber(letter string, facts map[string]bool, rules map[string]Rule) int {
36+
var z int
37+
for i := 63; i >= 0; i-- {
38+
if solve(fmt.Sprintf("%s%02d", letter, i), facts, rules) {
39+
z |= 1 << i
40+
}
41+
}
42+
return z
43+
}
44+
45+
func solve(target string, facts map[string]bool, rules map[string]Rule) bool {
46+
if v, ok := facts[target]; ok {
47+
return v
48+
}
49+
50+
rule, ok := rules[target]
51+
if !ok {
52+
return false
53+
}
54+
55+
left := solve(rule.Left, facts, rules)
56+
right := solve(rule.Right, facts, rules)
57+
58+
var result bool
59+
switch rule.Op {
60+
case "AND":
61+
result = left && right
62+
case "OR":
63+
result = left || right
64+
case "XOR":
65+
result = left != right
66+
}
67+
facts[target] = result
68+
return result
69+
}

2024/24/main1.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func main() {
6+
facts, rules := parseInput()
7+
z := GetNumber("z", facts, rules)
8+
fmt.Println(z)
9+
}

2024/24/main2.go

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"sort"
8+
"strings"
9+
)
10+
11+
func main() {
12+
facts, rules := parseInput()
13+
14+
// GenerateDot(rules)
15+
// return
16+
17+
// After generating the dot file, I could generate an image with
18+
//
19+
// dot -Tpng -O graph.dot
20+
//
21+
// and thanks to the colors of the arrows, it was easy to spot inconsistencies.
22+
// E.g.
23+
// All zXX were reached by two red arrows (a XOR operation).
24+
// `z13` was reached by two green, meaning it needed to be swapped with a node
25+
// that is reached by two red arrows instead of green.
26+
// `z19` and `z33` were incorrectly blue.
27+
//
28+
// The full list was:
29+
// - z13 green (supposed red)
30+
// - z19 blue (supposed red)
31+
// - z33 blue (supposed red)
32+
// - gws blue (supposed red)
33+
// - hgj red (supposed blue)
34+
// - npf red (supposed green)
35+
// - nnt red (supposed blue)
36+
// - cph red (supposed blue)
37+
38+
list := []string{"z13", "z19", "z33", "npf", "hgj", "gws", "nnt", "cph"}
39+
sort.Strings(list)
40+
fmt.Println(strings.Join(list, ","))
41+
42+
return
43+
44+
// The assignment didn't ask to fix the gates (so the list above is enough
45+
// to generate the solution:
46+
//
47+
// Anyway it's pretty easy to spot the pairs:
48+
// - z13 <> npf (the only green/red pair)
49+
// - gws <> nnt (they are both in the z09 area: a different swap would change the graph massively)
50+
// - z19 <> cph (they are both in the z19 area)
51+
// - z33 <> hgj (they are both in the z33 area)
52+
53+
swap("z13", "npf", rules)
54+
swap("z33", "hgj", rules)
55+
swap("gws", "nnt", rules)
56+
swap("z19", "cph", rules)
57+
x := GetNumber("x", facts, rules)
58+
y := GetNumber("y", facts, rules)
59+
z := GetNumber("z", facts, rules)
60+
fmt.Printf(" x: %d +\n y: %d =\nx+y: %d\n z: %d\n", x, y, x+y, z)
61+
fmt.Printf("Sum is working = %t\n", x+y == z)
62+
63+
// x: 22423510084409 +
64+
// y: 19634559019535 =
65+
// x+y: 42058069103944
66+
// z: 42058069103944
67+
// Sum is working = true
68+
}
69+
70+
func swap(r1, r2 string, rules map[string]Rule) {
71+
rules[r1], rules[r2] = rules[r2], rules[r1]
72+
}
73+
74+
func GenerateDot(rules map[string]Rule) {
75+
f, err := os.Create("graph.dot")
76+
if err != nil {
77+
log.Fatal(err)
78+
}
79+
defer f.Close()
80+
81+
const Size = 45
82+
fmt.Fprint(f, "digraph {\n")
83+
for rName, r := range rules {
84+
var color string
85+
switch r.Op {
86+
case "XOR":
87+
color = "red"
88+
case "AND":
89+
color = "blue"
90+
case "OR":
91+
color = "green"
92+
}
93+
94+
fmt.Fprintf(f, "%s -> %s [color=\"%s\"];\n", r.Left, rName, color)
95+
fmt.Fprintf(f, "%s -> %s [color=\"%s\"];\n", r.Right, rName, color)
96+
}
97+
98+
var xs, ys, zs []string
99+
for i := 0; i < Size; i++ {
100+
xs = append(xs, fmt.Sprintf("x%02d", i))
101+
ys = append(ys, fmt.Sprintf("y%02d", i))
102+
zs = append(zs, fmt.Sprintf("z%02d", i))
103+
}
104+
fmt.Fprintf(f, "{rank = min;\n %s ; \n};\n", strings.Join(xs, " -> "))
105+
fmt.Fprintf(f, "{rank = min;\n %s ; \n};\n", strings.Join(ys, " -> "))
106+
fmt.Fprintf(f, "{rank = max;\n %s ; \n};\n", strings.Join(zs, " -> "))
107+
fmt.Fprint(f, "}\n")
108+
}

0 commit comments

Comments
 (0)