105 lines
1.9 KiB
Go
105 lines
1.9 KiB
Go
|
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
|
||
|
}
|