Files
advent-of-code-2022/day12/common/heightmap.go
2022-12-15 14:56:28 +01:00

143 lines
4.3 KiB
Go

package common
import (
"bufio"
"math"
)
type Tile struct {
height int
steps int
}
func NewTile(height int) *Tile {
return &Tile{height, math.MaxInt32}
}
func (tile Tile) GetSteps() int {
return tile.steps
}
type Map struct {
tiles [][]Tile
start *Tile
end *Tile
}
func (heightmap Map) GetEndTile() Tile {
return *heightmap.end
}
func (heightmap Map) GetStartTile() Tile {
return *heightmap.start
}
func (heightmap Map) FindBestStart() Tile {
min := math.MaxInt32
var bestStart Tile
for i := 0; i < len(heightmap.tiles); i++ {
for j := 0; j < len(heightmap.tiles[i]); j++ {
if heightmap.tiles[i][j].height == 1 && heightmap.tiles[i][j].steps < min {
bestStart = heightmap.tiles[i][j]
min = bestStart.steps
}
}
}
return bestStart
}
func (heightmap *Map) ComputeStepsFromStart() {
heightmap.start.steps = 0
for i := 0; i < len(heightmap.tiles); i++ {
for j := 0; j < len(heightmap.tiles[i]); j++ {
if &heightmap.tiles[i][j] == heightmap.start {
heightmap.ComputeSteps(i, j, 1)
}
}
}
}
func (heightmap *Map) ComputeStepsFromEnd() {
heightmap.end.steps = 0
for i := 0; i < len(heightmap.tiles); i++ {
for j := 0; j < len(heightmap.tiles[i]); j++ {
if &heightmap.tiles[i][j] == heightmap.end {
heightmap.ComputeStepsInReverse(i, j, 1)
}
}
}
}
func (heightmap *Map) ComputeSteps(row int, column int, steps int) {
if row > 0 && heightmap.tiles[row-1][column].steps > steps &&
heightmap.tiles[row-1][column].height <= heightmap.tiles[row][column].height + 1 {
heightmap.tiles[row-1][column].steps = steps
heightmap.ComputeSteps(row-1, column, steps+1)
}
if row < len(heightmap.tiles)-1 && heightmap.tiles[row+1][column].steps > steps &&
heightmap.tiles[row+1][column].height <= heightmap.tiles[row][column].height + 1 {
heightmap.tiles[row+1][column].steps = steps
heightmap.ComputeSteps(row+1, column, steps+1)
}
if column > 0 && heightmap.tiles[row][column-1].steps > steps &&
heightmap.tiles[row][column-1].height <= heightmap.tiles[row][column].height + 1 {
heightmap.tiles[row][column-1].steps = steps
heightmap.ComputeSteps(row, column-1, steps+1)
}
if column < len(heightmap.tiles[0])-1 && heightmap.tiles[row][column+1].steps > steps &&
heightmap.tiles[row][column+1].height <= heightmap.tiles[row][column].height + 1 {
heightmap.tiles[row][column+1].steps = steps
heightmap.ComputeSteps(row, column+1, steps+1)
}
}
func (heightmap *Map) ComputeStepsInReverse(row int, column int, steps int) {
if row > 0 && heightmap.tiles[row-1][column].steps > steps &&
heightmap.tiles[row-1][column].height + 1 >= heightmap.tiles[row][column].height {
heightmap.tiles[row-1][column].steps = steps
heightmap.ComputeStepsInReverse(row-1, column, steps+1)
}
if row < len(heightmap.tiles)-1 && heightmap.tiles[row+1][column].steps > steps &&
heightmap.tiles[row+1][column].height + 1 >= heightmap.tiles[row][column].height {
heightmap.tiles[row+1][column].steps = steps
heightmap.ComputeStepsInReverse(row+1, column, steps+1)
}
if column > 0 && heightmap.tiles[row][column-1].steps > steps &&
heightmap.tiles[row][column-1].height + 1 >= heightmap.tiles[row][column].height {
heightmap.tiles[row][column-1].steps = steps
heightmap.ComputeStepsInReverse(row, column-1, steps+1)
}
if column < len(heightmap.tiles[0])-1 && heightmap.tiles[row][column+1].steps > steps &&
heightmap.tiles[row][column+1].height + 1 >= heightmap.tiles[row][column].height {
heightmap.tiles[row][column+1].steps = steps
heightmap.ComputeStepsInReverse(row, column+1, steps+1)
}
}
func Parse(scanner bufio.Scanner) Map {
heightmap := Map{}
for scanner.Scan() {
line := scanner.Text()
heightmapRow := make([]Tile, len(line))
for i := 0; i < len(line); i++ {
if line[i] == 'S' {
heightmapRow[i] = *NewTile(1)
heightmap.start = &heightmapRow[i]
} else if line[i] == 'E' {
heightmapRow[i] = *NewTile(26)
heightmap.end = &heightmapRow[i]
} else {
heightmapRow[i] = *NewTile(int(line[i] - 'a' + 1))
}
}
heightmap.tiles = append(heightmap.tiles, heightmapRow)
}
return heightmap
}