adventofcode/2020/day21.go

135 lines
2.5 KiB
Go
Raw Normal View History

2020-12-21 06:07:42 +00:00
package main
import (
"fmt"
"os"
"regexp"
"sort"
"strings"
"git.annabunch.es/annabunches/adventofcode/2020/lib/util"
)
// could optimize this better with maps, but we'll just do this. Our data set should be small enough
func intersection(a, b []string) (result []string) {
result = make([]string, 0)
for _, av := range a {
for _, bv := range b {
if av == bv {
result = append(result, av)
break
}
}
}
return
}
func includes(list []string, item string) bool {
for _, cmp := range list {
if cmp == item {
return true
}
}
return false
}
func remove(list []string, item string) []string {
for i, cmp := range list {
if cmp == item {
return append(list[:i], list[i+1:]...)
}
}
return list
}
func parseInput(input []string) (ingredients map[string]int, allergens map[string][]string) {
re := regexp.MustCompile("^(.*) \\(contains (.*)\\)")
allergens = make(map[string][]string)
ingredients = make(map[string]int)
for _, line := range input {
data := re.FindStringSubmatch(line)
is := strings.Split(data[1], " ")
as := strings.Split(data[2], ", ")
for _, ingredient := range is {
ingredients[ingredient]++
}
for _, allergen := range as {
if ingredients, ok := allergens[allergen]; ok {
allergens[allergen] = intersection(is, ingredients)
} else {
allergens[allergen] = is
}
}
}
return
}
func findUniqueSolution(aMap map[string][]string) {
done := false
for !done {
done = true
for a1, is1 := range aMap {
if len(is1) == 1 {
ingredient := is1[0]
for a2, is2 := range aMap {
if a1 == a2 {
continue
}
aMap[a2] = remove(is2, ingredient)
}
}
}
for _, is := range aMap {
if len(is) > 1 {
done = false
break
}
}
}
}
func main() {
step := os.Args[1]
values := util.InputParserStrings(os.Args[2])
ingredients, allergenMap := parseInput(values)
switch step {
case "1":
loose := make([]string, 0)
for ingredient, _ := range ingredients {
found := false
for _, is := range allergenMap {
if includes(is, ingredient) {
found = true
break
}
}
if !found {
loose = append(loose, ingredient)
}
}
total := 0
for _, i := range loose {
total += ingredients[i]
}
fmt.Println(total)
case "2":
findUniqueSolution(allergenMap)
keys := make([]string, 0)
for k, _ := range allergenMap {
keys = append(keys, k)
}
result := ""
sort.Strings(keys)
for _, k := range keys {
result = result + "," + allergenMap[k][0]
}
fmt.Println(strings.Trim(result, ","))
}
}