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 }