package main import ( "bufio" "fmt" "os" ) func waitEnter() { fmt.Printf("Press ENTER to continue\n") bufio.NewReader(os.Stdin).ReadBytes('\n') } var doors = map[byte]Point{ 'N': Point{0, -1}, 'W': Point{-1, 0}, 'E': Point{1, 0}, 'S': Point{0, 1}, } type Puzzle struct { } func (p *Puzzle) PrintMap() { /* for y := 0; y < p.gridH; y++ { i := y * p.gridW for x := 0; x < p.gridW; x++ { c := p.grid[i+x] if c == 0 { c = ' ' } fmt.Printf("%c", c) } fmt.Printf("\n") } */ } type Point struct { X, Y int } func min(a, b int) int { if a < b { return a } return b } func (p *Puzzle) Map(directions []byte) { positions := make([]Point, 0, 100) distances := make(map[Point]int) pos := Point{5000, 5000} prev := pos for _, c := range directions[1 : len(directions)-1] { switch c { case '(': positions = append(positions, pos) case ')': pos, positions = positions[len(positions)-1], positions[:len(positions)-1] case '|': pos = positions[len(positions)-1] default: target := doors[c] pos.X += target.X pos.Y += target.Y if _, ok := distances[pos]; ok { distances[pos] = min(distances[pos], distances[prev]+1) } else { distances[pos] = distances[prev] + 1 } } prev = pos } dist := 0 count := 0 for _, d := range distances { if d > dist { dist = d } if d >= 1000 { count++ } } fmt.Println("Solution 1:", dist, "steps") fmt.Println("Solution 2:", count, "rooms") } func (p *Puzzle) MapFile(filepath string) { var buf []byte input, err := os.Open(filepath) if err != nil { panic(err.Error()) } defer input.Close() scanner := bufio.NewScanner(input) for scanner.Scan() { buf = scanner.Bytes() } if err := scanner.Err(); err != nil { panic(err.Error()) } p.Map(buf) } func main() { // Tests p := Puzzle{} p.Map([]byte("^WNE$")) p.Map([]byte("^ENWWW(NEEE|SSE(EE|N))$")) p.Map([]byte("^ENNWSWW(NEWS|)SSSEEN(WNSE|)EE(SWEN|)NNN$")) p.MapFile("input.txt") waitEnter() }