123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- package main
- import (
- "bufio"
- "fmt"
- "log"
- "os"
- "strings"
- )
- const (
- Up = iota
- Down
- Left
- Right
- )
- type Point struct {
- y, x int
- direction int
- }
- func (p *Point) move(maze [][]byte, height int, width int) bool {
- switch maze[p.y][p.x] {
- case '|':
- if p.direction == Up && p.y-1 >= 0 {
- p.y--
- return true
- } else if p.direction == Down && p.y+1 < height {
- p.y++
- return true
- }
- case '-':
- if p.direction == Right && p.x+1 < width {
- p.x++
- return true
- } else if p.direction == Left && p.x-1 >= 0 {
- p.x--
- return true
- }
- case 'L':
- if p.direction == Down && p.x+1 < width {
- p.x++
- p.direction = Right
- return true
- } else if p.direction == Left && p.y-1 >= 0 {
- p.y--
- p.direction = Up
- return true
- }
- case 'J':
- if p.direction == Down && p.x-1 >= 0 {
- p.x--
- p.direction = Left
- return true
- } else if p.direction == Right && p.y-1 >= 0 {
- p.y--
- p.direction = Up
- return true
- }
- case '7':
- if p.direction == Right && p.y+1 < height {
- p.y++
- p.direction = Down
- return true
- } else if p.direction == Up && p.x-1 >= 0 {
- p.x--
- p.direction = Left
- return true
- }
- case 'F':
- if p.direction == Up && p.x+1 < width {
- p.x++
- p.direction = Right
- return true
- } else if p.direction == Left && p.y+1 < height {
- p.y++
- p.direction = Down
- return true
- }
- }
- return false
- }
- const (
- verticalAbove = "|7F"
- verticalBelow = "|LJ"
- horizontalLeft = "-LF"
- horizontalRight = "-J7"
- )
- func establishS(s Point, maze [][]byte, height int, width int) (byte, Point) {
- var left, right, up, down bool
- if s.x-1 >= 0 && strings.Contains(horizontalLeft, string(maze[s.y][s.x-1])) {
- left = true
- }
- if s.x+1 < width && strings.Contains(horizontalRight, string(maze[s.y][s.x+1])) {
- right = true
- }
- if s.y-1 >= 0 && strings.Contains(verticalAbove, string(maze[s.y-1][s.x])) {
- up = true
- }
- if s.y+1 < height && strings.Contains(verticalBelow, string(maze[s.y+1][s.x])) {
- down = true
- }
- var char byte
- if left {
- if right {
- char = '-'
- s.direction = Right
- } else if up {
- char = 'J'
- s.direction = Down
- } else if down {
- char = '7'
- s.direction = Up
- }
- } else if right {
- if up {
- char = 'L'
- s.direction = Down
- } else if down {
- char = 'F'
- s.direction = Up
- }
- } else if up {
- char = '|'
- s.direction = Down
- }
- return char, s
- }
- func part1(maze [][]byte) int {
- height := len(maze)
- width := len(maze[0])
- for y := range maze {
- for x := range maze[y] {
- if maze[y][x] == 'S' {
- char, start := establishS(Point{y: y, x: x}, maze, height, width)
- maze[y][x] = char
- current := start
- steps := 0
- for {
- if !current.move(maze, height, width) {
- break
- }
- steps++
- if current.x == start.x && current.y == start.y {
- return steps / 2
- }
- }
- }
- }
- }
- return -1
- }
- func readInput(file *os.File) [][]byte {
- scanner := bufio.NewScanner(file)
- var maze [][]byte
- width := -1
- for scanner.Scan() {
- line := scanner.Text()
- if line == "" {
- break
- }
- if width < 0 {
- width = len(line)
- }
- row := make([]byte, width)
- for i := range line {
- row[i] = line[i]
- }
- maze = append(maze, row)
- }
- return maze
- }
- func main() {
- if len(os.Args) < 2 {
- log.Fatal("You need to specify a file!")
- }
- filePath := os.Args[1]
- file, err := os.Open(filePath)
- if err != nil {
- log.Fatalf("Failed to open %s!\n", filePath)
- }
- maze := readInput(file)
- fmt.Println("Part1:", part1(maze))
- }
|