2022-12-22 16:51:39 +01:00
package main
import (
"AOC2022/helper"
"fmt"
"strconv"
"strings"
)
func main ( ) {
//args := os.Args[1:]
lines := helper . ReadTextFile ( "day22/input" )
2022-12-22 23:43:15 +01:00
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 ) {
2022-12-22 16:51:39 +01:00
field := [ ] [ ] rune { }
for _ , line := range lines {
if line == "" {
break
}
field = append ( field , [ ] rune ( line ) )
}
2022-12-22 23:43:15 +01:00
fields := [ ] [ ] [ ] rune { field }
currentPosition := [ 4 ] int { 0 , 0 , 0 , 0 }
2022-12-22 16:51:39 +01:00
for i , c := range field [ 0 ] {
if c == '.' {
currentPosition [ 1 ] = i
break
}
}
for _ , command := range commands {
2022-12-22 23:43:15 +01:00
currentPosition = runCommand ( fields , command , currentPosition , false )
2022-12-22 16:51:39 +01:00
}
fmt . Println ( 1000 * ( currentPosition [ 0 ] + 1 ) + 4 * ( currentPosition [ 1 ] + 1 ) + currentPosition [ 2 ] )
}
2022-12-22 23:43:15 +01:00
func runCommand ( field [ ] [ ] [ ] rune , command string , currentPosition [ 4 ] int , part2 bool ) [ 4 ] int {
2022-12-22 16:51:39 +01:00
rotation := command [ len ( command ) - 1 ]
if rotation < 57 {
rotation = 0
} else {
command = command [ : len ( command ) - 1 ]
}
distance := helper . RemoveError ( strconv . Atoi ( command ) )
2022-12-22 23:43:15 +01:00
currentPosition = move ( field , currentPosition , distance , part2 )
currentPosition = rotate ( rotation , currentPosition )
return currentPosition
}
func rotate ( rotation uint8 , currentPosition [ 4 ] int ) [ 4 ] int {
2022-12-22 16:51:39 +01:00
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
}
2022-12-22 23:43:15 +01:00
func getDirection ( currentPosition [ 4 ] int ) [ 2 ] int {
2022-12-22 16:51:39 +01:00
directions := [ ] [ 2 ] int { { 0 , 1 } , { 1 , 0 } , { 0 , - 1 } , { - 1 , 0 } }
return directions [ currentPosition [ 2 ] ]
}
2022-12-22 23:43:15 +01:00
func move ( fields [ ] [ ] [ ] rune , currentPosition [ 4 ] int , distance int , part2 bool ) [ 4 ] int {
field := fields [ 0 ]
2022-12-22 16:51:39 +01:00
direction := getDirection ( currentPosition )
for i := 0 ; i < distance ; i ++ {
2022-12-22 23:43:15 +01:00
if part2 {
field = fields [ currentPosition [ 3 ] ]
direction = getDirection ( currentPosition )
}
2022-12-22 16:51:39 +01:00
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 {
2022-12-22 23:43:15 +01:00
if ! part2 {
currentPosition = loop ( field , currentPosition )
} else {
currentPosition = loopPart2 ( fields , currentPosition )
}
2022-12-22 16:51:39 +01:00
}
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
}
2022-12-22 23:43:15 +01:00
func loop ( field [ ] [ ] rune , currentPosition [ 4 ] int ) [ 4 ] int {
2022-12-22 16:51:39 +01:00
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
}
2022-12-22 23:43:15 +01:00
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
}
}