package day06 import ( "strings" ) type Point struct { x int y int direction int } const ( Up = 0 Right = 1 Down = 2 Left = 3 ) var rows, cols int var moves = []Point{ {-1, 0, Up}, {0, 1, Up}, {1, 0, Up}, {0, -1, Up}, } func Part1(input string) int { grid, start, direction := ParseInput(input) total := PredictPath(grid, start, direction) return total } func Part2(input string) int { grid, start, direction := ParseInput(input) total := FindLoopingPositions(grid, start, direction) return total } func ParseInput(input string) ([][]rune, Point, int) { lines := strings.Split(strings.TrimSpace(input), "\n") rows = len(lines) cols = len(lines[0]) grid := make([][]rune, rows) var start Point var direction int for i := 0; i < rows; i++ { grid[i] = []rune(lines[i]) for j, char := range lines[i] { if char == '^' { start = Point{i, j, Up} direction = Up } else if char == '>' { start = Point{i, j, Right} direction = Right } else if char == 'v' { start = Point{i, j, Down} direction = Down } else if char == '<' { start = Point{i, j, Left} direction = Left } } } return grid, start, direction } func PredictPath(grid [][]rune, start Point, direction int) int { visited := make(map[Point]bool) current := start visited[current] = true // do while for { next := Point{current.x + moves[direction].x, current.y + moves[direction].y, Up} if next.x < 0 || next.x >= rows || next.y < 0 || next.y >= cols { break } if grid[next.x][next.y] == '#' { direction = (direction + 1) % 4 } else { current = next visited[current] = true } } return len(visited) } func FindLoopingPositions(grid [][]rune, start Point, direction int) int { possiblePositions := 0 for i := 0; i < rows; i++ { for j := 0; j < cols; j++ { if grid[i][j] != '.' || (i == start.x && j == start.y) { continue } grid[i][j] = '#' if IsLooping(grid, start, direction) { possiblePositions++ } grid[i][j] = '.' } } return possiblePositions } func IsLooping(grid [][]rune, start Point, direction int) bool { visited := make(map[Point]int) current := start step := 0 for { step++ next := Point{current.x + moves[direction].x, current.y + moves[direction].y, direction} if next.x < 0 || next.x >= rows || next.y < 0 || next.y >= cols { return false } if grid[next.x][next.y] == '#' { direction = (direction + 1) % 4 } else { current = next if visitStep, ok := visited[current]; ok && step-visitStep > 4 { return true } visited[current] = step } } }