157 lines
3.4 KiB
Go
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))
|
|
}
|
|
}
|