AOC2022/day14/day14.go
2022-12-15 01:02:04 +01:00

157 lines
3.4 KiB
Go

package main
import (
"AOC2022/helper"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
args := os.Args[1:]
lines := helper.ReadTextFile(args[0])
cave := generateCavePart(lines, 2)
run := 0
steps := 0
for run == 0 {
run = step(&cave)
steps++
}
//print(cave)
fmt.Println(steps - 1)
cave = generateCavePart(lines, 0)
run = 0
steps = 0
for run == 0 {
run = step(&cave)
steps++
}
fmt.Println(steps)
}
func step(cave *[][]rune) int {
sandDestination := getSandDestination(cave)
if sandDestination == [2]int{0, 500} {
helper.SetValueOf2DMap(sandDestination, 'o', cave)
return -1
}
return helper.SetValueOf2DMap(sandDestination, 'o', cave)
}
func getSandDestination(cave *[][]rune) (destination [2]int) {
startPoint := [2]int{0, 500}
if helper.RemoveError(helper.GetValueOf2DMap(startPoint, cave)) != '.' {
return startPoint
}
destination = [2]int{-1, -1}
for destination == [2]int{-1, -1} {
possibleNextPoint := startPoint
possibleNextPoint[0]++
getValue, err := helper.GetValueOf2DMap(possibleNextPoint, cave)
if err != nil {
return possibleNextPoint
}
if getValue != '.' {
diagonalMovePoint := diagonalMove(cave, possibleNextPoint)
if diagonalMovePoint == possibleNextPoint {
destination = startPoint
} else {
startPoint = diagonalMovePoint
}
} else {
startPoint = possibleNextPoint
}
}
return
}
func diagonalMove(cave *[][]rune, startPoint [2]int) [2]int {
potenTialPoints := [2][2]int{}
tempPoint := startPoint
tempPoint[1]--
potenTialPoints[0] = tempPoint
tempPoint[1] += 2
potenTialPoints[1] = tempPoint
for _, point := range potenTialPoints {
if helper.RemoveError(helper.GetValueOf2DMap(point, cave)) == '.' {
return point
}
}
return startPoint
}
func generateCavePart(lines []string, additionalSpace int) [][]rune {
lowestPoint := 0
cave := [200][]rune{}
for i := 0; i < len(cave); i++ {
cave[i] = []rune(strings.Repeat(".", 1000))
}
for _, line := range lines {
points := getPoints(line)
for _, point := range points {
if point[1] > lowestPoint {
lowestPoint = point[1]
}
}
drawLine(&cave, points)
}
lowestPoint += additionalSpace
if additionalSpace > 0 {
drawLine(&cave, [][2]int{{0, lowestPoint}, {999, lowestPoint}})
}
//print(cave[:lowestPoint+1])
return cave[:lowestPoint+1]
}
//x represents distance to the right and y represents distance down.
func drawLine(cave *[200][]rune, points [][2]int) {
for i := 0; i < len(points)-1; i++ {
point := points[i]
nextPoint := points[i+1]
if point[0] == nextPoint[0] {
direction := 1
if point[1]-nextPoint[1] > 0 {
direction = -1
}
for j := point[1] - direction; j != nextPoint[1]; {
j += direction
cave[j][point[0]] = '#'
}
} else {
direction := 1
if point[0]-nextPoint[0] > 0 {
direction = -1
}
for j := point[0] - direction; j != nextPoint[0]; {
j += direction
cave[point[1]][j] = '#'
}
}
}
}
func getPoints(line string) (points [][2]int) {
for _, pointsString := range strings.Split(line, " -> ") {
point := [2]int{}
for i, pointString := range strings.Split(pointsString, ",") {
point[i] = helper.RemoveError(strconv.Atoi(pointString))
}
point[0] = point[0]
points = append(points, point)
}
return
}
func print(cave [][]rune) {
fmt.Println()
fmt.Println(strings.Repeat(" ", 25) + "V" + strings.Repeat(" ", 24))
for _, line := range cave {
fmt.Println(string(line))
}
}