Day06
This commit is contained in:
142
2024/gareth/day06/day06.go
Normal file
142
2024/gareth/day06/day06.go
Normal file
@@ -0,0 +1,142 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user