master
1package aoc
2
3import (
4 "bufio"
5 "fmt"
6 "log"
7 "os"
8 "time"
9)
10
11const (
12 Example = InputType("e")
13 Puzzle = InputType("p")
14
15 Part1 = Part(1)
16 Part2 = Part(2)
17
18 Day1 = Day(1)
19 Day2 = Day(2)
20 Day3 = Day(3)
21 Day4 = Day(4)
22 Day5 = Day(5)
23 Day6 = Day(6)
24 Day7 = Day(7)
25 Day8 = Day(8)
26 Day9 = Day(9)
27 Day10 = Day(10)
28 Day11 = Day(11)
29 Day12 = Day(12)
30 Day13 = Day(13)
31 Day14 = Day(14)
32 Day15 = Day(15)
33 Day16 = Day(16)
34 Day17 = Day(17)
35 Day18 = Day(18)
36 Day19 = Day(19)
37 Day20 = Day(20)
38 Day21 = Day(21)
39 Day22 = Day(22)
40 Day23 = Day(23)
41 Day24 = Day(24)
42 Day25 = Day(25)
43
44 UnknownExpected = -1
45)
46
47type InputType string
48type Day int
49type Part int
50
51type Solve func([]string) int
52
53type ProblemId struct {
54 Day Day
55 Part Part
56}
57
58type Input struct {
59 ProblemId
60 Solve
61 Type InputType
62 Expected int
63}
64
65func (i Input) String() string {
66 var t string = "Example"
67 if i.Type == Puzzle {
68 t = "Puzzle"
69 }
70 return fmt.Sprintf("Day %02d, Part %d %7s: ", i.Day, i.Part, t)
71
72}
73
74func (i Input) Calculate() (err error) {
75 inputFilename := fmt.Sprintf("../input/%02d-%s%d.txt", i.Day, i.Type, i.Part)
76 input := []string{}
77 file, err := os.Open(inputFilename)
78 if err != nil {
79 return fmt.Errorf("failed to open %s: %w", inputFilename, err)
80 }
81 defer file.Close()
82
83 scanner := bufio.NewScanner(file)
84 for scanner.Scan() {
85 input = append(input, scanner.Text())
86 }
87 if err := scanner.Err(); err != nil {
88 return fmt.Errorf("failed to scan by lines: %w", err)
89 }
90
91 solution := i.Solve(input)
92 if i.Expected == UnknownExpected {
93 fmt.Printf("%12d\n", solution)
94 return nil
95 }
96 if solution != i.Expected {
97 fmt.Printf("%12d ❌\n", solution)
98 return nil
99 }
100 fmt.Printf("%12d ✅\n", solution)
101 return nil
102}
103
104func EventDay(year int) (day int) {
105
106 start := time.Date(year, time.December, 1, 0, 0, 0, 0, time.UTC)
107 now := time.Now()
108 end := time.Date(year, time.December, 25, 0, 0, 0, 0, time.UTC)
109
110 if now.After(end) {
111 return 25
112 }
113 if now.Before(start) {
114 return 0
115 }
116 return now.Day()
117}
118
119func ReleasedDays(year int) (days []Day) {
120 today := EventDay(year)
121 days = []Day{}
122 for d := 1; d <= today; d++ {
123 days = append(days, Day(d))
124 }
125 return days
126}
127
128func SolveExample(day Day, part Part, fn Solve, expected int) {
129 i := Input{
130 ProblemId: ProblemId{
131 Day: day,
132 Part: part,
133 },
134 Type: Example,
135 Solve: fn,
136 Expected: expected,
137 }
138 err := i.Calculate()
139 if err != nil {
140 log.Fatal(err)
141 }
142}
143
144func SolvePuzzle(day Day, part Part, fn Solve, expected int) {
145 i := Input{
146 ProblemId: ProblemId{
147 Day: day,
148 Part: part,
149 },
150 Type: Puzzle,
151 Solve: fn,
152 Expected: expected,
153 }
154 err := i.Calculate()
155 if err != nil {
156 log.Fatal(err)
157 }
158}