214 lines
3.0 KiB
Go
214 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
N = iota
|
|
E
|
|
S
|
|
W
|
|
)
|
|
|
|
const (
|
|
ST_CLEAN = iota
|
|
ST_WEAK
|
|
ST_INFECTED
|
|
ST_FLAGGED
|
|
ST_ERROR
|
|
)
|
|
|
|
var nodes map[string]int
|
|
var cX, cY, cD int
|
|
var minX, minY, maxX, maxY int
|
|
var tickCount, infectCount int
|
|
|
|
func main() {
|
|
inp := StdinToStrings()
|
|
nodes = make(map[string]int)
|
|
cX, cY, cD = len(inp)/2, len(inp[0])/2, N
|
|
for y := 0; y < len(inp); y++ {
|
|
for x := 0; x < len(inp[y]); x++ {
|
|
nodes[cs(x, y)] = ST_CLEAN
|
|
if inp[y][x] == '#' {
|
|
nodes[cs(x, y)] = ST_INFECTED
|
|
}
|
|
updateMinMax(x, y)
|
|
}
|
|
}
|
|
|
|
for i := 0; i < 10000000; i++ {
|
|
//ClearScreen()
|
|
if part1 {
|
|
p1Tick()
|
|
} else {
|
|
p2Tick()
|
|
}
|
|
//PrettyPrint()
|
|
//PrintStatus()
|
|
//time.Sleep(time.Second / 5)
|
|
}
|
|
}
|
|
|
|
func p1Tick() {
|
|
tickCount++
|
|
switch nodes[cs(cX, cY)] {
|
|
case ST_INFECTED:
|
|
TurnRight()
|
|
nodes[cs(cX, cY)] = ST_CLEAN
|
|
infectCount++
|
|
default:
|
|
TurnLeft()
|
|
nodes[cs(cX, cY)] = ST_INFECTED
|
|
infectCount++
|
|
}
|
|
cX, cY = getXYInDir()
|
|
updateMinMax(cX, cY)
|
|
}
|
|
|
|
func p2Tick() {
|
|
tickCount++
|
|
switch nodes[cs(cX, cY)] {
|
|
case ST_CLEAN:
|
|
TurnLeft()
|
|
nodes[cs(cX, cY)] = ST_WEAK
|
|
case ST_WEAK:
|
|
nodes[cs(cX, cY)] = ST_INFECTED
|
|
infectCount++
|
|
case ST_INFECTED:
|
|
TurnRight()
|
|
nodes[cs(cX, cY)] = ST_FLAGGED
|
|
case ST_FLAGGED:
|
|
TurnRight()
|
|
TurnRight()
|
|
nodes[cs(cX, cY)] = ST_CLEAN
|
|
}
|
|
cX, cY = getXYInDir()
|
|
updateMinMax(cX, cY)
|
|
}
|
|
|
|
func updateMinMax(x, y int) {
|
|
if x < minX {
|
|
minX = x
|
|
}
|
|
if x > maxX {
|
|
maxX = x
|
|
}
|
|
if y < minY {
|
|
minY = y
|
|
}
|
|
if y > maxY {
|
|
maxY = y
|
|
}
|
|
}
|
|
|
|
func PrettyPrint() {
|
|
for kY := minY; kY <= maxY; kY++ {
|
|
for kX := minX; kX <= maxX; kX++ {
|
|
if kX == cX && kY == cY {
|
|
fmt.Print("[")
|
|
} else {
|
|
fmt.Print(" ")
|
|
}
|
|
switch nodes[cs(kX, kY)] {
|
|
case ST_CLEAN:
|
|
fmt.Print(".")
|
|
case ST_WEAK:
|
|
fmt.Print("W")
|
|
case ST_INFECTED:
|
|
fmt.Print("#")
|
|
case ST_FLAGGED:
|
|
fmt.Print("F")
|
|
}
|
|
if kX == cX && kY == cY {
|
|
fmt.Print("]")
|
|
} else {
|
|
fmt.Print(" ")
|
|
}
|
|
}
|
|
fmt.Println()
|
|
}
|
|
}
|
|
|
|
func PrintStatus() {
|
|
fmt.Println("Ticks:", tickCount)
|
|
fmt.Println("Infections:", infectCount)
|
|
}
|
|
|
|
func TurnRight() {
|
|
switch cD {
|
|
case N:
|
|
cD = E
|
|
case E:
|
|
cD = S
|
|
case S:
|
|
cD = W
|
|
case W:
|
|
cD = N
|
|
}
|
|
}
|
|
|
|
func TurnLeft() {
|
|
switch cD {
|
|
case N:
|
|
cD = W
|
|
case E:
|
|
cD = N
|
|
case S:
|
|
cD = E
|
|
case W:
|
|
cD = S
|
|
}
|
|
}
|
|
|
|
func getXYInDir() (int, int) {
|
|
switch cD {
|
|
case N:
|
|
return cX, cY - 1
|
|
case E:
|
|
return cX + 1, cY
|
|
case S:
|
|
return cX, cY + 1
|
|
case W:
|
|
return cX - 1, cY
|
|
}
|
|
return cX, cY
|
|
}
|
|
|
|
func cs(x, y int) string {
|
|
return fmt.Sprintf("%d;%d", x, y)
|
|
}
|
|
|
|
func sc(key string) (int, int) {
|
|
pts := strings.Split(key, ";")
|
|
return Atoi(pts[0]), Atoi(pts[1])
|
|
}
|
|
|
|
func Atoi(i string) int {
|
|
var ret int
|
|
var err error
|
|
if ret, err = strconv.Atoi(i); err != nil {
|
|
log.Fatal("Invalid Atoi")
|
|
}
|
|
return ret
|
|
}
|
|
|
|
func ClearScreen() {
|
|
fmt.Println("\033[H\033[2J")
|
|
}
|
|
|
|
func StdinToStrings() []string {
|
|
var input []string
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for scanner.Scan() {
|
|
input = append(input, scanner.Text())
|
|
}
|
|
return input
|
|
}
|