package main import ( "os" "fmt" "strings" ) // type definitions type Direction int const ( Up Direction = iota + 1 Down Left Right ) type state struct { field [][]rune guard_x int guard_y int direction Direction } func new_state(text string) *state { lines := strings.Split(text, "\n") field := make([][]rune, len(lines)) guard := [2]int{-1,-1} for y := range lines { field[y] = []rune(lines[y]) for x, r := range field[y] { if r == '^' { guard = [2]int{x, y} field[y][x] = '.' } } } s := state{field: field, guard_x: guard[0], guard_y: guard[1], direction: Up} return &s } // general util func check(e error) { if e != nil { panic(e) } } func add_non_duplicate(slice [][2]int, elem [2]int) [][2]int { for _, e := range slice { if e == elem { return slice } } return append(slice, elem) } // simulation functions func iter(s *state) *state { new_guard_x := s.guard_x new_guard_y := s.guard_y // try to move switch { case s.direction == Up: new_guard_y-- case s.direction == Down: new_guard_y++ case s.direction == Left: new_guard_x-- case s.direction == Right: new_guard_x++ } // if guard is outside of the field if new_guard_x < 0 || new_guard_y < 0 || new_guard_x >= len(s.field[0]) || new_guard_y >= len(s.field) { new_guard_x = -1 new_guard_y = -1 } else if s.field[new_guard_y][new_guard_x] == '#' { // correct if path is blocked switch { case s.direction == Up: new_guard_y++ s.direction = Right new_guard_x++ case s.direction == Down: new_guard_y-- s.direction = Left new_guard_x-- case s.direction == Left: new_guard_x++ s.direction = Up new_guard_y-- case s.direction == Right: new_guard_x-- s.direction = Down new_guard_y++ } } // set new guard coordinates s.guard_x = new_guard_x s.guard_y = new_guard_y return s } // main loop func main() { // read in file dat, err := os.ReadFile("data.txt") check(err) dat_str := string(dat[:len(dat) - 1]) stateobj := new_state(dat_str) distinct_pos := make([][2]int, 0) for stateobj.guard_x >= 0 { distinct_pos = add_non_duplicate(distinct_pos, [2]int{stateobj.guard_x, stateobj.guard_y}) stateobj = iter(stateobj) } fmt.Println(len(distinct_pos)) }