145 lines
3.4 KiB
Go
145 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"AOC2022/helper"
|
|
"fmt"
|
|
)
|
|
|
|
type ActivePath struct {
|
|
activePosition [2]int
|
|
visitedPositions [][2]int
|
|
steps int
|
|
}
|
|
|
|
type FieldPoint struct {
|
|
cost int
|
|
height int
|
|
}
|
|
|
|
func main() {
|
|
//args := os.Args[1:]
|
|
lines := helper.ReadTextFile("day12/input")
|
|
start, end := getStartingPointAndEndpoint(lines)
|
|
fmt.Println(start)
|
|
fmt.Println(end)
|
|
field := getField(lines)
|
|
activePaths := []ActivePath{{start, [][2]int{}, 0}}
|
|
fastestRoute := 999999999
|
|
for len(activePaths) > 0 {
|
|
newPaths := []ActivePath{}
|
|
for _, path := range activePaths {
|
|
if path.activePosition == [2]int{2, 6} {
|
|
//fmt.Println("here")
|
|
}
|
|
newPathStep := path.step(field)
|
|
if path.activePosition == end && fastestRoute > path.steps {
|
|
fastestRoute = path.steps
|
|
path.print(field)
|
|
} else if path.steps < fastestRoute {
|
|
newPaths = append(newPaths, newPathStep...)
|
|
}
|
|
}
|
|
activePaths = newPaths
|
|
}
|
|
fmt.Println(fastestRoute)
|
|
}
|
|
|
|
func getField(lines []string) [][]FieldPoint {
|
|
field := make([][]FieldPoint, len(lines))
|
|
for i := 0; i < len(lines); i++ {
|
|
line := lines[i]
|
|
fieldLine := make([]FieldPoint, len(line))
|
|
for j := 0; j < len(line); j++ {
|
|
height := int(line[j])
|
|
if line[j] == 'S' {
|
|
height = int('a')
|
|
}
|
|
if line[j] == 'E' {
|
|
height = int('z')
|
|
}
|
|
fieldLine[j] = FieldPoint{0, height}
|
|
}
|
|
}
|
|
return field
|
|
}
|
|
|
|
func (path *ActivePath) step(field []string) (newPaths []ActivePath) {
|
|
if getHeight(path.activePosition, field) == 'E' {
|
|
return
|
|
}
|
|
nextSteps := path.getNextStep(field)
|
|
for _, step := range nextSteps {
|
|
newPath := ActivePath{step, append(path.visitedPositions, path.activePosition), path.steps + 1}
|
|
newPaths = append(newPaths, newPath)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (path *ActivePath) checkVisitable(direction [2]int, field []string) (visitable bool) {
|
|
toVisit := path.activePosition
|
|
toVisit[0] += direction[0]
|
|
toVisit[1] += direction[1]
|
|
if toVisit[0] > -1 && toVisit[1] > -1 &&
|
|
toVisit[0] < len(field) && toVisit[1] < len((field)[0]) {
|
|
if helper.Contains2Int(path.visitedPositions, toVisit) {
|
|
return false
|
|
}
|
|
heightToVisit := getHeight(toVisit, field)
|
|
heightCurrentPos := getHeight(path.activePosition, field) + 1
|
|
if heightToVisit > heightCurrentPos {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (path ActivePath) getNextStep(field []string) (nextSteps [][2]int) {
|
|
directions := [][2]int{{0, -1}, {0, +1}, {-1, 0}, {+1, 0}}
|
|
for _, direction := range directions {
|
|
if path.checkVisitable(direction, field) {
|
|
newStep := [2]int{path.activePosition[0] + direction[0], path.activePosition[1] + direction[1]}
|
|
nextSteps = append(nextSteps, newStep)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func getHeight(location [2]int, field []string) int {
|
|
if field[location[0]][location[1]] == 'S' {
|
|
return 'a'
|
|
}
|
|
if field[location[0]][location[1]] == 'E' {
|
|
return 'z'
|
|
}
|
|
return int(field[location[0]][location[1]])
|
|
}
|
|
|
|
func getStartingPointAndEndpoint(field []string) (start, end [2]int) {
|
|
for i := 0; i < len(field); i++ {
|
|
for j := 0; j < len(field[i]); j++ {
|
|
if field[i][j] == 'S' {
|
|
start = [2]int{i, j}
|
|
}
|
|
if field[i][j] == 'E' {
|
|
end = [2]int{i, j}
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (path ActivePath) print(field []string) {
|
|
for i := 0; i < len(field); i++ {
|
|
tempArr := ""
|
|
for j := 0; j < len(field[i]); j++ {
|
|
if helper.Contains2Int(path.visitedPositions, [2]int{i, j}) {
|
|
tempArr += "#"
|
|
} else {
|
|
tempArr += "."
|
|
}
|
|
}
|
|
fmt.Println(tempArr)
|
|
}
|
|
}
|