adventofcode/2017/day19/main.go

202 lines
3.5 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"time"
termbox "github.com/nsf/termbox-go"
)
const (
N = iota
E
S
W
ERR
)
var network [][]byte
var message string
var ticks int
var nodes []byte
var width, height int
var printMap bool
func main() {
// Grab the window size
if len(os.Args) > 1 {
if os.Args[1] == "-print" {
fmt.Println("Not working right now... Sorry.")
os.Exit(1)
printMap = true
}
}
if err := termbox.Init(); err != nil {
panic(err)
}
go func() {
for {
event := termbox.PollEvent()
if event.Key == termbox.KeyCtrlC {
termbox.Close()
os.Exit(0)
}
}
}()
width, height = termbox.Size()
network = StdinTo2DBytes()
if printMap {
ClearScreen()
PrintMap(0, 0)
PrintStatus()
}
posX, posY, dir := FindEntry(), 0, S
for dir != ERR {
posX, posY, dir = Move(posX, posY, dir)
ticks++
switch network[posY][posX] {
case '|', '-', '+':
case ' ':
dir = ERR
break
default:
if len(nodes) == 0 || nodes[len(nodes)-1] != network[posY][posX] {
message = fmt.Sprint("Found node ", string(network[posY][posX]), "!")
nodes = append(nodes, network[posY][posX])
}
}
ClearScreen()
if printMap {
PrintMap(posX, posY)
time.Sleep(time.Second / 30)
}
PrintStatus()
}
fmt.Println("Ctrl+C to Quit")
}
func GetNodesAsString(nodes []byte) string {
ret := "[ "
for i := range nodes {
ret += string(nodes[i]) + " "
}
return ret + "]"
}
func Move(posX, posY, dir int) (int, int, int) {
chkX, chkY := posX, posY
switch dir {
case N:
chkY--
case E:
chkX++
case S:
chkY++
case W:
chkX--
}
if chkX < 0 || chkY < 0 || chkX > len(network[0]) || chkY > len(network) {
// Went off the map
return posX, posY, ERR
}
if network[chkY][chkX] == '+' {
// Which direction do we need to turn?
switch dir {
case N, S:
if CanMoveTo(chkX+1, chkY) {
dir = E
} else if CanMoveTo(chkX-1, chkY) {
dir = W
}
case E, W:
fmt.Println(len(network), chkY+1)
if CanMoveTo(chkX, chkY+1) {
dir = S
} else if CanMoveTo(chkX, chkY-1) {
dir = N
}
}
}
return chkX, chkY, dir
}
func CanMoveTo(chkX, chkY int) bool {
if chkY < 0 && chkX < 0 && chkY > len(network) && chkX > len(network[chkY]) {
return false
}
fmt.Println(chkX, chkY)
return network[chkY][chkX] != ' '
}
func FindEntry() int {
for i := range network[0] {
if network[0][i] == '|' {
return i
}
}
return -1
}
func ClearScreen() {
fmt.Print("\033[H\033[2J")
}
func PrintMap(posX, posY int) {
stX, stY := 0, 0
useHeight, useWidth := height-2, width
if posY > useHeight/2 {
stY = posY - (useHeight / 2)
}
if posX > width/2 {
stX = posX - (width / 2)
}
totHeight := useHeight/2 + posY
if totHeight < useHeight {
useHeight = useHeight + (useHeight - totHeight) + 4
}
totWidth := useWidth/2 + posX
if totWidth < useWidth {
useWidth = useWidth + (useWidth - totWidth) + 4
}
for y := stY; y < posY+(useHeight/2); y++ {
for x := stX; x < posX+(useWidth/2); x++ {
if len(network) > y {
if len(network[y]) > x {
if y == posY && x == posX {
fmt.Print("*")
} else {
fmt.Print(string(network[y][x]))
}
}
}
}
fmt.Println("")
}
}
func PrintStatus() {
fmt.Print(ticks, " Ticks ", GetNodesAsString(nodes), "\n")
fmt.Println(message)
}
func StdinTo2DBytes() [][]byte {
var ret [][]byte
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
bts := scanner.Bytes()
t := make([]byte, len(bts))
copy(t, bts)
ret = append(ret, t)
}
return ret
}