-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday07.go
More file actions
119 lines (93 loc) · 3.17 KB
/
day07.go
File metadata and controls
119 lines (93 loc) · 3.17 KB
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
package main
import (
"fmt"
"strings"
)
func readSingleRule(ruleLine string, bagRules map[string]map[string]int, part byte, debug bool) {
// split on "contain". On the left is the master bag. On the right the remainder
// check remainder for "no other bags"
// split the remainder on ","
// - process each of the remaining strings as a bag
var topLevelBag string
initialSplit := strings.Split(ruleLine, "contain")
topLevelBag = strings.Trim(initialSplit[0], " ")
topLevelBag = strings.TrimSuffix(topLevelBag, " bags")
topLevelBag = strings.TrimSuffix(topLevelBag, " bag")
bagRules[topLevelBag] = make(map[string]int)
if strings.Trim(initialSplit[1], " .") == "no other bags" {
if debug {
fmt.Println("No other bags so stop processing")
}
} else {
for _, item := range strings.Split(initialSplit[1], ",") {
var numBags int = 0
var lowerLevelBag string
item = strings.Trim(item, " .")
// Grab the number, plus trim spaces, full stops and get rid of bag/bags
fmt.Sscanf(item, "%d %s", &numBags, &lowerLevelBag)
lowerLevelBag = item[strings.IndexByte(item, ' ')+1:]
lowerLevelBag = strings.TrimSuffix(lowerLevelBag, " bags")
lowerLevelBag = strings.TrimSuffix(lowerLevelBag, " bag")
bagRules[topLevelBag][lowerLevelBag] = numBags
}
}
}
func searchBagsRecurse(bagRules map[string]map[string]int, topLevelBag string, bagToSearch string) int {
var foundCount int = 0
for thing := range bagRules[topLevelBag] {
if thing == bagToSearch {
//fmt.Println("Got it in searchBagsRecurse")
return 1
}
foundCount = searchBagsRecurse(bagRules, thing, bagToSearch)
if foundCount > 0 {
return 1
}
}
return 0
}
func searchBags(bagRules map[string]map[string]int, bagToSearch string) int {
var foundBagsCount int = 0
for thing := range bagRules {
if thing == bagToSearch {
// If we find it at the top level we ignore it as needs to be INSIDE another bag
//fmt.Println("Got it in searchBags")
} else {
foundBagsCount += searchBagsRecurse(bagRules, thing, bagToSearch)
}
}
return foundBagsCount
}
// Process the whole file of bag rules
// Build a map of maps containing the rules
func processAllBagRules(filename string, bagToSearch string, part byte, debug bool) int {
var bagRules map[string]map[string]int
bagRules = make(map[string]map[string]int)
puzzleInput, _ := readFile(filename)
for _, singleRule := range puzzleInput {
readSingleRule(singleRule, bagRules, part, debug)
}
bagToSearch = strings.TrimSuffix(bagToSearch, " bags")
bagToSearch = strings.TrimSuffix(bagToSearch, " bag")
if debug {
fmt.Println("Bag to Search for:", bagToSearch)
fmt.Println("Bag Rules:", bagRules)
}
if part == 'a' {
return searchBags(bagRules, bagToSearch)
}
return countNeededBags(bagRules, bagToSearch)
}
// Main routine
func main() {
filenamePtr, execPart, debug, test := catchUserInput()
if test {
}
if execPart == 'z' {
fmt.Println("Bad part choice. Available choices are 'a' and 'b'")
} else if execPart == 'a' {
fmt.Println("Bag Varieties:", processAllBagRules(filenamePtr, "shiny gold bag", execPart, debug))
} else {
fmt.Println("Number of Bags:", processAllBagRules(filenamePtr, "shiny gold bag", execPart, debug))
}
}