add day-10 + benchmarks

This commit is contained in:
2024-12-10 21:45:16 +00:00
parent 0236679639
commit 503082d822
22 changed files with 559 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
goos: linux
goarch: amd64
pkg: github.com/onyx-and-iris/aoc2024/day-10/internal/one
cpu: Intel(R) Core(TM) i7-8700K CPU @ 3.70GHz
BenchmarkSolve-12 1000000000 0.001398 ns/op
ok github.com/onyx-and-iris/aoc2024/day-10/internal/one 0.014s

View File

@@ -0,0 +1,9 @@
package one
const (
N = iota
E
S
W
None
)

View File

@@ -0,0 +1,40 @@
package one
import (
"slices"
"strings"
)
type point struct {
x int
y int
}
type graph struct {
data []string
startPositions []point
}
func newGrid() *graph {
return &graph{data: make([]string, 0), startPositions: make([]point, 0)}
}
func (g *graph) String() string {
return strings.Join(g.data, "\n")
}
func (g *graph) isOutOfBounds(p point) bool {
return p.x < 0 || p.y < 0 || p.y >= len(g.data) || p.x >= len(g.data[p.y])
}
func (g *graph) valueAt(p point) rune {
return rune(g.data[p.y][p.x])
}
func (g *graph) debug(path []point) string {
temp := slices.Clone(g.data)
for _, pos := range path {
temp[pos.y] = replaceAtIndex(temp[pos.y], '+', pos.x)
}
return strings.Join(temp, "\n")
}

View File

@@ -0,0 +1,10 @@
package one
func neighbours(p point) [4]point {
return [4]point{
{p.x, p.y - 1},
{p.x + 1, p.y},
{p.x, p.y + 1},
{p.x - 1, p.y},
}
}

View File

@@ -0,0 +1,68 @@
package one
import (
"bytes"
log "github.com/sirupsen/logrus"
"github.com/onyx-and-iris/aoc2024/day-10/internal/queue"
)
const target = '9'
func Solve(buf []byte) (int, error) {
r := bytes.NewReader(buf)
graph, err := parseLines(r)
if err != nil {
return 0, err
}
var totalScore int
queue := queue.New[point]()
for _, pos := range graph.startPositions {
if graph.isOutOfBounds(pos) {
continue
}
queue.Enqueue(pos)
var score int
visited := make(map[point]struct{})
endpoints := make(map[point]struct{})
for !queue.IsEmpty() {
current := queue.Dequeue()
_, ok := endpoints[current]
if ok {
continue
}
endpoints[current] = struct{}{}
if graph.valueAt(current) == target {
score++
continue
}
_, ok = visited[current]
if ok {
continue
}
visited[current] = struct{}{}
for _, n := range neighbours(current) {
if graph.isOutOfBounds(n) {
continue
}
if graph.valueAt(n)-graph.valueAt(current) == 1 {
log.Tracef("pushing %v with value %s back onto the queue\n", n, string(graph.valueAt(n)))
queue.Enqueue(n)
}
}
}
log.Debugf("score for trailhead %v - %d\n", pos, score)
totalScore += score
}
return totalScore, nil
}

View File

@@ -0,0 +1,15 @@
package one
import (
_ "embed"
"os"
"testing"
)
//go:embed testdata/input.txt
var data []byte
func BenchmarkSolve(b *testing.B) {
os.Stdout, _ = os.Open(os.DevNull)
Solve(data)
}

View File

@@ -0,0 +1,45 @@
package one
import (
"bufio"
"io"
"regexp"
log "github.com/sirupsen/logrus"
)
var reStartPos = regexp.MustCompile(`0`)
func parseLines(r io.Reader) (*graph, error) {
graph := newGrid()
var linecount int
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := scanner.Text()
graph.data = append(graph.data, line)
for _, m := range reStartPos.FindAllStringIndex(line, -1) {
graph.startPositions = append(
graph.startPositions,
point{x: m[0], y: linecount},
)
}
linecount++
}
log.Debug(graph.startPositions)
if err := scanner.Err(); err != nil {
return nil, err
}
return graph, nil
}
func replaceAtIndex(s string, r rune, i int) string {
out := []rune(s)
out[i] = r
return string(out)
}