summaryrefslogtreecommitdiffstats
path: root/aoc23/day04_test.go
blob: 1d7aacd5d8eb6c00bdee7500147bb21105c84ee8 (plain) (blame)
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
package aoc23

import (
	"io"
	"slices"
	"strings"
	"testing"
)

type Card struct {
	id      int
	winners []int
	got     []int
}

func parseCard(s string) Card {
	parts := strings.FieldsFunc(s, func(r rune) bool { return r == ':' || r == '|' })
	id := requireInt(strings.Fields(parts[0])[1])
	winners := transform(strings.Fields(parts[1]), requireInt)
	slices.Sort(winners)
	got := transform(strings.Fields(parts[2]), requireInt)
	return Card{id, winners, got}
}

func countWinners(card Card) int {
	return quantify(card.got, func(n int) bool {
		_, found := slices.BinarySearch(card.winners, n)
		return found
	})
}

func cardPoints(r io.Reader) int {
	score := 0
	cards := parseLines(r, parseCard)
	for _, card := range cards {
		winners := countWinners(card)
		if winners > 0 {
			score += pow(2, winners-1)
		}
	}
	return score
}

func countCards(cards []Card) int {
	sum := 0
	for i, card := range cards {
		winners := countWinners(card)
		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)))
}