refactor: massive refactor to have only one binary to call
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
module 2020/day01
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2020/day02
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2020/day03
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2020/day04
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2020/day05
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2020/day06
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2021/day01
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2021/day02
|
||||
|
||||
go 1.25.4
|
||||
@@ -1,3 +0,0 @@
|
||||
module 2021/day03
|
||||
|
||||
go 1.25.4
|
||||
13
Makefile
Normal file
13
Makefile
Normal file
@@ -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)
|
||||
70
README.md
70
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: <answer>
|
||||
Part 2: <answer>
|
||||
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
|
||||
|
||||
56
cmd/aoc/main.go
Normal file
56
cmd/aoc/main.go
Normal file
@@ -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 <YEAR>D<DAY>[P<PART>]\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)
|
||||
}
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
42
internal/registry/registry.go
Normal file
42
internal/registry/registry.go
Normal file
@@ -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,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user