mirror of
https://github.com/onyx-and-iris/aoc2024.git
synced 2026-04-07 09:33:37 +00:00
add day-10 + benchmarks
This commit is contained in:
6
day-10/internal/one/benchmark
Normal file
6
day-10/internal/one/benchmark
Normal 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
|
||||
9
day-10/internal/one/direction.go
Normal file
9
day-10/internal/one/direction.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package one
|
||||
|
||||
const (
|
||||
N = iota
|
||||
E
|
||||
S
|
||||
W
|
||||
None
|
||||
)
|
||||
40
day-10/internal/one/graph.go
Normal file
40
day-10/internal/one/graph.go
Normal 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")
|
||||
}
|
||||
10
day-10/internal/one/neighbours.go
Normal file
10
day-10/internal/one/neighbours.go
Normal 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},
|
||||
}
|
||||
}
|
||||
68
day-10/internal/one/solve.go
Normal file
68
day-10/internal/one/solve.go
Normal 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
|
||||
}
|
||||
15
day-10/internal/one/solve_internal_test.go
Normal file
15
day-10/internal/one/solve_internal_test.go
Normal 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)
|
||||
}
|
||||
45
day-10/internal/one/util.go
Normal file
45
day-10/internal/one/util.go
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user