-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
116 lines (95 loc) · 1.89 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package main
import (
"fmt"
"strings"
"github.com/devkvlt/aoc"
)
type Rule struct {
category byte
min int
max int
next string
}
func parseWorkflow(line string) (string, []Rule) {
fields := strings.Split(line, "{")
name := fields[0]
conds := strings.Split(fields[1][:len(fields[1])-1], ",")
workflow := make([]Rule, len(conds))
for i, cond := range conds {
if !strings.ContainsRune(cond, ':') {
workflow[i] = Rule{next: cond}
continue
}
category := cond[0]
split := strings.Split(cond, ":")
threshold := aoc.Atoi(split[0][2:])
next := split[1]
mi := 1
ma := 4000
if cond[1] == '>' {
mi = threshold + 1
} else {
ma = threshold - 1
}
workflow[i] = Rule{category, mi, ma, next}
}
return name, workflow
}
type Part map[byte]int
func parsePart(line string) Part {
p := make(Part)
line = line[1 : len(line)-1]
rs := strings.Split(line, ",")
for _, r := range rs {
k := strings.Split(r, "=")[0][0]
v := strings.Split(r, "=")[1]
p[k] = aoc.Atoi(v)
}
return p
}
var (
workflows map[string][]Rule
parts []Part
)
func init() {
chunks := aoc.Chunks("input")
workflows = make(map[string][]Rule, len(chunks[0]))
parts = make([]Part, len(chunks[1]))
for _, line := range chunks[0] {
id, wf := parseWorkflow(line)
workflows[id] = wf
}
for i, line := range chunks[1] {
parts[i] = parsePart(line)
}
}
func part1() {
total := 0
for _, part := range parts {
next := "in"
for {
if next == "A" {
total += part['x'] + part['m'] + part['a'] + part['s']
break
} else if next == "R" {
break
}
RulesLoop:
for _, rule := range workflows[next] {
if rule.min == 0 {
next = rule.next
} else {
rating := part[rule.category]
if rule.min <= rating && rating <= rule.max {
next = rule.next
break RulesLoop
}
}
}
}
}
fmt.Println(total)
}
func main() {
part1() // 377025
}