package main import ( "fmt" "math" "strings" h "git.bullercodeworks.com/brian/adventofcode/helpers" ) func main() { inp := h.StdinToStringSlice() part1(inp) fmt.Println() part2(inp) } func part1(input []string) { var total int for i := range input { total += cardFromLine(input[i]).Value() } fmt.Println("# Part 1") fmt.Println(total) } func part2(input []string) { cards := make(map[int]*Card) for i := range input { c := cardFromLine(input[i]) cards[c.id] = c } result := len(cards) for _, card := range cards { result += card.TotalCardsWon(cards) } fmt.Println("# Part 2") fmt.Println(result) } type Card struct { id int winners []int numbers []int winsCards []int totalCardsWon int } func (c Card) String() string { return fmt.Sprintf("Card %d: %v | %v", c.id, c.winners, c.numbers) } func cardFromLine(input string) *Card { pts := strings.Fields(input) ret := Card{id: h.Atoi(pts[1]), totalCardsWon: -1} winners := true for _, s := range pts[2:] { if s == "|" { winners = false } else { if winners { ret.winners = append(ret.winners, h.Atoi(s)) } else { ret.numbers = append(ret.numbers, h.Atoi(s)) } } } for _, w := range ret.winners { for _, n := range ret.numbers { skip := h.IntSliceContains(ret.winsCards, w) if n == w && !skip { ret.winsCards = append(ret.winsCards, w) } if skip { break } } } return &ret } func (c *Card) Value() int { return int(math.Pow(2, float64(len(c.winsCards)-1))) } func (c *Card) TotalCardsWon(cm map[int]*Card) int { if c.totalCardsWon != -1 { return c.totalCardsWon } result := len(c.winsCards) // TODO: It doesn't with cards that match the ID, // it wins X cards increasing from the current cards ID // where x is the number of winning numbers matched for i := 1; i <= len(c.winsCards); i++ { if v, ok := cm[c.id+i]; ok { result += v.TotalCardsWon(cm) } } c.totalCardsWon = result return result }