Skip to content

Commit aeb6d7b

Browse files
committed
21st day
1 parent 5a04889 commit aeb6d7b

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

day21/day21.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
"strings"
7+
8+
. "majcn.si/advent-of-code-2022/util"
9+
)
10+
11+
type Node interface {
12+
Value() float64
13+
}
14+
15+
type ValueNode struct {
16+
V float64
17+
}
18+
19+
func (node *ValueNode) Value() float64 {
20+
return node.V
21+
}
22+
23+
type EquationNode struct {
24+
Left Node
25+
Right Node
26+
Function func(left float64, right float64) float64
27+
}
28+
29+
func (node *EquationNode) Value() float64 {
30+
return node.Function(node.Left.Value(), node.Right.Value())
31+
}
32+
33+
type DataType map[string]Node
34+
35+
func parseData(data string) DataType {
36+
dataSplit := strings.Split(data, "\n")
37+
38+
rValueNode := regexp.MustCompile(`^(\w{4}): (\d+)$`)
39+
rEquationNode := regexp.MustCompile(`^(\w{4}): (\w{4}) ([+\-*/]) (\w{4})$`)
40+
41+
result := make(map[string]Node, len(data))
42+
for _, line := range dataSplit {
43+
match := rValueNode.FindStringSubmatch(line)
44+
if match != nil {
45+
result[match[1]] = &ValueNode{V: float64(ParseInt(match[2]))}
46+
} else {
47+
result[line[:4]] = &EquationNode{}
48+
}
49+
}
50+
51+
for _, line := range dataSplit {
52+
match := rEquationNode.FindStringSubmatch(line)
53+
if match != nil {
54+
node, _ := result[match[1]].(*EquationNode)
55+
node.Left = result[match[2]]
56+
node.Right = result[match[4]]
57+
switch match[3][0] {
58+
case '+':
59+
node.Function = func(left float64, right float64) float64 { return left + right }
60+
case '-':
61+
node.Function = func(left float64, right float64) float64 { return left - right }
62+
case '*':
63+
node.Function = func(left float64, right float64) float64 { return left * right }
64+
case '/':
65+
node.Function = func(left float64, right float64) float64 { return left / right }
66+
}
67+
}
68+
}
69+
70+
return result
71+
}
72+
73+
func solvePart1(data DataType) (rc int) {
74+
return int(data["root"].Value())
75+
}
76+
77+
func solvePart2(data DataType) (rc int) {
78+
rootNode := data["root"].(*EquationNode)
79+
right := rootNode.Right.Value()
80+
81+
a := 0
82+
b := MaxInt / 2
83+
for {
84+
c := (a + b) / 2
85+
data["humn"].(*ValueNode).V = float64(c)
86+
left := rootNode.Left.Value()
87+
88+
switch {
89+
case left > right:
90+
a = c
91+
case left < right:
92+
b = c
93+
default:
94+
return c
95+
}
96+
}
97+
}
98+
99+
func main() {
100+
data := parseData(FetchInputData(21))
101+
fmt.Println(solvePart1(data))
102+
fmt.Println(solvePart2(data))
103+
}

day21/day21_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
. "majcn.si/advent-of-code-2022/util"
8+
)
9+
10+
func ExpectedPart1() int {
11+
return 152
12+
}
13+
14+
func ExpectedPart2() int {
15+
return 301
16+
}
17+
18+
var data DataType
19+
20+
func init() {
21+
input, _ := os.ReadFile("../examples/21.txt")
22+
data = parseData(string(input))
23+
}
24+
25+
func TestPart1(t *testing.T) {
26+
AssertTestPartX(t, ExpectedPart1(), solvePart1(data))
27+
}
28+
29+
func TestPart2(t *testing.T) {
30+
AssertTestPartX(t, ExpectedPart2(), solvePart2(data))
31+
}

examples/21.txt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root: pppw + sjmn
2+
dbpl: 5
3+
cczh: sllz + lgvd
4+
zczc: 2
5+
ptdq: humn - dvpt
6+
dvpt: 3
7+
lfqf: 4
8+
humn: 5
9+
ljgn: 2
10+
sjmn: drzm * dbpl
11+
sllz: 4
12+
pppw: cczh / lfqf
13+
lgvd: ljgn * ptdq
14+
drzm: hmdt - zczc
15+
hmdt: 32

0 commit comments

Comments
 (0)