363 lines
9.1 KiB
Go
363 lines
9.1 KiB
Go
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
|
|
}
|
|
}
|