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, ",")) } }