/
day21.go
98 lines (91 loc) · 2.28 KB
/
day21.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
package main
import (
"flag"
"fmt"
"io/ioutil"
"sort"
"strings"
)
var inputFile = flag.String("inputFile", "inputs/day21.input", "Relative file path to use as input.")
func main() {
flag.Parse()
bytes, err := ioutil.ReadFile(*inputFile)
if err != nil {
return
}
contents := string(bytes)
split := strings.Split(contents, "\n")
split = split[:len(split)-1]
foods := make(map[int][]string)
inverseContains := make(map[string][]int)
for i, s := range split {
parts := strings.Split(s, " (contains ")
ingreds := strings.Split(parts[0], " ")
for _, ing := range ingreds {
foods[i] = append(foods[i], ing)
}
allergens := strings.Split(parts[1][0:len(parts[1])-1], ", ")
for _, a := range allergens {
inverseContains[a] = append(inverseContains[a], i)
}
}
candidates := make(map[string]map[string]bool)
for allergen, recipes := range inverseContains {
// For each allergen, look for a food that is found in all of the
// recipes containing that allergen.
ingredientsSeen := make(map[string]int)
candidates[allergen] = make(map[string]bool)
for _, rNum := range recipes {
recipe := foods[rNum]
for _, i := range recipe {
ingredientsSeen[i]++
}
}
for k, v := range ingredientsSeen {
if v == len(recipes) {
// This is a candidate for being our allergen.
candidates[allergen][k] = true
}
}
}
foodToAllergenMapping := make(map[string]string)
allergenToFoodMapping := make(map[string]string)
for {
changed := false
for k, ingredients := range candidates {
for i := range foodToAllergenMapping {
delete(ingredients, i)
}
if len(ingredients) == 1 {
changed = true
delete(candidates, k)
for i := range ingredients {
foodToAllergenMapping[i] = k
allergenToFoodMapping[k] = i
}
}
}
if !changed {
break
}
}
var result int
for _, recipe := range foods {
for _, i := range recipe {
if _, found := foodToAllergenMapping[i]; !found {
result++
}
}
}
fmt.Println(result)
var allergens sort.StringSlice
for allergen := range allergenToFoodMapping {
allergens = append(allergens, allergen)
}
allergens.Sort()
dangerous := make([]string, len(allergens))
for i, allergen := range allergens {
dangerous[i] = allergenToFoodMapping[allergen]
}
fmt.Println(strings.Join(dangerous, ","))
}