aoc2024/day-12/internal/two/solve.go

134 lines
2.9 KiB
Go
Raw Normal View History

2024-12-13 10:02:48 +00:00
package two
import (
"bytes"
log "github.com/sirupsen/logrus"
)
func Solve(buf []byte) (int, error) {
r := bytes.NewReader(buf)
graph, err := parseLines(r)
if err != nil {
return 0, err
}
var totalCost int
totalAreaVisited := make(map[point]struct{})
for i := 0; i < len(graph.data); i++ {
for j := 0; j < len(graph.data[i]); j++ {
start := newPoint(j, i)
if graph.isOutOfBounds(start) {
continue
}
_, ok := totalAreaVisited[start]
if ok {
continue
}
totalAreaVisited[start] = struct{}{}
path := exploreAreaSequentially(start, graph)
numSides := analyzeSides(graph.valueAt(firstPointFromMap(path.visited)), graph, path)
totalCost += len(path.visited) * numSides
for point := range path.visited {
totalAreaVisited[point] = struct{}{}
}
}
}
return totalCost, nil
}
func analyzeSides(kind rune, graph *graph, path path) int {
log.Debugf("graph for values %s\n%s\n", string(kind), graph.debug(path.visited))
var corners int
for current := range path.visited {
ns := neighbours(current)
if isCorner(graph, current, ns[N], ns[E]) {
corners++
}
if isCorner(graph, current, ns[S], ns[E]) {
corners++
}
if isCorner(graph, current, ns[N], ns[W]) {
corners++
}
if isCorner(graph, current, ns[S], ns[W]) {
corners++
}
2024-12-13 11:18:52 +00:00
corners += numInnerCorner(graph, current, ns)
2024-12-13 10:02:48 +00:00
}
log.Debugf("this path has %d corners", corners)
return corners
}
func isCorner(graph *graph, current, p, q point) bool {
if graph.isOutOfBounds(p) && graph.isOutOfBounds(q) {
return true
}
if !graph.isOutOfBounds(p) {
if graph.isOutOfBounds(q) && !graph.sameKind(p, current) {
return true
}
}
if !graph.isOutOfBounds(q) {
if graph.isOutOfBounds(p) && !graph.sameKind(q, current) {
return true
}
}
if !graph.isOutOfBounds(p) && !graph.isOutOfBounds(q) {
if !graph.sameKind(p, current) && !graph.sameKind(q, current) {
return true
}
}
return false
}
2024-12-13 11:18:52 +00:00
func numInnerCorner(graph *graph, current point, ns [4]point) int {
2024-12-13 10:02:48 +00:00
var corners int
if !graph.isOutOfBounds(ns[N]) && !graph.isOutOfBounds(ns[E]) {
if graph.sameKind(ns[N], current) && graph.sameKind(ns[E], current) &&
!graph.sameKind(point{current.x + 1, current.y - 1}, current) {
corners++
}
}
if !graph.isOutOfBounds(ns[N]) && !graph.isOutOfBounds(ns[W]) {
if graph.sameKind(ns[N], current) && graph.sameKind(ns[W], current) &&
!graph.sameKind(point{current.x - 1, current.y - 1}, current) {
corners++
}
}
if !graph.isOutOfBounds(ns[S]) && !graph.isOutOfBounds(ns[E]) {
if graph.sameKind(ns[S], current) && graph.sameKind(ns[E], current) &&
!graph.sameKind(point{current.x + 1, current.y + 1}, current) {
corners++
}
}
if !graph.isOutOfBounds(ns[S]) && !graph.isOutOfBounds(ns[W]) {
if graph.sameKind(ns[S], current) && graph.sameKind(ns[W], current) &&
!graph.sameKind(point{current.x - 1, current.y + 1}, current) {
corners++
}
}
return corners
}