From 25b6db75c86f63c2054096d835def808739c0771 Mon Sep 17 00:00:00 2001 From: onyx-and-iris Date: Sun, 1 Dec 2024 17:50:02 +0000 Subject: [PATCH] first commit --- .gitignore | 29 +++++++++++++++++ day-01/go.mod | 3 ++ day-01/internal/one/solve.go | 50 ++++++++++++++++++++++++++++ day-01/internal/two/solve.go | 63 ++++++++++++++++++++++++++++++++++++ day-01/internal/util/util.go | 20 ++++++++++++ day-01/main.go | 27 ++++++++++++++++ day-01/makefile | 25 ++++++++++++++ scaffold.sh | 55 +++++++++++++++++++++++++++++++ 8 files changed, 272 insertions(+) create mode 100644 .gitignore create mode 100644 day-01/go.mod create mode 100644 day-01/internal/one/solve.go create mode 100644 day-01/internal/two/solve.go create mode 100644 day-01/internal/util/util.go create mode 100644 day-01/main.go create mode 100644 day-01/makefile create mode 100755 scaffold.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a967731 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work +go.work.sum + +# env file +.env + +# input files +partial.txt +input.txt diff --git a/day-01/go.mod b/day-01/go.mod new file mode 100644 index 0000000..f1efe37 --- /dev/null +++ b/day-01/go.mod @@ -0,0 +1,3 @@ +module github.com/onyx-and-iris/aoc2024/day-01 + +go 1.23.3 diff --git a/day-01/internal/one/solve.go b/day-01/internal/one/solve.go new file mode 100644 index 0000000..caaa0a6 --- /dev/null +++ b/day-01/internal/one/solve.go @@ -0,0 +1,50 @@ +package one + +import ( + "bufio" + "bytes" + "embed" + "io" + "math" + "regexp" + + "github.com/onyx-and-iris/aoc2024/day-01/internal/util" +) + +//go:embed testdata +var files embed.FS + +var reNums = regexp.MustCompile(`[0-9]+`) + +func Solve() (int, error) { + data, _ := files.ReadFile("testdata/input.txt") + + r := bytes.NewReader(data) + left, right, err := parseLines(r) + if err != nil { + return 0, err + } + + var sum int + for i, n := range left { + sum += int(math.Abs(float64(n - right[i]))) + } + return sum, nil +} + +func parseLines(r io.Reader) ([]int, []int, error) { + var left, right []int + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + nums := reNums.FindAllString(scanner.Text(), -1) + left = util.InsertSorted(left, util.MustConv(nums[0])) + right = util.InsertSorted(right, util.MustConv(nums[1])) + } + + if err := scanner.Err(); err != nil { + return nil, nil, err + } + + return left, right, nil +} diff --git a/day-01/internal/two/solve.go b/day-01/internal/two/solve.go new file mode 100644 index 0000000..2d16959 --- /dev/null +++ b/day-01/internal/two/solve.go @@ -0,0 +1,63 @@ +package two + +import ( + "bufio" + "bytes" + "embed" + "io" + "regexp" + "slices" + + "github.com/onyx-and-iris/aoc2024/day-01/internal/util" +) + +//go:embed testdata +var files embed.FS + +var reNums = regexp.MustCompile(`[0-9]+`) + +func Solve() (int, error) { + data, _ := files.ReadFile("testdata/input.txt") + + r := bytes.NewReader(data) + left, right, err := parseLines(r) + if err != nil { + return 0, err + } + + var similarity int + for k, v := range left { + indx := slices.Index(right, k) + if indx == -1 { + continue + } + + var occurrences int + for _, n := range right[indx:] { + if n == k { + occurrences++ + } + } + similarity += k * v * occurrences + } + + return similarity, nil +} + +func parseLines(r io.Reader) (map[int]int, []int, error) { + var left map[int]int = make(map[int]int) + var right []int + + scanner := bufio.NewScanner(r) + for scanner.Scan() { + nums := reNums.FindAllString(scanner.Text(), -1) + left[util.MustConv(nums[0])] = left[util.MustConv(nums[0])] + 1 + right = util.InsertSorted(right, util.MustConv(nums[1])) + } + + if err := scanner.Err(); err != nil { + return nil, nil, err + } + + return left, right, nil +} diff --git a/day-01/internal/util/util.go b/day-01/internal/util/util.go new file mode 100644 index 0000000..88876bf --- /dev/null +++ b/day-01/internal/util/util.go @@ -0,0 +1,20 @@ +package util + +import ( + "cmp" + "slices" + "strconv" +) + +func MustConv(s string) int { + n, err := strconv.Atoi(s) + if err != nil { + panic(err) + } + return n +} + +func InsertSorted[T cmp.Ordered](ts []T, t T) []T { + i, _ := slices.BinarySearch(ts, t) + return slices.Insert(ts, i, t) +} diff --git a/day-01/main.go b/day-01/main.go new file mode 100644 index 0000000..691e863 --- /dev/null +++ b/day-01/main.go @@ -0,0 +1,27 @@ +/******************************************************************************** + Advent of Code 2024 - day-01 +********************************************************************************/ + +package main + +import ( + "fmt" + "log" + + "github.com/onyx-and-iris/aoc2024/day-01/internal/one" + "github.com/onyx-and-iris/aoc2024/day-01/internal/two" +) + +func main() { + val, err := one.Solve() + if err != nil { + log.Fatal(err) + } + fmt.Printf("solution one: %d\n", val) + + val, err = two.Solve() + if err != nil { + log.Fatal(err) + } + fmt.Printf("solution two: %d\n", val) +} diff --git a/day-01/makefile b/day-01/makefile new file mode 100644 index 0000000..30f75ca --- /dev/null +++ b/day-01/makefile @@ -0,0 +1,25 @@ +program = day-01 + +GO = go +SRC_DIR := src +BIN_DIR := bin + +EXE := $(BIN_DIR)/$(program) + +.DEFAULT_GOAL := build + +.PHONY: fmt vet build clean +fmt: + $(GO) fmt ./... + +vet: fmt + $(GO) vet ./... + +build: vet | $(BIN_DIR) + $(GO) build -o $(EXE) . + +$(BIN_DIR): + @mkdir -p $@ + +clean: + @rm -rv $(BIN_DIR) diff --git a/scaffold.sh b/scaffold.sh new file mode 100755 index 0000000..a4436be --- /dev/null +++ b/scaffold.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +name=day-"$1" + +if [ -d day-"$name" ]; then + echo "program $name already exists" + exit 1 +fi + +mkdir -p "$name"/testdata +touch "$name"/makefile + +cat <> "$name"/makefile +program = $name + +GO = go +SRC_DIR := src +BIN_DIR := bin + +EXE := \$(BIN_DIR)/\$(program) + +.DEFAULT_GOAL := build + +.PHONY: fmt vet build clean +fmt: + \$(GO) fmt ./... + +vet: fmt + \$(GO) vet ./... + +build: vet | \$(BIN_DIR) + \$(GO) build -o \$(EXE) ./\$(SRC_DIR) + +\$(BIN_DIR): + @mkdir -p \$@ + +clean: + @rm -rv \$(BIN_DIR) +EOT + +cat <> "$name"/solution.go +/******************************************************************************** + Advent of Code 2024 - $name +********************************************************************************/ + +package main + +func main() { + +} +EOT + +cd "$name" || exit + +go mod init github.com/onyx-and-iris/aoc2024/"$name" \ No newline at end of file