package main import ( "bufio" "errors" "fmt" "io" "log" "os" ) func main() { r := bufio.NewReader(os.Stdin) sitMap := make([]byte, 0, 128) width := 0 height := 0 var guard *Cursor // Read map for { b, err := r.ReadByte() if errors.Is(err, io.EOF) { break } if err != nil { log.Fatalf("While reading input: %v", err) } if b == '\n' { if width == 0 { width = len(sitMap) } continue } switch b { case Left, Right, Up, Down: tmp := NewCursor(width, len(sitMap), b) guard = &tmp // Replace ^ with . so we don't run into our past // self. b = '.' } sitMap = append(sitMap, b) } height = len(sitMap) / width // Walk map positions := make(map[Coord]struct{}) for 0 <= guard.Pos.X && guard.Pos.X <= width && 0 <= guard.Pos.Y && guard.Pos.Y <= height { positions[guard.Pos] = struct{}{} idx := IndexOf(guard.Front(), width) if idx < 0 || len(sitMap) < idx { break } e := sitMap[idx] switch e { case '#': guard.Turn() case '.': guard.Forward() default: log.Fatalf("Unexpected map element %#v at line %d, column %d", string(e), guard.Pos.X+1, guard.Pos.Y+1) } } fmt.Println(len(positions)) } type Orientation = byte const ( Left Orientation = '<' Up Orientation = '^' Down Orientation = 'v' Right Orientation = '>' ) type Coord struct{ X, Y int } func IndexOf(c Coord, width int) int { return c.X + c.Y*width } func OrientationOf(dir Coord) Orientation { var o Orientation switch dir { case Coord{-1, 0}: o = Left case Coord{1, 0}: o = Right case Coord{0, -1}: o = Up case Coord{0, 1}: o = Down default: panic(fmt.Sprintf("Unknown direction %#v", dir)) } return o } func NewCursor(width, idx int, o Orientation) Cursor { x := idx % width y := idx / width d := Coord{} switch o { case Left: d.X = -1 case Right: d.X = 1 case Up: d.Y = -1 case Down: d.Y = 1 } return Cursor{Pos: Coord{x, y}, Dir: d} } type Cursor struct { Pos, Dir Coord } func (c *Cursor) Forward() { c.Pos = c.Front() } func (c *Cursor) Turn() { tmp := c.Dir.X c.Dir.X = -1 * c.Dir.Y c.Dir.Y = tmp } func (c *Cursor) Front() Coord { return Coord{c.Pos.X + c.Dir.X, c.Pos.Y + c.Dir.Y} }