-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscratchoff.go
More file actions
122 lines (96 loc) · 2.52 KB
/
scratchoff.go
File metadata and controls
122 lines (96 loc) · 2.52 KB
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// ___ __ _ _
// | \ __ _ _ _ / \| | |
// | |) / _` | || | | () |_ _|
// |___/\__,_|\_, | \__/ |_|
// |__/
//
// "Scratchcards"
//
// Given a list of cards in the format `Card X: NN NN NN | MM MM MM`. Winning
// numbers you NEED are left of the separator, numbers you HAVE are on the right.
// Determine which numbers you have that are in the list. The first match is
// worth 1 point, each subsequent match doubles the points.
package main
import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
"strings"
)
const FILENAME = "input.txt"
const DEBUG = false
var CardParser = regexp.MustCompile(` (?P<card>\d+): ?(?P<winners>(\d+\s*)+)\| ?(?P<mine>(\d+\s*)+)`)
// Simple wrapper for debug printing
func DebugPrint(template string, data ...interface{}) {
if DEBUG {
fmt.Printf(template, data...)
}
}
func main() {
file, err := os.Open(FILENAME)
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
totalScore := 0
// For each "scratch card" (line in the input file)
for scanner.Scan() {
line := scanner.Text()
// Parse the line into its pieces
matches := CardParser.FindStringSubmatch(line)
// And convert the strings into int and []int
card := NumbersFromString(matches[CardParser.SubexpIndex("card")])[0]
winners := NumbersFromString(matches[CardParser.SubexpIndex("winners")])
mine := NumbersFromString(matches[CardParser.SubexpIndex("mine")])
score := scratchTheCard(mine, winners)
totalScore += score
DebugPrint("Card %d has %v (winning numbers %v)\n", card, mine, winners)
DebugPrint("Score: %d\n\n", score)
}
// Part One:
// Total Score: 21213
fmt.Printf("Total Score: %d\n", totalScore)
PartTwo()
}
// Given a string with spaces and numbers, return a slice of the integers
func NumbersFromString(input string) (output []int) {
pieces := strings.Split(input, " ")
for _, s := range pieces {
s = strings.TrimSpace(s)
if len(s) == 0 {
continue
}
n, err := strconv.Atoi(s)
if err != nil {
panic(err)
}
output = append(output, n)
}
return
}
// Utility function to find an int in a slice of ints
func SliceContains(haystack []int, needle int) bool {
for _, h := range haystack {
if h == needle {
return true
}
}
return false
}
// Given a slice of numbers and a slice of winning numbers, score the card
func scratchTheCard(mine []int, winning []int) (score int) {
score = 0
for _, n := range mine {
if SliceContains(winning, n) {
if score == 0 {
score = 1
} else {
score *= 2
}
}
}
return
}