mirror of
https://github.com/onyx-and-iris/aoc2024.git
synced 2025-01-09 14:20:48 +00:00
97 lines
1.9 KiB
Go
97 lines
1.9 KiB
Go
package two
|
|
|
|
import (
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/onyx-and-iris/aoc2024/day-18/internal/point"
|
|
"github.com/onyx-and-iris/aoc2024/day-18/internal/queue"
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type graph struct {
|
|
start point.Point
|
|
end point.Point
|
|
data []string
|
|
}
|
|
|
|
func newGraph(width, height, numCorruptions int, corruptedCoords [][]int) *graph {
|
|
var data []string
|
|
var sb strings.Builder
|
|
for range height {
|
|
for range width {
|
|
sb.WriteRune('.')
|
|
}
|
|
data = append(data, sb.String())
|
|
sb.Reset()
|
|
}
|
|
|
|
for _, coords := range corruptedCoords[:numCorruptions] {
|
|
data[coords[1]] = replaceAtIndex(data[coords[1]], '#', coords[0])
|
|
}
|
|
|
|
return &graph{point.Point{X: 0, Y: 0}, point.Point{X: len(data[0]) - 1, Y: len(data) - 1}, data}
|
|
}
|
|
|
|
func (g *graph) String() string {
|
|
return strings.Join(g.data, "\n")
|
|
}
|
|
|
|
func (g *graph) isOutOfBounds(p point.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.Point) rune {
|
|
return rune(g.data[p.Y][p.X])
|
|
}
|
|
|
|
func (g *graph) addCorruption(p point.Point) {
|
|
g.data[p.Y] = replaceAtIndex(g.data[p.Y], '#', p.X)
|
|
}
|
|
|
|
func (g *graph) bfs() bool {
|
|
queue := queue.New[point.Point]()
|
|
queue.Enqueue(g.start)
|
|
visited := make(map[point.Point]struct{})
|
|
|
|
for !queue.IsEmpty() {
|
|
current := queue.Dequeue()
|
|
|
|
if current == g.end {
|
|
return true
|
|
}
|
|
|
|
_, ok := visited[current]
|
|
if ok {
|
|
continue
|
|
}
|
|
visited[current] = struct{}{}
|
|
|
|
for _, n := range neighbours(current) {
|
|
if g.isOutOfBounds(n) {
|
|
continue
|
|
}
|
|
|
|
if g.valueAt(n) == '#' {
|
|
continue
|
|
}
|
|
|
|
queue.Enqueue(n)
|
|
}
|
|
}
|
|
log.Debugf("\n%s\n", g.debug(visited))
|
|
|
|
return false
|
|
}
|
|
|
|
func (g *graph) debug(visited map[point.Point]struct{}) string {
|
|
temp := slices.Clone(g.data)
|
|
for p := range visited {
|
|
if g.valueAt(p) == '#' {
|
|
continue
|
|
}
|
|
temp[p.Y] = replaceAtIndex(temp[p.Y], 'O', p.X)
|
|
}
|
|
return strings.Join(temp, "\n")
|
|
}
|