Files
adventofcode/2024/gareth/day06/day06.go
Gareth ae293fe5a2 Day06
2025-01-11 16:39:58 +00:00

143 lines
2.6 KiB
Go

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
}
}
}