AOC2022/day12/day12.go

145 lines
3.4 KiB
Go
Raw Normal View History

2022-12-12 21:54:34 +01:00
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)
}
}