package main import ( "bufio" "fmt" "os" ) const ( CLEAR_SCREEN = "\033[H\033[2J" MAX_INT = int(^uint(0) >> 1) MIN_INT = -MAX_INT - 1 ) var input []byte var currRoom *Room var facility *Facility var pathStack []Room func main() { input = stdinToByteSlice() input = input[1 : len(input)-1] // Trim ^...$ part1() part2() } func part1() { facility = NewFacility() currRoom = &Room{0, 0, 0} for _, v := range input { switch v { case 'N': facility.move(0, -1) case 'E': facility.move(1, 0) case 'S': facility.move(0, 1) case 'W': facility.move(-1, 0) case '(': pathStack = append(pathStack, *currRoom) case ')': currRoom, pathStack = &pathStack[len(pathStack)-1], pathStack[:len(pathStack)-1] case '|': currRoom = &pathStack[len(pathStack)-1] } } var longest int for _, v := range facility.rooms { if v.dist > longest { longest = v.dist } } fmt.Println("= Part 1 =") fmt.Println(longest) } func part2() { var kilo int for _, v := range facility.rooms { if v.dist >= 1000 { kilo++ } } fmt.Println("= Part 2 =") fmt.Println(kilo) } type Facility struct { minX, maxX int minY, maxY int rooms map[string]*Room } func NewFacility() *Facility { f := Facility{ minX: MAX_INT, maxX: MIN_INT, minY: MAX_INT, maxY: MIN_INT, rooms: make(map[string]*Room), } return &f } func (f *Facility) key(x, y int) string { return fmt.Sprintf("%d,%d", x, y) } func (f *Facility) move(xd, yd int) { n := f.getRoom(currRoom.x+xd, currRoom.y+yd) n.dist = min(n.dist, currRoom.dist+1) currRoom = n f.setRoom(n) } func (f *Facility) getRoom(x, y int) *Room { if v, ok := f.rooms[f.key(x, y)]; ok { return v } return &Room{x, y, MAX_INT} } func (f *Facility) setRoom(r *Room) { f.minX = min(f.minX, r.x) f.maxX = max(f.maxX, r.x) f.minY = min(f.minY, r.y) f.maxY = max(f.maxY, r.y) f.rooms[r.key()] = r } func (f *Facility) string() string { var ret string for y := f.minY; y < f.maxY; y++ { for x := f.minX; x < f.maxX; x++ { if r, ok := f.rooms[f.key(x, y)]; !ok { ret += " " + r.key() + " " } } ret += "\n" } return ret } type Room struct { x, y int dist int } func (r *Room) key() string { return fmt.Sprintf("%d,%d", r.x, r.y) } func min(i, j int) int { if j < i { return j } return i } func max(i, j int) int { if j > i { return j } return i } func stdinToByteSlice() []byte { var ret []byte scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { data := scanner.Bytes() ret = append(input, data...) } return ret }