diff --git a/go/rotting-oranges.go b/go/rotting-oranges.go new file mode 100644 index 0000000..76680ed --- /dev/null +++ b/go/rotting-oranges.go @@ -0,0 +1,79 @@ +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 +}