-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday07.go
129 lines (113 loc) · 3.56 KB
/
day07.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
122
123
124
125
126
127
128
129
package main
import (
"fmt"
"io/ioutil"
"log"
"path/filepath"
"regexp"
"strconv"
"strings"
)
// Read the input file.
func getInput() []string {
filepath, err := filepath.Abs("2020/inputs/day07.txt")
if err != nil {
log.Fatal(err)
}
inputVal, err := ioutil.ReadFile(filepath)
if err != nil {
log.Fatal(err)
}
return strings.Split(string(inputVal), "\n")
}
// Turn the string input into a map structure where each outermost bag color is the key.
func parseInput(inputVal []string) map[string][]string {
bagMap := make(map[string][]string)
for _, element := range inputVal {
bagSplit := strings.Split(string(element), " bags contain ")
re := regexp.MustCompile(`([0-9]\s[a-z]*\s[a-z]*)\sbag[s]?(,?)[\.]?`)
contents := re.ReplaceAllString(bagSplit[1], "$1$2")
bagMap[bagSplit[0]] = strings.Split(contents, ", ")
}
return bagMap
}
// Create a map of the count of bags in each outermost bag
func parseCounts(bagMap map[string][]string) map[string]int {
bagCounts := make(map[string]int)
for key, value := range bagMap {
for _, element := range value {
re := regexp.MustCompile(`^([0-9])\s([a-z]*\s[a-z]*)`)
replacement := re.ReplaceAllString(element, "$1")
n, _ := strconv.Atoi(string(replacement))
bagCounts[key] += n
}
}
return bagCounts
}
// Given a bagColor return a slice of all the outermost bags which
// contain it.
func bagSearch(bagColor string, bagMap map[string][]string) []string {
var matches []string
for key, value := range bagMap {
for _, element := range value {
match, err := regexp.MatchString(bagColor, element)
if match && err == nil {
matches = append(matches, key)
}
}
}
return matches
}
// Create a map of the count of bags in each outermost bag
func bagCount(bagColor string, bagMap map[string][]string, bagCounts map[string]int) int {
totalCount := bagCounts[bagColor]
for _, match := range bagMap[bagColor] {
re := regexp.MustCompile(`^([0-9])\s([a-z]*\s[a-z]*)`)
multiple, _ := strconv.Atoi(re.ReplaceAllString(match, "$1"))
color := re.ReplaceAllString(match, "$2")
totalCount += bagCounts[color] * multiple
}
return totalCount
}
// Recursively search the bags
func recursiveSearch(bagColor string, bagMap map[string][]string) []string {
totalMatches := bagSearch(bagColor, bagMap)
for _, match := range totalMatches {
totalMatches = append(totalMatches, recursiveSearch(match, bagMap)...)
}
return totalMatches
}
func recursiveCount(bagColor string, bagMap map[string][]string, bagCounts map[string]int) int {
totalMatches := bagSearch(bagColor, bagMap)
totalCount := bagCount(bagColor, bagMap, bagCounts)
for _, match := range totalMatches {
totalMatches = append(totalMatches, recursiveSearch(match, bagMap)...)
totalCount += recursiveCount(match, bagMap, bagCounts)
}
return totalCount
}
// Count the number of outermost bags which can contain a shiny gold bag.
func partOne(inputVal []string) int {
bagColor := "shiny gold"
bagMap := parseInput(inputVal)
numberMatches := make(map[string]int)
matches := recursiveSearch(bagColor, bagMap)
for _, match := range matches {
numberMatches[match]++
}
return len(numberMatches)
}
// Count the number of bags a shiny gold bag must contain
func partTwo(inputVal []string) int {
bagColor := "shiny gold"
bagMap := parseInput(inputVal)
fmt.Println(bagMap)
bagCounts := parseCounts(bagMap)
totalCount := recursiveCount(bagColor, bagMap, bagCounts)
return totalCount
}
func main() {
inputVal := getInput()
fmt.Printf("Part One - Shiny Gold Bags: %d\n", partOne(inputVal))
fmt.Printf("Part Two - Total Bags in Shiny Gold: %d", partTwo(inputVal))
}