2023-12-04 11:40:25 -07:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
|
|
|
_ "embed"
|
|
|
|
"log/slog"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
2023-12-13 08:32:37 -07:00
|
|
|
|
2023-12-15 15:13:24 -07:00
|
|
|
aoc "go.sour.is/advent-of-code"
|
2023-12-04 11:40:25 -07:00
|
|
|
)
|
|
|
|
|
|
|
|
//go:embed input.txt
|
|
|
|
var input []byte
|
|
|
|
|
|
|
|
type card struct {
|
|
|
|
card int
|
|
|
|
winner []int
|
|
|
|
scratch []int
|
|
|
|
copies int
|
|
|
|
}
|
|
|
|
|
2023-12-13 08:32:37 -07:00
|
|
|
func main() { aoc.MustResult(aoc.Runner(run)) }
|
2023-12-04 11:40:25 -07:00
|
|
|
|
2023-12-13 08:32:37 -07:00
|
|
|
type result struct {
|
|
|
|
points int
|
|
|
|
cards int
|
2023-12-04 11:40:25 -07:00
|
|
|
}
|
|
|
|
|
2023-12-13 08:32:37 -07:00
|
|
|
func run(scan *bufio.Scanner) (result, error) {
|
2023-12-04 11:40:25 -07:00
|
|
|
cards := []*card{}
|
|
|
|
|
|
|
|
for scan.Scan() {
|
|
|
|
pfx, text, ok := strings.Cut(scan.Text(), ":")
|
|
|
|
|
|
|
|
if !ok || !strings.HasPrefix(pfx, "Card ") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2023-12-13 08:32:37 -07:00
|
|
|
num := aoc.Atoi(strings.TrimSpace(strings.SplitN(pfx, " ", 2)[1]))
|
2023-12-04 11:40:25 -07:00
|
|
|
cards = append(cards, &card{card: num})
|
|
|
|
buf := make([]rune, 0, 4)
|
|
|
|
winner := true
|
|
|
|
|
|
|
|
for _, a := range text {
|
|
|
|
if a >= '0' && a <= '9' {
|
|
|
|
buf = append(buf, a)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if a == ' ' && len(buf) > 0 {
|
|
|
|
num, _ = strconv.Atoi(string(buf))
|
|
|
|
buf = buf[:0]
|
|
|
|
if winner {
|
|
|
|
cards[len(cards)-1].winner = append(cards[len(cards)-1].winner, num)
|
|
|
|
} else {
|
|
|
|
cards[len(cards)-1].scratch = append(cards[len(cards)-1].scratch, num)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if a == '|' {
|
|
|
|
winner = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(buf) > 0 {
|
2023-12-13 08:32:37 -07:00
|
|
|
num = aoc.Atoi(string(buf))
|
2023-12-04 11:40:25 -07:00
|
|
|
buf = buf[:0]
|
|
|
|
_ = buf // ignore
|
|
|
|
cards[len(cards)-1].scratch = append(cards[len(cards)-1].scratch, num)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var sumPoints int
|
|
|
|
var sumCards int
|
|
|
|
|
|
|
|
for _, card := range cards {
|
|
|
|
m := []int{}
|
|
|
|
|
|
|
|
for _, w := range card.winner {
|
|
|
|
for _, s := range card.scratch {
|
|
|
|
if w == s {
|
|
|
|
m = append(m, w)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(m) > 0 {
|
|
|
|
sumPoints += 1 << (len(m) - 1)
|
|
|
|
for i, c := range cards[card.card:min(card.card+len(m), len(cards))] {
|
|
|
|
c.copies += 1 + 1*card.copies
|
|
|
|
slog.Debug("cards", "card", card.card, "wins", i+1, "with", card.copies, "copies, wins", len(m), "giving", 1+1*card.copies, "for card", c.card, "total", c.copies)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sumCards += 1 + 1*card.copies
|
|
|
|
slog.Debug("cards", "card", card.card, "wins", len(m), "as", 1, "+", 1*card.copies, "for", 1+1*card.copies, "copies. total", sumCards)
|
|
|
|
slog.Debug("points", "card", card.card, "match", m, "score", sumPoints)
|
|
|
|
}
|
|
|
|
|
2023-12-13 08:32:37 -07:00
|
|
|
return result{sumPoints, sumCards}, nil
|
2023-12-04 11:40:25 -07:00
|
|
|
}
|