80 lines
1.3 KiB
Go
80 lines
1.3 KiB
Go
|
package main
|
||
|
|
||
|
import (
|
||
|
aq "github.com/emirpasic/gods/v2/queues/arrayqueue"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
EMPTY_CELL int = 0
|
||
|
FRESH_ORANGE int = 1
|
||
|
ROTTEN_ORANGE int = 2
|
||
|
)
|
||
|
|
||
|
type BFSEntry struct {
|
||
|
time int
|
||
|
y, x int
|
||
|
}
|
||
|
|
||
|
func orangesRotting(grid [][]int) int {
|
||
|
DIRECTIONS := [][]int{
|
||
|
[]int{0, 1},
|
||
|
[]int{0, -1},
|
||
|
[]int{1, 0},
|
||
|
[]int{-1, 0},
|
||
|
}
|
||
|
|
||
|
inBounds := func(y, x int) bool {
|
||
|
return y >= 0 && y < len(grid) && x >= 0 && x < len(grid[y])
|
||
|
}
|
||
|
countFresh := func() int {
|
||
|
fresh := 0
|
||
|
|
||
|
for _, row := range grid {
|
||
|
for _, orange := range row {
|
||
|
if orange == FRESH_ORANGE {
|
||
|
fresh++
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fresh
|
||
|
}
|
||
|
initializeQueue := func(q *aq.Queue[BFSEntry]) {
|
||
|
for y, row := range grid {
|
||
|
for x, orange := range row {
|
||
|
if orange != ROTTEN_ORANGE {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
q.Enqueue(BFSEntry{time: 0, y: y, x: x})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
q := aq.New[BFSEntry]()
|
||
|
initializeQueue(q)
|
||
|
|
||
|
fresh, time := countFresh(), 0
|
||
|
for !q.Empty() && fresh > 0 {
|
||
|
value, _ := q.Dequeue()
|
||
|
|
||
|
for _, d := range DIRECTIONS {
|
||
|
ny, nx := value.y+d[0], value.x+d[1]
|
||
|
if !inBounds(ny, nx) || grid[ny][nx] != FRESH_ORANGE {
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
grid[ny][nx] = ROTTEN_ORANGE
|
||
|
fresh--
|
||
|
q.Enqueue(BFSEntry{time: value.time + 1, y: ny, x: nx})
|
||
|
time = value.time + 1
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if fresh > 0 {
|
||
|
return -1
|
||
|
}
|
||
|
|
||
|
return time
|
||
|
}
|