AoC2021/src/day9/day9.go
2021-12-09 20:34:12 +01:00

129 lines
2.9 KiB
Go

package main
import (
"AOC2021/src/helper"
"fmt"
"os"
)
//0 -> Unknown
//1 -> true
//2 -> false
type field struct {
height int
lowPoint int
basin [2]int
}
func main() {
args := os.Args[1:]
input, err := helper.GetInput(args[0])
if err != nil {
fmt.Println(err)
}
heightMap := [100][100]field{}
for i, line := range input {
for j, r := range line {
heightMap[i][j] = field{int(r - '0'), 0, [2]int{-1,-1}}
}
}
sum := 0
amountOfBasinSet := 0
//find Lowpoints
for i, _ := range heightMap {
for j, _ := range heightMap[i] {
checkFieldLowpoint(&heightMap, j, i)
if heightMap[i][j].lowPoint == 1 {
sum += heightMap[i][j].height + 1
amountOfBasinSet++
}
}
}
fmt.Println(sum)
//find Basin
for amountOfBasinSet < len(heightMap) * len(heightMap[0]) {
for i, _ := range heightMap {
for j, _ := range heightMap[i] {
if heightMap[i][j].height == 9 && checkBasin(heightMap[i][j]) != 2 {
heightMap[i][j].basin = [2]int{-2, -2}
amountOfBasinSet++
}
checkFieldBasin(&heightMap, j, i, &amountOfBasinSet)
}
}
}
basinMap := make(map[string]int)
for i, _ := range heightMap {
for j, _ := range heightMap[i] {
if checkBasin(heightMap[i][j]) == 1 {
fieldBasin := heightMap[i][j].basin
basinString := fmt.Sprintf("X%d Y%d", fieldBasin[0], fieldBasin[1])
basinMap[basinString] += 1
}
}
}
rankedMap := helper.RankByValueAmount(basinMap)
fmt.Println(rankedMap[0].Value * rankedMap[1].Value * rankedMap[2].Value)
}
func checkFieldBasin(heightMap *[100][100]field, x int, y int, amountOfBasinSet *int) {
if checkBasin(heightMap[y][x]) != 0 {
return
}
directions := [4][2]int{{0, -1}, {+1, 0}, {0, 1}, {-1, 0}}
for _, direction := range directions {
px := x + direction[0]
py := y + direction[1]
if py < len(heightMap) && py >= 0 && px < len(heightMap[0]) && px >= 0 {
if checkBasin(heightMap[py][px]) == 1{
heightMap[y][x].basin = heightMap[py][px].basin
*amountOfBasinSet++
return
}
}
}
}
//0 no Basin Set
//1 Basin Set
//2 no Basin Exists
func checkBasin(inputField field) int {
fieldBasinX := inputField.basin[0]
fieldBasinY := inputField.basin[1]
if fieldBasinY == -1 || fieldBasinX == -1 {
return 0
}
if fieldBasinY == -2 || fieldBasinX == -2 {
return 2
}
return 1
}
func checkFieldLowpoint(heightMap *[100][100]field, x int, y int) {
if heightMap[y][x].lowPoint == 2 {
return
}
directions := [4][2]int{{0, -1}, {+1, 0}, {0, 1}, {-1, 0}}
fieldHeight := heightMap[y][x].height
for _, direction := range directions {
px := x + direction[0]
py := y + direction[1]
if py < len(heightMap) && py >= 0 && px < len(heightMap[0]) && px >= 0 {
if heightMap[py][px].height >= fieldHeight {
heightMap[py][px].lowPoint = 2
}
if heightMap[py][px].height <= fieldHeight {
heightMap[y][x].lowPoint = 2
return
}
}
}
heightMap[y][x].lowPoint = 1
heightMap[y][x].basin = [2]int{x,y}
return
}