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)) } }