143 lines
2.2 KiB
Go
143 lines
2.2 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
"bufio"
|
||
|
"fmt"
|
||
|
"os"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
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
|
||
|
}
|
||
|
|
||
|
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
|
||
|
}
|