-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
97 lines (82 loc) · 2 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
package main
import (
"bufio"
"fmt"
"os"
"sort"
"strings"
)
func main() {
var input []string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
input = append(input, scanner.Text())
}
root := parseProgramTree(input)
unbalanced, diff := findUnbalancedChild(root)
fmt.Printf("Part 1: %s\n", root.Name)
fmt.Printf("Part 2: %d\n", unbalanced.Weight-diff)
}
type Program struct {
Name string `json:"name"`
Weight int `json:"weight"`
TotalWeight int `json:"total_weight"`
Parent *Program `json:"-"`
Children []*Program `json:"children"`
}
func setTotalWeights(root *Program) {
root.TotalWeight = root.Weight
for _, c := range root.Children {
setTotalWeights(c)
root.TotalWeight += c.TotalWeight
}
}
func findUnbalancedChild(root *Program) (child *Program, diff int) {
if len(root.Children) < 3 {
return nil, 0
}
sort.Slice(root.Children, func(i, j int) bool {
return root.Children[i].TotalWeight >= root.Children[j].TotalWeight
})
if c1, c2 := root.Children[0], root.Children[1]; c1.TotalWeight != c2.TotalWeight {
if c, d := findUnbalancedChild(c1); d != 0 {
return c, d
}
return c1, c1.TotalWeight - c2.TotalWeight
}
return nil, 0
}
func parseProgramTree(input []string) (root *Program) {
programMap := map[string]*Program{}
for _, entry := range input {
var name string
var weight int
fmt.Sscanf(entry, "%s (%d)", &name, &weight)
parent, ok := programMap[name]
if !ok {
parent = &Program{Name: name}
programMap[name] = parent
}
parent.Weight = weight
if idx := strings.Index(entry, "->"); idx > -1 {
childNames := strings.Split(entry[idx+3:], ", ")
for _, name := range childNames {
child, ok := programMap[name]
if !ok {
child = &Program{Name: name}
programMap[name] = child
}
child.Parent = parent
}
}
}
for _, p := range programMap {
if p.Parent != nil {
p.Parent.Children = append(p.Parent.Children, p)
} else {
root = p
}
}
setTotalWeights(root)
return root
}