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 }