-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
121 lines (104 loc) · 2.29 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
117
118
119
120
121
package main
import (
input "aoc2020/inpututils"
"fmt"
"regexp"
"strconv"
"strings"
)
func main() {
fmt.Println("--- Part One ---")
fmt.Println(Part1("input.txt"))
fmt.Println("--- Part Two ---")
fmt.Println(Part2("input.txt"))
}
func Part1(filename string) int {
lines := input.ReadLines(filename)
bags := CreateGraph(lines)
var goldBagInside func(string) bool
goldBagInside = func(startBag string) bool {
if contents, bagExists := bags[startBag]; !bagExists || len(contents) == 0 {
return false
}
if startBag == "shiny gold bag" {
return true
}
contents := bags[startBag]
for _, b := range contents {
if goldBagInside(b.name) {
return true
}
}
return false
}
var s int
for bag, _ := range bags {
if bag != "shiny gold bag" && goldBagInside(bag) {
s += 1
}
}
return s
}
func Part2(filename string) int {
lines := input.ReadLines(filename)
graph := CreateGraph(lines)
var countBags func(string) int
countBags = func(bag string) int {
if contents, bagExists := graph[bag]; !bagExists || len(contents) == 0 {
return 0
}
contents, s := graph[bag], 0
for _, b := range contents {
s += b.num + (b.num * countBags(b.name))
}
return s
}
return countBags("shiny gold bag")
}
func CreateGraph(lines []string) map[string][]innerBag {
bags := map[string][]innerBag{}
for _, line := range lines {
splittedString := strings.Split(line, "contain")
outerBag, innerBags := trimBag(splittedString[0]), splittedString[1]
bags[outerBag] = []innerBag{}
if innerBags != "no other bags." {
splitBags := strings.Split(innerBags, ",")
for _, bag := range splitBags {
re := regexp.MustCompile(`(\d+) (\S+.*)`)
parts := re.FindStringSubmatch(trimBag(bag))
if len(parts) == 3 {
num, bagName := toInt(parts[1]), parts[2]
bags[outerBag] = append(bags[outerBag], innerBag{bagName, num})
}
}
}
}
return bags
}
func trimBag(bag string) string {
bag = strings.TrimSpace(bag)
bag = strings.TrimRight(bag, ".")
bag = strings.TrimRight(bag, "s")
return bag
}
type innerBag struct {
name string
num int
}
func sum(arr []int) int {
var s int
for _, a := range arr {
s += a
}
return s
}
func toInt(s string) int {
i, err := strconv.Atoi(s)
check(err)
return i
}
func check(err error) {
if err != nil {
panic(err)
}
}