You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
5.6 KiB
Go

package day21
import (
"fmt"
"gitea.paas.celticinfo.fr/oabrivard/aoc2023/utils"
)
type Coord struct {
row int
col int
}
func BFS1(matrix [][]byte, root Coord, maxSteps int) int {
height := len(matrix)
width := len(matrix[0])
queue := utils.NewQueue[*Coord]()
matrix[root.row][root.col] = 'O'
queue.Enqueue(&root)
moves := 0
for moves < maxSteps {
//fmt.Println(moves + 1)
newQueue := utils.NewQueue[*Coord]()
for queue.HasElement() {
coord := queue.Dequeue()
matrix[coord.row][coord.col] = '.'
if coord.row > 0 && matrix[coord.row-1][coord.col] != '#' {
newCoord := Coord{coord.row - 1, coord.col}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
}
if coord.row < height-1 && matrix[coord.row+1][coord.col] != '#' {
newCoord := Coord{coord.row + 1, coord.col}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
}
if coord.col > 0 && matrix[coord.row][coord.col-1] != '#' {
newCoord := Coord{coord.row, coord.col - 1}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
}
if coord.col < width-1 && matrix[coord.row][coord.col+1] != '#' {
newCoord := Coord{coord.row, coord.col + 1}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
}
}
queue = newQueue
moves++
}
// count 'O' in matrix
count := 0
for r := range matrix {
for _, b := range matrix[r] {
if b == 'O' {
count++
}
}
}
return count
}
func redrawFromCache(matrix [][]byte, cacheQueue utils.Queue[*Coord]) {
for _, coord := range cacheQueue.GetData() {
if coord != nil {
matrix[coord.row][coord.col] = 'O'
}
}
}
func BFS2(matrix [][]byte, root Coord, maxSteps int) int {
height := len(matrix)
width := len(matrix[0])
queue := utils.NewQueue[*Coord]()
cache := make([][]utils.Queue[*Coord], height)
for r, row := range matrix {
cache[r] = make([]utils.Queue[*Coord], width)
for c := range row {
cache[r][c] = utils.NewQueue[*Coord]()
}
}
matrix[root.row][root.col] = 'O'
queue.Enqueue(&root)
moves := 0
for moves < maxSteps {
fmt.Println(moves + 1)
newQueue := utils.NewQueue[*Coord]()
for queue.HasElement() {
coord := queue.Dequeue()
if cache[coord.row][coord.col].HasElement() {
matrix[coord.row][coord.col] = '.'
redrawFromCache(matrix, cache[coord.row][coord.col])
} else {
cacheQueue := utils.NewQueue[*Coord]()
matrix[coord.row][coord.col] = '.'
if coord.row > 0 && matrix[coord.row-1][coord.col] != '#' {
newCoord := Coord{coord.row - 1, coord.col}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
cacheQueue.Enqueue(&newCoord)
}
if coord.row < height-1 && matrix[coord.row+1][coord.col] != '#' {
newCoord := Coord{coord.row + 1, coord.col}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
cacheQueue.Enqueue(&newCoord)
}
if coord.col > 0 && matrix[coord.row][coord.col-1] != '#' {
newCoord := Coord{coord.row, coord.col - 1}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
cacheQueue.Enqueue(&newCoord)
}
if coord.col < width-1 && matrix[coord.row][coord.col+1] != '#' {
newCoord := Coord{coord.row, coord.col + 1}
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
cacheQueue.Enqueue(&newCoord)
}
cache[coord.row][coord.col] = cacheQueue
}
}
queue = newQueue
moves++
}
// count 'O' in matrix
count := 0
for r := range matrix {
for _, b := range matrix[r] {
if b == 'O' {
count++
}
}
}
return count
}
func BFS3(matrix [][]byte, root Coord, maxSteps int) int {
height := len(matrix)
width := len(matrix[0])
queue := utils.NewQueue[*Coord]()
matrix[root.row][root.col] = 'O'
queue.Enqueue(&root)
moves := 0
for moves < maxSteps {
//fmt.Println(moves + 1)
newQueue := utils.NewQueue[*Coord]()
coordInQueue := map[Coord]bool{}
for queue.HasElement() {
coord := queue.Dequeue()
matrix[coord.row][coord.col] = '.'
if coord.row > 0 && matrix[coord.row-1][coord.col] != '#' {
newCoord := Coord{coord.row - 1, coord.col}
if !coordInQueue[newCoord] {
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
coordInQueue[newCoord] = true
}
}
if coord.row < height-1 && matrix[coord.row+1][coord.col] != '#' {
newCoord := Coord{coord.row + 1, coord.col}
if !coordInQueue[newCoord] {
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
coordInQueue[newCoord] = true
}
}
if coord.col > 0 && matrix[coord.row][coord.col-1] != '#' {
newCoord := Coord{coord.row, coord.col - 1}
if !coordInQueue[newCoord] {
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
coordInQueue[newCoord] = true
}
}
if coord.col < width-1 && matrix[coord.row][coord.col+1] != '#' {
newCoord := Coord{coord.row, coord.col + 1}
if !coordInQueue[newCoord] {
newQueue.Enqueue(&newCoord)
matrix[newCoord.row][newCoord.col] = 'O'
coordInQueue[newCoord] = true
}
}
}
queue = newQueue
moves++
}
// count 'O' in matrix
count := 0
for r := range matrix {
for _, b := range matrix[r] {
if b == 'O' {
count++
}
}
}
return count
}
func Part1(lines []string, maxSteps int) int {
matrix := make([][]byte, len(lines))
var root Coord
for r, line := range lines {
matrix[r] = make([]byte, len(line))
for c, b := range line {
matrix[r][c] = byte(b)
if b == 'S' {
root.row = r
root.col = c
}
}
}
result := BFS3(matrix, root, maxSteps)
return result
}