chore: initialized initial repo for 2025 aoc

This commit is contained in:
Ceferino Patino 2025-12-03 20:16:17 -06:00
commit 4ca16dabaa
Signed by: c4patino
SSH key fingerprint: SHA256:Wu+cU1t+7zVT9wzew/4meNmeulo66NzMqc22MdDBgXI
10 changed files with 480 additions and 3 deletions

3
.envrc
View file

@ -1,3 +0,0 @@
watch_file flake.nix flake.lock
use flake . --no-pure-eval

49
2025/cmd/generate/cmd.go Normal file
View file

@ -0,0 +1,49 @@
package generate
import (
"fmt"
"log"
"os"
"strconv"
"github.com/spf13/cobra"
)
func handleErr(err error, folder string) {
os.RemoveAll(folder)
log.Fatal(err)
}
var GenerateCmd = &cobra.Command{
Use: "generate",
Short: "Generate a new day directory",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
day, err := strconv.Atoi(args[0])
if err != nil {
log.Fatal(err)
}
folder := fmt.Sprintf("./day%02d", day)
if err := os.Mkdir(folder, 0755); err != nil {
log.Fatal(err)
}
if err := generateMainCode(day); err != nil {
handleErr(err, folder)
}
if err := generateTestCode(day); err != nil {
handleErr(err, folder)
}
if err := retrieveInput(day); err != nil {
handleErr(err, folder)
}
filename := fmt.Sprintf("./day%02d/test.txt", day)
if err := os.WriteFile(filename, []byte{}, 0755); err != nil {
handleErr(err, folder)
}
},
}

View file

@ -0,0 +1,92 @@
package generate
import (
"fmt"
"io"
"net/http"
"net/http/cookiejar"
"net/url"
"os"
)
const (
baseURL = "https://adventofcode.com/2025/day/%d/input"
host = "adventofcode.com"
userAgent = "github.com/C4theBomb/advent-of-code by c4patino@gmail.com"
cookieEnvName = "COOKIE"
)
func getCookie() (string, error) {
cookieValue := os.Getenv(cookieEnvName)
if cookieValue == "" {
return "", fmt.Errorf("%s environment variable not set", cookieEnvName)
}
return cookieValue, nil
}
func createHTTPClient(cookieValue string) (*http.Client, error) {
jar, err := cookiejar.New(nil)
if err != nil {
return nil, fmt.Errorf("failed to create cookie jar: %w", err)
}
domainURL := &url.URL{Scheme: "https", Host: host}
client := &http.Client{Jar: jar}
jar.SetCookies(domainURL, []*http.Cookie{{Name: "session", Value: cookieValue}})
return client, nil
}
func fetchInput(client *http.Client, day int) ([]byte, error) {
url := fmt.Sprintf(baseURL, day)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("User-Agent", userAgent)
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code %d: %s", resp.StatusCode, string(body))
}
return body, nil
}
func retrieveInput(day int) error {
cookieValue, err := getCookie()
if err != nil {
return err
}
client, err := createHTTPClient(cookieValue)
if err != nil {
return err
}
body, err := fetchInput(client, day)
if err != nil {
return err
}
filename := fmt.Sprintf("./day%02d/input.txt", day)
if err := os.WriteFile(filename, []byte(body), 0755); err != nil {
return err
}
return nil
}

View file

@ -0,0 +1,66 @@
package generate
import (
"fmt"
"os"
"os/exec"
)
const mainCodeTemplate = `package day%02d
import (
"bufio"
"fmt"
"os"
)
func Part1() int {
return -1
}
func Part2() int {
return -1
}
func Run(filename string) (any, any) {
file, err := os.Open(filename)
if err != nil {
panic(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fmt.Println(line)
}
if err := scanner.Err(); err != nil {
panic(err)
}
part1 := Part1()
part2 := Part2()
return part1, part2
}
`
func generateMainCode(day int) error {
testCode := fmt.Sprintf(mainCodeTemplate, day)
filename := fmt.Sprintf("./day%02d/day%02d.go", day, day)
if err := os.WriteFile(filename, []byte(testCode), 0755); err != nil {
return err
}
cmd := exec.Command("go", "fmt", filename)
if err := cmd.Run(); err != nil {
return err
}
return nil
}

View file

@ -0,0 +1,60 @@
package generate
import (
"fmt"
"os"
"os/exec"
)
const testCodeTemplate = `package day%02d
import (
"os"
"testing"
)
type TestCase struct {
FileName string
Part1 any
Part2 any
}
func TestDay%02d(t *testing.T) {
tests := []TestCase{
{"test.txt", -1, -1},
// {"input.txt", -1, -1},
}
for _, test := range tests {
if _, err := os.Stat(test.FileName); os.IsNotExist(err) {
t.Fatalf("test file does not exist: %%v", test.FileName)
}
part1, part2 := Run(test.FileName)
if test.Part1 != nil && part1 != test.Part1 {
t.Fatalf("%%s: unexpected part1:\nwant:\t%%v\ngot:\t%%v", test.FileName, test.Part1, part1)
}
if test.Part2 != nil && part2 != test.Part2 {
t.Fatalf("%%s: unexpected part2:\nwant:\t%%v\ngot:\t%%v", test.FileName, test.Part2, part2)
}
}
}
`
func generateTestCode(day int) error {
testCode := fmt.Sprintf(testCodeTemplate, day, day)
filename := fmt.Sprintf("./day%02d/day%02d_test.go", day, day)
if err := os.WriteFile(filename, []byte(testCode), 0755); err != nil {
return err
}
cmd := exec.Command("go", "fmt", filename)
if err := cmd.Run(); err != nil {
return err
}
return nil
}

61
2025/cmd/root.go Normal file
View file

@ -0,0 +1,61 @@
package cmd
import (
"fmt"
"log"
"os"
"strconv"
"cpatino.com/advent-of-code/2025/cmd/generate"
"github.com/spf13/cobra"
)
var days = map[int]func(string) (any, any){}
var rootCmd = &cobra.Command{
Use: "advent-of-code",
Short: "Advent of Code 2024",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
day, err := strconv.Atoi(args[0])
if err != nil {
log.Fatal(err)
}
file, _ := cmd.Flags().GetString("file")
if file == "" {
file = fmt.Sprintf("./day%02d/input.txt", day)
}
if _, err := os.Stat(file); os.IsNotExist(err) {
log.Fatalf("file does not exist: %s", file)
}
log.Printf("Day: %d, Input File: %s\n", day, file)
part1, part2 := days[day](file)
log.Printf("Part 1: %v\n", part1)
log.Printf("Part 2: %v\n", part2)
},
}
func init() {
rootCmd.AddCommand(generate.GenerateCmd)
rootCmd.Flags().String("file", "", "Path to a file")
}
func Execute() error {
if len(os.Args) == 1 {
return rootCmd.Execute()
}
subCmd := os.Args[1]
for _, cmd := range rootCmd.Commands() {
if cmd.Use == subCmd {
return cmd.Execute()
}
}
return rootCmd.Execute()
}

118
2025/cmd/update/main.go Normal file
View file

@ -0,0 +1,118 @@
package main
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
)
func main() {
const mainTemplate = `package cmd
import (
"fmt"
"log"
"os"
"strconv"
"github.com/spf13/cobra"
"cpatino.com/advent-of-code/2025/cmd/generate"
%s
)
var days = map[int]func(string) (any, any){
%s
}
var rootCmd = &cobra.Command{
Use: "advent-of-code",
Short: "Advent of Code 2024",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
day, err := strconv.Atoi(args[0])
if err != nil {
log.Fatal(err)
}
file, _ := cmd.Flags().GetString("file")
if file == "" {
file = fmt.Sprintf("./day%%02d/input.txt", day)
}
if _, err := os.Stat(file); os.IsNotExist(err) {
log.Fatalf("file does not exist: %%s", file)
}
log.Printf("Day: %%d, Input File: %%s\n", day, file)
part1, part2 := days[day](file)
log.Printf("Part 1: %%v\n", part1)
log.Printf("Part 2: %%v\n", part2)
},
}
func init() {
rootCmd.AddCommand(generate.GenerateCmd)
rootCmd.Flags().String("file", "", "Path to a file")
}
func Execute() error {
if len(os.Args) == 1 {
return rootCmd.Execute()
}
subCmd := os.Args[1]
for _, cmd := range rootCmd.Commands() {
if cmd.Use == subCmd {
return cmd.Execute()
}
}
return rootCmd.Execute()
}
`
var imports, mappings strings.Builder
err := filepath.Walk("./", func(path string, info os.FileInfo, err error) error {
if !info.IsDir() || !strings.HasPrefix(info.Name(), "day") {
return nil
}
dayStr := strings.TrimPrefix(info.Name(), "day")
day, err := strconv.Atoi(dayStr)
if err != nil {
log.Fatal(err)
}
imports.WriteString(fmt.Sprintf("\t\"cpatino.com/advent-of-code/2025/day%02d\"\n", day))
mappings.WriteString(fmt.Sprintf("\t%d: day%02d.Run,\n", day, day))
return nil
})
importsStr := strings.TrimSpace(imports.String())
mappingsStr := strings.TrimSpace(mappings.String())
if err != nil {
fmt.Println("Error walking the path:", err)
os.Exit(1)
}
mainCode := fmt.Sprintf(mainTemplate, importsStr, mappingsStr)
os.WriteFile("./cmd/root.go", []byte(mainCode), 0644)
cmd := exec.Command("go", "fmt", "./cmd/root.go")
if err := cmd.Run(); err != nil {
fmt.Println("Error running go fmt:", err)
os.Exit(1)
}
}

10
2025/go.mod Normal file
View file

@ -0,0 +1,10 @@
module cpatino.com/advent-of-code/2025
go 1.23.3
require github.com/spf13/cobra v1.8.1
require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)

10
2025/go.sum Normal file
View file

@ -0,0 +1,10 @@
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

14
2025/main.go Normal file
View file

@ -0,0 +1,14 @@
//go:generate go run ./cmd/update
package main
import (
"log"
"cpatino.com/advent-of-code/2025/cmd"
)
func main() {
log.SetFlags(0)
cmd.Execute()
}