123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- 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}
- }
|