package main import ( "crypto/md5" "fmt" "os" termbox "github.com/nsf/termbox-go" "../../" ) var gridWidth, gridHeight int var path string func main() { // TODO: Random seed passcode := "pvhmgsws" gridWidth, gridHeight = 4, 4 if len(os.Args) >= 3 { gridWidth = aoc.Atoi(os.Args[1]) gridHeight = aoc.Atoi(os.Args[2]) } run := true err := termbox.Init() if err != nil { panic(err) } defer termbox.Close() var e termbox.Event for run { PrintState("", passcode) e = termbox.PollEvent() if e.Type == termbox.EventKey { if e.Key == termbox.KeyCtrlC { run = false } } } } // We cache the last hash calculated // It should speed things up a little var lastHashInput string var lastHash string func doorIsOpen(path, passcode string, dir rune) bool { if lastHashInput != passcode+path { lastHashInput = passcode + path lastHash = fmt.Sprintf("%x", md5.Sum([]byte(lastHashInput))) } switch dir { case 'N': return lastHash[0] >= 'b' && lastHash[0] <= 'f' case 'E': return lastHash[3] >= 'b' && lastHash[3] <= 'f' case 'S': return lastHash[1] >= 'b' && lastHash[1] <= 'f' case 'W': return lastHash[2] >= 'b' && lastHash[2] <= 'f' } return false } func currPos(path string) (int, int) { var cX, cY int for i := range path { switch path[i] { case 'U': cY-- case 'D': cY++ case 'L': cX-- case 'R': cX++ } } return cX, cY } func PrintState(path, passcode string) { posX, posY := currPos(path) for y := 0; y < gridHeight; y++ { for x := 0; x < gridWidth; x++ { fmt.Print(aoc.BorderNW) if posX == x && posY == y && doorIsOpen(path, passcode, 'N') { // Current Pos w/ open door fmt.Print(aoc.BorderSE) fmt.Print(aoc.BorderSW) } else if y == posY+1 && x == posX && doorIsOpen(path, passcode, 'S') { // Room below, w/ open door fmt.Print(aoc.BorderNE) fmt.Print(aoc.BorderNW) } else { // All other cases fmt.Print(aoc.BorderWE) fmt.Print(aoc.BorderWE) } fmt.Print(aoc.BorderNE) } fmt.Println() for x := 0; x < gridWidth; x++ { if posX == x && posY == y && doorIsOpen(path, passcode, 'W') { fmt.Print(aoc.BorderSE) } else { fmt.Print(aoc.BorderNS) } if posX == x && posY == y { fmt.Print(aoc.BorderNW) fmt.Print(aoc.BorderNE) } else { fmt.Print(" ") fmt.Print(" ") } if posX == x && posY == y && doorIsOpen(path, passcode, 'E') { fmt.Print(aoc.BorderSW) } else { fmt.Print(aoc.BorderNS) } } fmt.Println() for x := 0; x < gridWidth; x++ { if posX == x && posY == y && doorIsOpen(path, passcode, 'W') { fmt.Print(aoc.BorderNE) } else { fmt.Print(aoc.BorderNS) } if posX == x && posY == y { fmt.Print(aoc.BorderSW) fmt.Print(aoc.BorderSE) } else { fmt.Print(" ") fmt.Print(" ") } if posX == x && posY == y && doorIsOpen(path, passcode, 'E') { fmt.Print(aoc.BorderNW) } else { fmt.Print(aoc.BorderNS) } } fmt.Println() for x := 0; x < gridWidth; x++ { fmt.Print(aoc.BorderSW) if posX == x && posY == y && doorIsOpen(path, passcode, 'S') { fmt.Print(aoc.BorderNE) fmt.Print(aoc.BorderNW) } else { fmt.Print(aoc.BorderWE) fmt.Print(aoc.BorderWE) } fmt.Print(aoc.BorderSE) } fmt.Println() } } func ClearScreen() { fmt.Print(aoc.ClearScreen) } func printUsageAndExit() { fmt.Println("Usage: ./day17 ") os.Exit(0) }