github.com/dds/aoc2020@v1.9.84/day7/day7.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"strconv"
     6  	"strings"
     7  
     8  	"github.com/dds/aoc2020/lib"
     9  	"github.com/dds/aoc2020/lib/inputs"
    10  )
    11  
    12  func parse(s string) []string {
    13  	parts := lib.TrimSpace(strings.Split(s, "bags contain"))
    14  	if len(parts) < 2 {
    15  		return []string{}
    16  	}
    17  	bags := strings.Split(parts[1], ", ")
    18  	r := []string{parts[0]}
    19  	// Drop the last word from each group.
    20  	for _, b := range bags {
    21  		t := strings.Fields(b)
    22  		r = append(r, strings.Join(t[:len(t)-1], " "))
    23  	}
    24  	return r
    25  }
    26  
    27  var Input = lib.ParseInput(inputs.Day7(), parse)
    28  
    29  func part1(input [][]string) (rc int) {
    30  	m := map[string][]string{}
    31  	for _, row := range input {
    32  		for _, s := range row[1:] {
    33  			bag := s[2:]
    34  			m[bag] = append(m[bag], row[0])
    35  		}
    36  	}
    37  	bagQueue := []string{"shiny gold"}
    38  	seenBags := map[string]int{}
    39  	for len(bagQueue) > 0 {
    40  		bag := bagQueue[0]
    41  		bagQueue = bagQueue[1:]
    42  		for _, u := range m[bag] {
    43  			if seenBags[u] == 1 {
    44  				continue
    45  			}
    46  			seenBags[u] = 1
    47  			bagQueue = append(bagQueue, u)
    48  			rc++
    49  		}
    50  	}
    51  	return
    52  }
    53  
    54  func part2(input [][]string) (rc int) {
    55  	type bagCount struct {
    56  		count int
    57  		bag   string
    58  	}
    59  	m := map[string][]bagCount{}
    60  	for _, row := range input {
    61  		for _, s := range row[1:] {
    62  			count, err := strconv.Atoi(s[:1])
    63  			if err != nil {
    64  				count = 0
    65  			}
    66  			bag := s[2:]
    67  			m[row[0]] = append(m[row[0]], bagCount{count: count, bag: bag})
    68  		}
    69  	}
    70  	var count func(map[string][]bagCount, string) int
    71  	count = func(m map[string][]bagCount, bag string) (sum int) {
    72  		for _, u := range m[bag] {
    73  			sum += u.count * (1 + count(m, u.bag))
    74  		}
    75  		return sum
    76  	}
    77  	return count(m, "shiny gold")
    78  }
    79  
    80  func main() {
    81  	fmt.Println(part1(Input))
    82  	fmt.Println(part2(Input))
    83  }