Files
adventofcode/2024/gareth/day10/day10.go
2025-01-13 23:48:55 +00:00

142 lines
3.0 KiB
Go

package day10
import (
"strings"
)
var directions = [][2]int{
{-1, 0},
{1, 0},
{0, -1},
{0, 1},
}
func Part1(input string) int {
grid := ParseInput(input)
return CalculateTotalTrailheadScore(grid)
}
func Part2(input string) int {
grid := ParseInput(input)
return CalculateTotalTrailheadRating(grid)
}
func ParseInput(input string) [][]int {
lines := strings.Split(strings.TrimSpace(input), "\n")
grid := make([][]int, len(lines))
for i, line := range lines {
grid[i] = make([]int, len(line))
for j, char := range line {
grid[i][j] = int(char - '0')
}
}
return grid
}
func IsValidPosition(x, y, rows, cols int) bool {
return x >= 0 && x < rows && y >= 0 && y < cols
}
func DFS(grid [][]int, x, y, prevHeight int, visited [][]bool, reached9 map[[2]int]bool) {
rows := len(grid)
cols := len(grid[0])
if !IsValidPosition(x, y, rows, cols) || visited[x][y] || grid[x][y] != prevHeight+1 {
return
}
if grid[x][y] == 9 {
reached9[[2]int{x, y}] = true
return
}
visited[x][y] = true
for _, dir := range directions {
nx, ny := x+dir[0], y+dir[1]
DFS(grid, nx, ny, grid[x][y], visited, reached9)
}
visited[x][y] = false
}
func CalculateTrailheadScore(grid [][]int, x, y int) int {
rows := len(grid)
cols := len(grid[0])
visited := make([][]bool, rows)
for i := range visited {
visited[i] = make([]bool, cols)
}
reached9 := make(map[[2]int]bool)
DFS(grid, x, y, -1, visited, reached9)
return len(reached9)
}
func DFSForRatings(grid [][]int, x, y, prevHeight int, visited [][]bool, trailCache map[[3]int]int) int {
rows := len(grid)
cols := len(grid[0])
if !IsValidPosition(x, y, rows, cols) || visited[x][y] || grid[x][y] != prevHeight+1 {
return 0
}
if grid[x][y] == 9 {
return 1
}
cacheKey := [3]int{x, y, grid[x][y]}
if count, exists := trailCache[cacheKey]; exists {
return count
}
visited[x][y] = true
totalTrails := 0
for _, dir := range directions {
nx, ny := x+dir[0], y+dir[1]
totalTrails += DFSForRatings(grid, nx, ny, grid[x][y], visited, trailCache)
}
visited[x][y] = false
trailCache[cacheKey] = totalTrails
return totalTrails
}
func CalculateTrailheadRating(grid [][]int, x, y int) int {
rows := len(grid)
cols := len(grid[0])
visited := make([][]bool, rows)
for i := range visited {
visited[i] = make([]bool, cols)
}
trailCache := make(map[[3]int]int)
return DFSForRatings(grid, x, y, -1, visited, trailCache)
}
func CalculateTotalTrailheadScore(grid [][]int) int {
rows := len(grid)
cols := len(grid[0])
totalScore := 0
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
if grid[i][j] == 0 {
score := CalculateTrailheadScore(grid, i, j)
totalScore += score
}
}
}
return totalScore
}
func CalculateTotalTrailheadRating(grid [][]int) int {
rows := len(grid)
cols := len(grid[0])
totalRating := 0
for i := 0; i < rows; i++ {
for j := 0; j < cols; j++ {
if grid[i][j] == 0 {
rating := CalculateTrailheadRating(grid, i, j)
totalRating += rating
}
}
}
return totalRating
}