package main import ( "os"; "fmt"; "strings" ) // ---------------------------------------- type Direction uint8 const ( Up Direction = iota Down Direction = iota Left Direction = iota Right Direction = iota ) func NewDirections(str string) []Direction { direct := make([]Direction, 0, len(str)) for _, char := range []byte(str) { switch { case char == '<': direct = append(direct, Left) case char == '>': direct = append(direct, Right) case char == '^': direct = append(direct, Up) case char == 'v': direct = append(direct, Down) default: } } return direct } // ---------------------------------------- type Field struct { robot [2]int field [][]byte } func NewField(str string) *Field { field := make([][]byte, 0) var robot [2]int for y, line := range strings.Split(str, "\n") { for x, char := range []byte(line) { if char == '@' { robot = [...]int{x, y} } } field = append(field, []byte(line)) } return &Field{robot: robot, field: field} } func (f *Field) StepUp() { switch { // blocked case f.field[f.robot[1] - 1][f.robot[0]] == '#': return // free to move case f.field[f.robot[1] - 1][f.robot[0]] == '.': f.field[f.robot[1] - 1][f.robot[0]] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[1]-- return // infront of box default: loop := true for i := 2 ; loop; i++ { switch { case f.field[f.robot[1] - i][f.robot[0]] == '#': return case f.field[f.robot[1] - i][f.robot[0]] == 'O': continue case f.field[f.robot[1] - i][f.robot[0]] == '.': // shift boxes f.field[f.robot[1] - i][f.robot[0]] = 'O' loop = false } } // continue shifting boxes f.field[f.robot[1] - 1][f.robot[0]] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[1]-- return } } func (f *Field) StepDown() { switch { // blocked case f.field[f.robot[1] + 1][f.robot[0]] == '#': return // free to move case f.field[f.robot[1] + 1][f.robot[0]] == '.': f.field[f.robot[1] + 1][f.robot[0]] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[1]++ return // infront of box default: loop := true for i := 2 ; loop; i++ { switch { case f.field[f.robot[1] + i][f.robot[0]] == '#': return case f.field[f.robot[1] + i][f.robot[0]] == 'O': continue case f.field[f.robot[1] + i][f.robot[0]] == '.': // shift boxes f.field[f.robot[1] + i][f.robot[0]] = 'O' loop = false } } // continue shifting boxes f.field[f.robot[1] + 1][f.robot[0]] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[1]++ return } } func (f *Field) StepRight() { switch { // blocked case f.field[f.robot[1]][f.robot[0] + 1] == '#': return // free to move case f.field[f.robot[1]][f.robot[0] + 1] == '.': f.field[f.robot[1]][f.robot[0] + 1] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[0]++ return // infront of box default: loop := true for i := 2 ; loop; i++ { switch { case f.field[f.robot[1]][f.robot[0] + i] == '#': return case f.field[f.robot[1]][f.robot[0] + i] == 'O': continue case f.field[f.robot[1]][f.robot[0] + i] == '.': // shift boxes f.field[f.robot[1]][f.robot[0] + i] = 'O' loop = false } } // continue shifting boxes f.field[f.robot[1]][f.robot[0] + 1] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[0]++ return } } func (f *Field) StepLeft() { switch { // blocked case f.field[f.robot[1]][f.robot[0] - 1] == '#': return // free to move case f.field[f.robot[1]][f.robot[0] - 1] == '.': f.field[f.robot[1]][f.robot[0] - 1] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[0]-- return // infront of box default: loop := true for i := 2 ; loop; i++ { switch { case f.field[f.robot[1]][f.robot[0] - i] == '#': return case f.field[f.robot[1]][f.robot[0] - i] == 'O': continue case f.field[f.robot[1]][f.robot[0] - i] == '.': // shift boxes f.field[f.robot[1]][f.robot[0] - i] = 'O' loop = false } } // continue shifting boxes f.field[f.robot[1]][f.robot[0] - 1] = '@' f.field[f.robot[1]][f.robot[0]] = '.' f.robot[0]-- return } } func (f *Field) Print() { for _, line := range f.field { fmt.Println(string(line)) } } func (f *Field) Gps() int { acc := 0 for y, line := range f.field { for x, char := range line { if char == 'O' { acc += 100 * y + x } } } return acc } // ---------------------------------------- func check(err error) { if err != nil { panic(err) } } func main() { dat, err := os.ReadFile("data.txt") check(err) input := strings.TrimSpace(string(dat)) field := NewField(strings.Split(input, "\n\n")[0]) directions := NewDirections(strings.Split(input, "\n\n")[1]) //field.Print() for _, d := range directions { switch { case d == Up: field.StepUp() case d == Down: field.StepDown() case d == Right: field.StepRight() case d == Left: field.StepLeft() } //field.Print() } fmt.Println(field.Gps()) }