master
Raw Download raw file
  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("%8d\n", solution)
 94		return nil
 95	}
 96	if solution != i.Expected {
 97		fmt.Printf("%8d ❌\n", solution)
 98		return nil
 99	}
100	fmt.Printf("%8d ✅\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}