diff --git a/2020/day01/go.mod b/2020/day01/go.mod deleted file mode 100644 index 87e4b5b..0000000 --- a/2020/day01/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2020/day01 - -go 1.25.4 diff --git a/2020/day02/go.mod b/2020/day02/go.mod deleted file mode 100644 index cac6c86..0000000 --- a/2020/day02/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2020/day02 - -go 1.25.4 diff --git a/2020/day03/go.mod b/2020/day03/go.mod deleted file mode 100644 index 1793f03..0000000 --- a/2020/day03/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2020/day03 - -go 1.25.4 diff --git a/2020/day04/go.mod b/2020/day04/go.mod deleted file mode 100644 index 5cf272d..0000000 --- a/2020/day04/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2020/day04 - -go 1.25.4 diff --git a/2020/day05/go.mod b/2020/day05/go.mod deleted file mode 100644 index 1ca3d73..0000000 --- a/2020/day05/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2020/day05 - -go 1.25.4 diff --git a/2020/day06/go.mod b/2020/day06/go.mod deleted file mode 100644 index fc13a4f..0000000 --- a/2020/day06/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2020/day06 - -go 1.25.4 diff --git a/2021/day01/go.mod b/2021/day01/go.mod deleted file mode 100644 index 2a8c064..0000000 --- a/2021/day01/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2021/day01 - -go 1.25.4 diff --git a/2021/day02/go.mod b/2021/day02/go.mod deleted file mode 100644 index 29c9096..0000000 --- a/2021/day02/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2021/day02 - -go 1.25.4 diff --git a/2021/day03/go.mod b/2021/day03/go.mod deleted file mode 100644 index 0dd8a55..0000000 --- a/2021/day03/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module 2021/day03 - -go 1.25.4 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6414976 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +GO = go +BIN = bin/aoc + +.PHONY: build test clean + +build: + $(GO) build -o $(BIN) ./cmd/aoc + +test: + $(GO) test ./... + +clean: + rm -f $(BIN) diff --git a/README.md b/README.md index 1ff4f7b..885eff3 100644 --- a/README.md +++ b/README.md @@ -16,26 +16,61 @@ Also, it's a fresh start from 2025. I do some exercises from other years along t ## Repository Structure ``` -yyyy/ -├── dayXX/ -│ ├── main.go # The main code to run to print solutions. -│ ├── main_test.go # The test file that validates the logic. -│ └── input.txt # The day's puzzle input. -└── ... +├── cmd/ +│ └── aoc/ +│ └── main.go # CLI entry point that runs solutions +└── internal/ + ├── 2020/ + │ ├── DayOne/ + │ │ ├── code.go # Go solution for Day 1 (2020) + │ │ └── code_test.go # Unit tests for Day 1 + │ └── ... + ├── 2021/ + │ └── ... # Additional years and days + ├── registry/ + │ └── registry.go # Central registry for day runners + └── data/ + ├── 2020/ + │ ├── DayOne/ + │ │ └── input.txt # Puzzle input for Day 1 (2020) + │ └── ... + └── ... ``` -Each day's code can be run with: +Each day's solution is organized into its own folder, named according to the day number (e.g., `DayOne`, `DayTwo`). Inside each folder, you'll find a `code.go` file with the Go implementation of the solution and a `code_test.go` file containing corresponding tests. The input data for each puzzle is located in the `internal/data` directory, mirroring the code structure for easy access. + +To connect each solution to the CLI, the repository uses a central registry located in `internal/registry/registry.go`. This registry is essentially a map linking a day key (combining year and day number) to assign a "day runner" which is a struct that specifies the `ParseInput`, `PartOne` and `PartTwo` functions of the day's problem. + +When running a solution, the CLI (`cmd/aoc/main.go`) looks up the appropriate runner from the registry based on your command-line input, uses the parsing function to load the input data, and then runs the desired part (or both parts) using the registered solution functions. + +## Usage + +Build the CLI tool: ```bash -cd yyyy/dayXX -go run main.go +make ``` -Expected output: +Run a day's solution: ```bash -Part 1: -Part 2: +bin/aoc 2020D1 # Run both parts +bin/aoc 2020D1P1 # Run only part one +bin/aoc 2020D1P2 # Run only part two +``` + +Example output: + +```bash +$ bin/aoc 2020D1 +197451 +138233720 + +$ bin/aoc 2020D1P1 +197451 + +$ bin/aoc 2020D1P2 +138233720 ``` ## Tests @@ -55,13 +90,18 @@ In this example, the calibration values of these four lines are 12, 38, 15, and Adding these together produces 142. ``` -I'm using these examples to validate my logic. +I'm using these examples each day to validate my logic. -If you want to run those, you can use: +Run all tests: ```bash -cd dayXX -go test +make test +``` + +Or run tests for a specific day: + +```bash +go test ./internal/2020/DayOne/... ``` ## Notes diff --git a/cmd/aoc/main.go b/cmd/aoc/main.go new file mode 100644 index 0000000..a0da1b6 --- /dev/null +++ b/cmd/aoc/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "advent-of-code/internal/registry" + "fmt" + "log" + "os" + "path/filepath" + "regexp" + + _ "advent-of-code/internal/2020/DayFour" + _ "advent-of-code/internal/2020/DayOne" + _ "advent-of-code/internal/2020/DaySix" + _ "advent-of-code/internal/2020/DayThree" + _ "advent-of-code/internal/2020/DayTwo" + _ "advent-of-code/internal/2021/DayOne" + _ "advent-of-code/internal/2021/DayThree" + _ "advent-of-code/internal/2021/DayTwo" +) + +func capitalize(day string) string { + dayNames := map[string]string{ + "1": "One", "2": "Two", "3": "Three", "4": "Four", "5": "Five", + "6": "Six", "7": "Seven", "8": "Eight", "9": "Nine", "10": "Ten", + "11": "Eleven", "12": "Twelve", "13": "Thirteen", "14": "Fourteen", "15": "Fifteen", + "16": "Sixteen", "17": "Seventeen", "18": "Eighteen", "19": "Nineteen", "20": "Twenty", + "21": "TwentyOne", "22": "TwentyTwo", "23": "TwentyThree", "24": "TwentyFour", "25": "TwentyFive", + } + return dayNames[day] +} + +func main() { + if len(os.Args) < 2 { + fmt.Fprintf(os.Stderr, "Usage: %s D[P]\n", os.Args[0]) + os.Exit(1) + } + + re := regexp.MustCompile(`^(\d{4})D(\d+)(?:P(\d+))?$`) + matches := re.FindStringSubmatch(os.Args[1]) + if matches == nil { + fmt.Fprintf(os.Stderr, "Invalid format: %s\n", os.Args[1]) + os.Exit(1) + } + + year, dayNum, part := matches[1], matches[2], matches[3] + dayKey := fmt.Sprintf("%sD%s", year, dayNum) + dayName := fmt.Sprintf("Day%s", capitalize(dayNum)) + input := filepath.Join("internal", "data", year, dayName, "input.txt") + + runner, ok := registry.Days[dayKey].(registry.Runner) + if !ok { + log.Fatalf("Day not found: %s\n", dayKey) + } + + runner.Run(input, part) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..1cebb14 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module advent-of-code + +go 1.25.4 diff --git a/2020/day05/main.go b/internal/2020/DayFive/code.go similarity index 78% rename from 2020/day05/main.go rename to internal/2020/DayFive/code.go index 5522ed3..dce8086 100644 --- a/2020/day05/main.go +++ b/internal/2020/DayFive/code.go @@ -1,18 +1,13 @@ -package main +package dayfive import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } - return strings.Split(string(content), "\n") +func init() { + registry.Register("2020D5", ParseInput, PartOne, PartTwo) } func calculateSeatID(pass string) int { @@ -39,6 +34,11 @@ func calculateSeatID(pass string) int { return row*8 + column } +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) + return strings.Split(string(content), "\n") +} + func PartOne(input []string) int { maxSeatID := 0 for _, pass := range input { @@ -77,9 +77,3 @@ func PartTwo(input []string) int { return 0 } - -func main() { - input := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(input)) - fmt.Println("Part 2:", PartTwo(input)) -} diff --git a/2020/day05/main_test.go b/internal/2020/DayFive/code_test.go similarity index 96% rename from 2020/day05/main_test.go rename to internal/2020/DayFive/code_test.go index 7425b52..a4d4d8c 100644 --- a/2020/day05/main_test.go +++ b/internal/2020/DayFive/code_test.go @@ -1,4 +1,4 @@ -package main +package dayfive import "testing" @@ -32,3 +32,4 @@ func TestPartTwo(t *testing.T) { t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2020/day04/main.go b/internal/2020/DayFour/code.go similarity index 91% rename from 2020/day04/main.go rename to internal/2020/DayFour/code.go index db47628..7ea293c 100644 --- a/2020/day04/main.go +++ b/internal/2020/DayFour/code.go @@ -1,18 +1,18 @@ -package main +package dayfour import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strconv" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2020D4", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) text := string(content) passports := strings.Split(text, "\n\n") @@ -152,8 +152,3 @@ func PartTwo(data []string) int { return count } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2020/day04/main_test.go b/internal/2020/DayFour/code_test.go similarity index 79% rename from 2020/day04/main_test.go rename to internal/2020/DayFour/code_test.go index c156414..701fc32 100644 --- a/2020/day04/main_test.go +++ b/internal/2020/DayFour/code_test.go @@ -1,4 +1,4 @@ -package main +package dayfour import "testing" @@ -13,7 +13,7 @@ func TestPartOne(t *testing.T) { expected := 2 got := PartOne(testInput) if got != expected { - t.Errorf("PartOne(%v) = %d, want %d", testInput, got, expected) + t.Errorf("PartOne() = %d, want %d", got, expected) } } @@ -21,6 +21,7 @@ func TestPartTwo(t *testing.T) { expected := 2 got := PartTwo(testInput) if got != expected { - t.Errorf("PartTwo(%v) = %d, want %d", testInput, got, expected) + t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2020/day01/main.go b/internal/2020/DayOne/code.go similarity index 62% rename from 2020/day01/main.go rename to internal/2020/DayOne/code.go index 88a6e66..a191fe2 100644 --- a/2020/day01/main.go +++ b/internal/2020/DayOne/code.go @@ -1,25 +1,22 @@ -package main +package dayone import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strconv" "strings" ) -func parseInput(file string) []int { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2020D1", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []int { + content, _ := os.ReadFile(filepath) lines := strings.Fields(string(content)) var data []int for _, line := range lines { - num, err := strconv.Atoi(line) - if err != nil { - log.Fatalf("Failed to convert string to int: %v", err) - } + num, _ := strconv.Atoi(line) data = append(data, num) } return data @@ -51,8 +48,3 @@ func PartTwo(data []int) int { return 0 } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2020/day01/main_test.go b/internal/2020/DayOne/code_test.go similarity index 66% rename from 2020/day01/main_test.go rename to internal/2020/DayOne/code_test.go index 9830f3b..3bb68a4 100644 --- a/2020/day01/main_test.go +++ b/internal/2020/DayOne/code_test.go @@ -1,4 +1,4 @@ -package main +package dayone import "testing" @@ -8,7 +8,7 @@ func TestPartOne(t *testing.T) { expected := 514579 got := PartOne(testInput) if got != expected { - t.Errorf("PartOne(%v) = %d, want %d", testInput, got, expected) + t.Errorf("PartOne() = %d, want %d", got, expected) } } @@ -16,6 +16,7 @@ func TestPartTwo(t *testing.T) { expected := 241861950 got := PartTwo(testInput) if got != expected { - t.Errorf("PartTwo(%v) = %d, want %d", testInput, got, expected) + t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2020/day06/main.go b/internal/2020/DaySix/code.go similarity index 76% rename from 2020/day06/main.go rename to internal/2020/DaySix/code.go index ad71c8c..fdc1249 100644 --- a/2020/day06/main.go +++ b/internal/2020/DaySix/code.go @@ -1,17 +1,17 @@ -package main +package daysix import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2020D6", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) return strings.Split(strings.TrimSpace(string(content)), "\n") } @@ -68,8 +68,3 @@ func PartTwo(input []string) int { return total } -func main() { - input := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(input)) - fmt.Println("Part 2:", PartTwo(input)) -} diff --git a/2020/day06/main_test.go b/internal/2020/DaySix/code_test.go similarity index 79% rename from 2020/day06/main_test.go rename to internal/2020/DaySix/code_test.go index 86ae0f8..e634248 100644 --- a/2020/day06/main_test.go +++ b/internal/2020/DaySix/code_test.go @@ -1,8 +1,8 @@ -package main +package daysix import "testing" -var input = []string{ +var testInput = []string{ "abc", "", "a", @@ -22,7 +22,7 @@ var input = []string{ func TestPartOne(t *testing.T) { expected := 11 - got := PartOne(input) + got := PartOne(testInput) if got != expected { t.Errorf("PartOne() = %d, want %d", got, expected) } @@ -30,8 +30,9 @@ func TestPartOne(t *testing.T) { func TestPartTwo(t *testing.T) { expected := 6 - got := PartTwo(input) + got := PartTwo(testInput) if got != expected { t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2020/day03/main.go b/internal/2020/DayThree/code.go similarity index 70% rename from 2020/day03/main.go rename to internal/2020/DayThree/code.go index bb57abb..53764ab 100644 --- a/2020/day03/main.go +++ b/internal/2020/DayThree/code.go @@ -1,17 +1,17 @@ -package main +package daythree import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2020D3", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) return strings.Split(string(content), "\n") } @@ -50,8 +50,3 @@ func PartTwo(input []string) int { return result } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2020/day03/main_test.go b/internal/2020/DayThree/code_test.go similarity index 96% rename from 2020/day03/main_test.go rename to internal/2020/DayThree/code_test.go index c13a358..04f5aa8 100644 --- a/2020/day03/main_test.go +++ b/internal/2020/DayThree/code_test.go @@ -1,4 +1,4 @@ -package main +package daythree import "testing" @@ -31,3 +31,4 @@ func TestPartTwo(t *testing.T) { t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2020/day02/main.go b/internal/2020/DayTwo/code.go similarity index 82% rename from 2020/day02/main.go rename to internal/2020/DayTwo/code.go index e43c720..030563d 100644 --- a/2020/day02/main.go +++ b/internal/2020/DayTwo/code.go @@ -1,18 +1,18 @@ -package main +package daytwo import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strconv" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2020D2", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) lines := strings.Split(string(content), "\n") var data []string for _, line := range lines { @@ -75,8 +75,3 @@ func PartTwo(data []string) int { return valid } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2020/day02/main_test.go b/internal/2020/DayTwo/code_test.go similarity index 67% rename from 2020/day02/main_test.go rename to internal/2020/DayTwo/code_test.go index 94d867e..016ea97 100644 --- a/2020/day02/main_test.go +++ b/internal/2020/DayTwo/code_test.go @@ -1,4 +1,4 @@ -package main +package daytwo import "testing" @@ -12,7 +12,7 @@ func TestPartOne(t *testing.T) { expected := 2 got := PartOne(testInput) if got != expected { - t.Errorf("PartOne(%v) = %d, want %d", testInput, got, expected) + t.Errorf("PartOne() = %d, want %d", got, expected) } } @@ -20,6 +20,7 @@ func TestPartTwo(t *testing.T) { expected := 1 got := PartTwo(testInput) if got != expected { - t.Errorf("PartTwo(%v) = %d, want %d", testInput, got, expected) + t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2021/day01/main.go b/internal/2021/DayOne/code.go similarity index 52% rename from 2021/day01/main.go rename to internal/2021/DayOne/code.go index 2562063..9d3b0d4 100644 --- a/2021/day01/main.go +++ b/internal/2021/DayOne/code.go @@ -1,24 +1,21 @@ -package main +package dayone import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strconv" "strings" ) -func parseInput(file string) []int { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2021D1", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []int { + content, _ := os.ReadFile(filepath) var data []int for line := range strings.SplitSeq(string(content), "\n") { - num, err := strconv.Atoi(line) - if err != nil { - log.Fatalf("Failed to convert string to int: %v", err) - } + num, _ := strconv.Atoi(line) data = append(data, num) } return data @@ -44,8 +41,3 @@ func PartTwo(data []int) int { return count } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2021/day01/main_test.go b/internal/2021/DayOne/code_test.go similarity index 96% rename from 2021/day01/main_test.go rename to internal/2021/DayOne/code_test.go index aa5a6a3..cdbf846 100644 --- a/2021/day01/main_test.go +++ b/internal/2021/DayOne/code_test.go @@ -1,4 +1,4 @@ -package main +package dayone import "testing" @@ -19,3 +19,4 @@ func TestPartTwo(t *testing.T) { t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2021/day03/main.go b/internal/2021/DayThree/code.go similarity index 87% rename from 2021/day03/main.go rename to internal/2021/DayThree/code.go index c8138d9..b588036 100644 --- a/2021/day03/main.go +++ b/internal/2021/DayThree/code.go @@ -1,17 +1,17 @@ -package main +package daythree import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2021D3", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) return strings.Split(strings.TrimSpace(string(content)), "\n") } @@ -115,8 +115,3 @@ func PartTwo(data []string) int { return oxygenRating * co2Rating } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2021/day03/main_test.go b/internal/2021/DayThree/code_test.go similarity index 96% rename from 2021/day03/main_test.go rename to internal/2021/DayThree/code_test.go index 3845aa3..95c9a37 100644 --- a/2021/day03/main_test.go +++ b/internal/2021/DayThree/code_test.go @@ -1,4 +1,4 @@ -package main +package daythree import "testing" @@ -32,3 +32,4 @@ func TestPartTwo(t *testing.T) { t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2021/day02/main.go b/internal/2021/DayTwo/code.go similarity index 73% rename from 2021/day02/main.go rename to internal/2021/DayTwo/code.go index 73a8d88..7f8c680 100644 --- a/2021/day02/main.go +++ b/internal/2021/DayTwo/code.go @@ -1,18 +1,18 @@ -package main +package daytwo import ( - "fmt" - "log" + "advent-of-code/internal/registry" "os" "strconv" "strings" ) -func parseInput(file string) []string { - content, err := os.ReadFile(file) - if err != nil { - log.Fatalf("Failed to read input file: %v", err) - } +func init() { + registry.Register("2021D2", ParseInput, PartOne, PartTwo) +} + +func ParseInput(filepath string) []string { + content, _ := os.ReadFile(filepath) return strings.Split(string(content), "\n") } @@ -58,8 +58,3 @@ func PartTwo(data []string) int { return horizontal * depth } -func main() { - data := parseInput("input.txt") - fmt.Println("Part 1:", PartOne(data)) - fmt.Println("Part 2:", PartTwo(data)) -} diff --git a/2021/day02/main_test.go b/internal/2021/DayTwo/code_test.go similarity index 96% rename from 2021/day02/main_test.go rename to internal/2021/DayTwo/code_test.go index 263db75..3ea3cca 100644 --- a/2021/day02/main_test.go +++ b/internal/2021/DayTwo/code_test.go @@ -1,4 +1,4 @@ -package main +package daytwo import "testing" @@ -26,3 +26,4 @@ func TestPartTwo(t *testing.T) { t.Errorf("PartTwo() = %d, want %d", got, expected) } } + diff --git a/2020/day05/input.txt b/internal/data/2020/DayFive/input.txt similarity index 100% rename from 2020/day05/input.txt rename to internal/data/2020/DayFive/input.txt diff --git a/2020/day04/input.txt b/internal/data/2020/DayFour/input.txt similarity index 100% rename from 2020/day04/input.txt rename to internal/data/2020/DayFour/input.txt diff --git a/2020/day01/input.txt b/internal/data/2020/DayOne/input.txt similarity index 100% rename from 2020/day01/input.txt rename to internal/data/2020/DayOne/input.txt diff --git a/2020/day06/input.txt b/internal/data/2020/DaySix/input.txt similarity index 100% rename from 2020/day06/input.txt rename to internal/data/2020/DaySix/input.txt diff --git a/2020/day03/input.txt b/internal/data/2020/DayThree/input.txt similarity index 100% rename from 2020/day03/input.txt rename to internal/data/2020/DayThree/input.txt diff --git a/2020/day02/input.txt b/internal/data/2020/DayTwo/input.txt similarity index 100% rename from 2020/day02/input.txt rename to internal/data/2020/DayTwo/input.txt diff --git a/2021/day01/input.txt b/internal/data/2021/DayOne/input.txt similarity index 100% rename from 2021/day01/input.txt rename to internal/data/2021/DayOne/input.txt diff --git a/2021/day03/input.txt b/internal/data/2021/DayThree/input.txt similarity index 100% rename from 2021/day03/input.txt rename to internal/data/2021/DayThree/input.txt diff --git a/2021/day02/input.txt b/internal/data/2021/DayTwo/input.txt similarity index 100% rename from 2021/day02/input.txt rename to internal/data/2021/DayTwo/input.txt diff --git a/internal/registry/registry.go b/internal/registry/registry.go new file mode 100644 index 0000000..7ce1b79 --- /dev/null +++ b/internal/registry/registry.go @@ -0,0 +1,42 @@ +package registry + +import ( + "fmt" + "os" +) + +type Runner interface { + Run(input string, part string) +} + +type DayRunner[T any] struct { + ParseInput func(string) T + PartOne func(T) int + PartTwo func(T) int +} + +func (r *DayRunner[T]) Run(input string, part string) { + data := r.ParseInput(input) + switch part { + case "": + fmt.Println(r.PartOne(data)) + fmt.Println(r.PartTwo(data)) + case "1": + fmt.Println(r.PartOne(data)) + case "2": + fmt.Println(r.PartTwo(data)) + default: + fmt.Fprintf(os.Stderr, "Invalid part: %s\n", part) + os.Exit(1) + } +} + +var Days = make(map[string]any) + +func Register[T any](key string, parseInput func(string) T, partOne func(T) int, partTwo func(T) int) { + Days[key] = &DayRunner[T]{ + ParseInput: parseInput, + PartOne: partOne, + PartTwo: partTwo, + } +}