148 lines
3.2 KiB
Go
148 lines
3.2 KiB
Go
package main
|
|
|
|
import (
|
|
"github.com/StevanFreeborn/advent-of-code-2025/internal/file"
|
|
"github.com/StevanFreeborn/advent-of-code-2025/internal/grid"
|
|
"github.com/StevanFreeborn/advent-of-code-2025/internal/move"
|
|
"github.com/StevanFreeborn/advent-of-code-2025/internal/position"
|
|
"github.com/StevanFreeborn/advent-of-code-2025/internal/queue"
|
|
"github.com/StevanFreeborn/advent-of-code-2025/internal/stack"
|
|
)
|
|
|
|
const StartCharacter = "S"
|
|
const SplitterCharacter = "^"
|
|
|
|
func SolvePartOne(filePath string) int {
|
|
input := file.ReadAllLines(filePath)
|
|
grid := grid.From(input)
|
|
|
|
var startPosition position.Position
|
|
|
|
for p, v := range grid.Positions() {
|
|
if v == StartCharacter {
|
|
startPosition = p
|
|
break
|
|
}
|
|
}
|
|
|
|
if startPosition == nil {
|
|
panic("unable to find start location")
|
|
}
|
|
|
|
beamStart := startPosition.Move(move.Down)
|
|
beamsQueue := queue.New[position.Position]()
|
|
beamsQueue.Enqueue(beamStart)
|
|
|
|
visited := map[position.Position]bool{}
|
|
|
|
total := 0
|
|
|
|
for beamsQueue.IsEmpty() == false {
|
|
currentBeam, _ := beamsQueue.Dequeue()
|
|
|
|
if visited[currentBeam] {
|
|
continue
|
|
}
|
|
|
|
if grid.InBounds(currentBeam) == false {
|
|
continue
|
|
}
|
|
|
|
visited[currentBeam] = true
|
|
|
|
value := grid.GetValueAt(currentBeam)
|
|
|
|
if value == SplitterCharacter {
|
|
total++
|
|
|
|
rightBeam := currentBeam.Move(move.Right)
|
|
leftBeam := currentBeam.Move(move.Left)
|
|
|
|
beamsQueue.Enqueue(rightBeam)
|
|
beamsQueue.Enqueue(leftBeam)
|
|
continue
|
|
}
|
|
|
|
nextBeam := currentBeam.Move(move.Down)
|
|
beamsQueue.Enqueue(nextBeam)
|
|
}
|
|
|
|
return total
|
|
}
|
|
|
|
func SolvePartTwo(filePath string) int {
|
|
input := file.ReadAllLines(filePath)
|
|
grid := grid.From(input)
|
|
|
|
var startPosition position.Position
|
|
|
|
for p, v := range grid.Positions() {
|
|
if v == StartCharacter {
|
|
startPosition = p
|
|
break
|
|
}
|
|
}
|
|
|
|
if startPosition == nil {
|
|
panic("unable to find start location")
|
|
}
|
|
|
|
beamStartPosition := startPosition.Move(move.Down)
|
|
beamsStack := stack.New[position.Position]()
|
|
beamsStack.Push(beamStartPosition)
|
|
|
|
positionsToTimelinesMap := map[position.Position]int{}
|
|
|
|
for beamsStack.IsEmpty() == false {
|
|
currentBeam, _ := beamsStack.Peek()
|
|
|
|
_, hasBeenProcessed := positionsToTimelinesMap[currentBeam]
|
|
|
|
if hasBeenProcessed {
|
|
beamsStack.Pop()
|
|
continue
|
|
}
|
|
|
|
value := grid.GetValueAt(currentBeam)
|
|
nextTimelinePositions := []position.Position{}
|
|
|
|
if value == SplitterCharacter {
|
|
rightBeam := currentBeam.Move(move.Right)
|
|
leftBeam := currentBeam.Move(move.Left)
|
|
nextTimelinePositions = append(nextTimelinePositions, rightBeam, leftBeam)
|
|
} else {
|
|
nextBeam := currentBeam.Move(move.Down)
|
|
nextTimelinePositions = append(nextTimelinePositions, nextBeam)
|
|
}
|
|
|
|
numberOfTimelinesForPosition := 0
|
|
finalizePosition := true
|
|
|
|
for _, newTimelinePosition := range nextTimelinePositions {
|
|
if grid.InBounds(newTimelinePosition) == false {
|
|
numberOfTimelinesForPosition++
|
|
continue
|
|
}
|
|
|
|
v, existing := positionsToTimelinesMap[newTimelinePosition]
|
|
|
|
if existing {
|
|
numberOfTimelinesForPosition += v
|
|
continue
|
|
}
|
|
|
|
beamsStack.Push(newTimelinePosition)
|
|
finalizePosition = false
|
|
}
|
|
|
|
if finalizePosition == false {
|
|
continue
|
|
}
|
|
|
|
beamsStack.Pop()
|
|
positionsToTimelinesMap[currentBeam] = numberOfTimelinesForPosition
|
|
}
|
|
|
|
return positionsToTimelinesMap[beamStartPosition]
|
|
}
|