package main import ( "AOC2022/helper" "fmt" "strconv" "strings" ) func main() { //args := os.Args[1:] lines := helper.ReadTextFile("day22/input") commandsLine := lines[len(lines)-1] commandsLine = strings.ReplaceAll(commandsLine, "R", "R,") commandsLine = strings.ReplaceAll(commandsLine, "L", "L,") commands := strings.Split(commandsLine, ",") fmt.Println(commands) part1(lines, commands) part2(lines, commands) } func part2(lines []string, commands []string) { fields := [][][]rune{} fields, cutFields := part2Parser(lines, fields, 50) currentPosition := [4]int{0, 0, 0, 0} for i, c := range cutFields[0][0] { if c == '.' { currentPosition[1] = i break } } fmt.Println(currentPosition) for i, command := range commands { fmt.Println(command) currentPosition = runCommand(cutFields, command, currentPosition, true) fmt.Printf("%v: %v \n", i+1, currentPosition) } fmt.Println(currentPosition) fmt.Println(1000*(currentPosition[0]+101) + 4*(currentPosition[1]+51) + currentPosition[2]) } func part2Parser(lines []string, fields [][][]rune, sidelength int) ([][][]rune, [][][]rune) { for i := 0; i < 4*sidelength; i += sidelength { field := [][]rune{} for j := i; j < i+sidelength; j++ { line := lines[j] if line == "" { break } fieldLine := strings.ReplaceAll(line, " ", "") field = append(field, []rune(fieldLine)) } fields = append(fields, field) } cutFields := [][][]rune{} for i := 0; i < len(fields); i++ { field := fields[i] if len(field[0]) < 2*sidelength { cutFields = append(cutFields, field) } else { tmpFields := [2][][]rune{} for _, fieldLine := range field { tmpFields[0] = append(tmpFields[0], fieldLine[:sidelength]) tmpFields[1] = append(tmpFields[1], fieldLine[sidelength:]) } cutFields = append(cutFields, tmpFields[:]...) } } fmt.Println(len(cutFields)) return fields, cutFields } func part1(lines []string, commands []string) { field := [][]rune{} for _, line := range lines { if line == "" { break } field = append(field, []rune(line)) } fields := [][][]rune{field} currentPosition := [4]int{0, 0, 0, 0} for i, c := range field[0] { if c == '.' { currentPosition[1] = i break } } for _, command := range commands { currentPosition = runCommand(fields, command, currentPosition, false) } fmt.Println(1000*(currentPosition[0]+1) + 4*(currentPosition[1]+1) + currentPosition[2]) } func runCommand(field [][][]rune, command string, currentPosition [4]int, part2 bool) [4]int { rotation := command[len(command)-1] if rotation < 57 { rotation = 0 } else { command = command[:len(command)-1] } distance := helper.RemoveError(strconv.Atoi(command)) currentPosition = move(field, currentPosition, distance, part2) currentPosition = rotate(rotation, currentPosition) return currentPosition } func rotate(rotation uint8, currentPosition [4]int) [4]int { if rotation == 'R' { newDirection := currentPosition[2] + 1 if newDirection > 3 { newDirection = 0 } currentPosition[2] = newDirection } if rotation == 'L' { newDirection := currentPosition[2] - 1 if newDirection < 0 { newDirection = 3 } currentPosition[2] = newDirection } return currentPosition } func getDirection(currentPosition [4]int) [2]int { directions := [][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}} return directions[currentPosition[2]] } func move(fields [][][]rune, currentPosition [4]int, distance int, part2 bool) [4]int { field := fields[0] direction := getDirection(currentPosition) for i := 0; i < distance; i++ { if part2 { field = fields[currentPosition[3]] direction = getDirection(currentPosition) } tmpPosition := [2]int{currentPosition[0], currentPosition[1]} tmpPosition[0] += direction[0] tmpPosition[1] += direction[1] check := checkPosition(field, tmpPosition) if check == 2 { break } if check == 1 { if !part2 { currentPosition = loop(field, currentPosition) } else { currentPosition = loopPart2(fields, currentPosition) } } if check == 0 { currentPosition[0] = tmpPosition[0] currentPosition[1] = tmpPosition[1] } } return currentPosition } //2 - Collision //1 - Out Of Bounds //0 - Fine func checkPosition(field [][]rune, position [2]int) int { if position[0] >= len(field) || position[0] < 0 { return 1 } if position[1] >= len(field[position[0]]) || position[1] < 0 { return 1 } switch field[position[0]][position[1]] { case ' ': return 1 case '.': return 0 case '#': return 2 } return -1 } func loop(field [][]rune, currentPosition [4]int) [4]int { direction := getDirection(currentPosition) newStartPosition := [2]int{0, 0} if direction[0] == 0 { newStartPosition[0] = currentPosition[0] } if direction[0] < 0 { newStartPosition[0] = len(field) - 1 } if direction[1] == 0 { newStartPosition[1] = currentPosition[1] } if direction[1] < 0 { newStartPosition[1] = len(field[newStartPosition[0]]) - 1 } for checkPosition(field, newStartPosition) == 1 { newStartPosition[0] += direction[0] newStartPosition[1] += direction[1] } if checkPosition(field, newStartPosition) == 0 { currentPosition[0] = newStartPosition[0] currentPosition[1] = newStartPosition[1] } return currentPosition } func loopPart2(fields [][][]rune, currentPosition [4]int) [4]int { tmpPosition := getNewStartPos(currentPosition, len(fields[0][0])) field := fields[tmpPosition[3]] if checkPosition(field, [2]int{tmpPosition[0], tmpPosition[1]}) == 0 { return tmpPosition } return currentPosition } func getNewStartPos(currentPosition [4]int, sidelength int) [4]int { highestPos := sidelength - 1 if currentPosition[3] == 0 { switch currentPosition[2] { case 0: currentPosition[3] = 1 currentPosition[1] = 0 case 1: currentPosition[3] = 2 currentPosition[0] = 0 case 2: currentPosition[3] = 3 currentPosition[1] = 0 currentPosition[0] = invertPosition(currentPosition[0], highestPos) currentPosition[2] = invertDirection(currentPosition[2]) case 3: currentPosition[3] = 5 currentPosition[0] = currentPosition[1] currentPosition[1] = 0 currentPosition = rotate('R', currentPosition) } return currentPosition } if currentPosition[3] == 1 { switch currentPosition[2] { case 0: currentPosition[3] = 4 currentPosition[0] = invertPosition(currentPosition[0], highestPos) currentPosition[1] = highestPos currentPosition[2] = invertDirection(currentPosition[2]) case 1: currentPosition[3] = 2 currentPosition[0] = currentPosition[1] currentPosition[1] = highestPos currentPosition = rotate('L', currentPosition) case 2: currentPosition[3] = 0 currentPosition[1] = highestPos case 3: currentPosition[3] = 5 currentPosition[0] = highestPos } return currentPosition } if currentPosition[3] == 2 { switch currentPosition[2] { case 0: currentPosition[3] = 1 currentPosition[1] = currentPosition[0] currentPosition[0] = highestPos currentPosition = rotate('L', currentPosition) case 1: currentPosition[3] = 4 currentPosition[0] = 0 case 2: currentPosition[3] = 3 currentPosition[1] = currentPosition[0] currentPosition[0] = 0 currentPosition = rotate('L', currentPosition) case 3: currentPosition[3] = 0 currentPosition[0] = highestPos } return currentPosition } if currentPosition[3] == 3 { switch currentPosition[2] { case 0: currentPosition[3] = 4 currentPosition[1] = 0 case 1: currentPosition[3] = 5 currentPosition[0] = 0 case 2: currentPosition[3] = 0 currentPosition[0] = invertPosition(currentPosition[0], highestPos) currentPosition[1] = 0 currentPosition[2] = invertDirection(currentPosition[2]) case 3: currentPosition[3] = 2 currentPosition[0] = currentPosition[1] currentPosition[1] = 0 currentPosition = rotate('R', currentPosition) } return currentPosition } if currentPosition[3] == 4 { switch currentPosition[2] { //Potential Error case 0: currentPosition[3] = 1 currentPosition[0] = invertPosition(currentPosition[0], highestPos) currentPosition[1] = highestPos currentPosition[2] = invertDirection(currentPosition[2]) case 1: currentPosition[3] = 5 currentPosition[0] = currentPosition[1] currentPosition[1] = highestPos currentPosition = rotate('R', currentPosition) case 2: currentPosition[3] = 3 currentPosition[1] = highestPos case 3: currentPosition[3] = 2 currentPosition[0] = highestPos } return currentPosition } if currentPosition[3] == 5 { switch currentPosition[2] { case 0: currentPosition[3] = 4 currentPosition[1] = currentPosition[0] currentPosition[0] = highestPos currentPosition = rotate('L', currentPosition) case 1: currentPosition[3] = 1 currentPosition[0] = 0 case 2: currentPosition[3] = 0 currentPosition[1] = currentPosition[0] currentPosition[0] = 0 currentPosition = rotate('L', currentPosition) case 3: currentPosition[3] = 3 currentPosition[0] = highestPos } return currentPosition } return currentPosition } func invertPosition(input int, highestPos int) int { return highestPos - input } func invertDirection(input int) int { if input > 1 { return input - 2 } else { return input + 2 } }