1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
package aoc23
import (
"io"
"slices"
"strings"
"testing"
)
type Card struct {
winning []int
numbers []int
matches int
}
func parseCard(s string) Card {
parts := strings.FieldsFunc(s, func(r rune) bool { return r == ':' || r == '|' })
winning := transform(strings.Fields(parts[1]), atoi)
slices.Sort(winning)
numbers := transform(strings.Fields(parts[2]), atoi)
return Card{winning, numbers, -1}
}
func (c *Card) winners() int {
if c.matches < 0 {
c.matches = quantify(c.numbers, func(n int) bool {
_, found := slices.BinarySearch(c.winning, n)
return found
})
}
return c.matches
}
func cardPoints(r io.Reader) int {
score := 0
cards := parseLines(r, parseCard)
for _, card := range cards {
winners := card.winners()
if winners > 0 {
score += pow(2, winners-1)
}
}
return score
}
func countCards(cards []Card) int {
sum := 0
for i := range cards {
winners := cards[i].winners()
next := i + 1
sum += 1 + countCards(cards[next:next+winners])
}
return sum
}
func cardCount(r io.Reader) int {
cards := parseLines(r, parseCard)
return countCards(cards)
}
func TestDay04(t *testing.T) {
example := `
Card 1: 41 48 83 86 17 | 83 86 6 31 17 9 48 53
Card 2: 13 32 20 16 61 | 61 30 68 82 17 32 24 19
Card 3: 1 21 53 59 44 | 69 82 63 72 16 21 14 1
Card 4: 41 92 73 84 69 | 59 84 76 51 58 5 54 83
Card 5: 87 83 26 28 32 | 88 30 70 12 93 22 82 36
Card 6: 31 18 13 56 72 | 74 77 10 23 35 67 36 11
`
assert(t, 13, run(cardPoints, inputString(example)))
assert(t, 32001, run(cardPoints, inputFile(4)))
assert(t, 30, run(cardCount, inputString(example)))
assert(t, 5037841, run(cardCount, inputFile(4)))
}
|