Rotting Oranges
Problem statement
You are given an m x n grid where each cell can have one of three values:
0representing an empty cell,1representing a fresh orange, or2representing a rotten orange.
Every minute, any fresh orange that is 4-directionally adjacent to a rotten orange becomes rotten.
Return the minimum number of minutes that must elapse until no cell has a fresh orange. If this is impossible, return -1.
Example 1:

Input: grid = [[2,1,1],[1,1,0],[0,1,1]]Output: 4
Example 2:
Input: grid = [[2,1,1],[0,1,1],[1,0,1]]Output: -1Explanation: The orange in the bottom left corner (row 2, column 0) is never rotten, because rotting only happens 4-directionally.
Example 3:
Input: grid = [[0,2]]Output: 0Explanation: Since there are already no fresh oranges at minute 0, the answer is just 0.
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 10grid[i][j]is0,1, or2.
My solution
/**
* @param {number[][]} grid
* @return {number}
*/
var orangesRotting = function(grid) {
const fresh = new Set();
let rottens = new Set();
function makeKey(i, j) {
return `${i}${j}`
}
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid[0].length; j++) {
if (grid[i][j] === 2) {
rottens.add(makeKey(i, j))
} else if (grid[i][j] === 1) {
fresh.add(makeKey(i, j))
}
}
}
let minutes = 0;
const getDirections = (i, j) => [
[i + 1, j],
[i - 1, j],
[i, j + 1],
[i, j - 1],
];
while (fresh.size > 0) {
let infected = new Set();
for (const [rotten] of rottens.entries()) {
const [x, y] = rotten.split("").map(v => parseInt(v, 10))
for (const [newX, newY] of getDirections(x, y)) {
const newKey = makeKey(newX, newY);
if (fresh.has(newKey)) {
fresh.delete(newKey);
infected.add(newKey)
}
}
}
if (infected.size === 0) {
return -1;
}
rottens = infected;
minutes++
}
return minutes;
};