Horje
Rotten Oranges using JavaScript

Given a matrix of dimension M * N, where each cell in the matrix can have values 0, 1, or 2 which has the following meaning:

  • 0: Empty cell
  • 1: Cells have fresh oranges
  • 2: Cells have rotten oranges

The task is to find the minimum time required so that all the oranges become rotten. A rotten orange at index (i,j ) can rot other fresh oranges which are its neighbors (up, down, left, and right). If it is impossible to rot every orange then simply return -1.

Examples:

Input:  arr[][C] = { {2, 1, 0, 2, 1}, {1, 0, 1, 2, 1}, {1, 0, 0, 2, 1}};
Output: 2
Explanation: At 0th time frame:
{2, 1, 0, 2, 1}
{1, 0, 1, 2, 1}
{1, 0, 0, 2, 1}
At 1st time frame:
{2, 2, 0, 2, 2}
{2, 0, 2, 2, 2}
{1, 0, 0, 2, 2}
At 2nd time frame:
{2, 2, 0, 2, 2}
{2, 0, 2, 2, 2}
{2, 0, 0, 2, 2}

Input:  arr[][C] = { {2, 1, 0, 2, 1}, {0, 0, 1, 2, 1}, {1, 0, 0, 2, 1}}
Output: -1
Explanation: At 0th time frame:
{2, 1, 0, 2, 1}
{0, 0, 1, 2, 1}
{1, 0, 0, 2, 1}
At 1st time frame:
{2, 2, 0, 2, 2}
{0, 0, 2, 2, 2}
{1, 0, 0, 2, 2}
At 2nd time frame:
{2, 2, 0, 2, 2}
{0, 0, 2, 2, 2}
{1, 0, 0, 2, 2}
The 1 at the bottom left corner of the matrix is never rotten.

Below are the approaches to find minimum time required to rot all oranges using JavaScript:

Naive Approach

Traverse through all oranges in multiple rounds. In every round, rot the oranges to the adjacent position of oranges that were rotten in the last round.

  • Create a variable no = 2 and changed = false.
  • Run a loop until there is no cell of the matrix which is changed in an iteration.
  • Run a nested loop and traverse the matrix.
  • If the element of the matrix is equal to number then assign the adjacent elements to number + 1, if the adjacent element’s value is equal to 1, i.e. not rotten, and update changed to “true”.
  • Traverse the matrix and check if there is any cell that is 1.
  • If 1 is present, return -1
  • else return no – 2.

Example: Below is the implementation of the above approach in JavaScript.

JavaScript
// Javascript program to
// rot all oranges when you can move
// in all the four direction from a rotten orange
let R = 3;
let C = 5;

// Check if i, j is under the array 
// limits of row and column
function issafe(i, j)
{
    if (i >= 0 && i < R && j >= 0 && j < C)
        return true;
    return false;
}

function rotOranges(v)
{
    let changed = false;
    let no = 2;
    while (true) {
        for (let i = 0; i < R; i++) {
            for (let j = 0; j < C; j++) {

                // Rot all other oranges present at
                // (i+1, j), (i, j-1), (i, j+1), (i-1, j)
                if (v[i][j] == no) {
                    if (issafe(i + 1, j) && v[i + 1][j] == 1) {
                        v[i + 1][j] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i, j + 1) && v[i][j + 1] == 1) {
                        v[i][j + 1] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i - 1, j) && v[i - 1][j] == 1) {
                        v[i - 1][j] = v[i][j] + 1;
                        changed = true;
                    }
                    if (issafe(i, j - 1) && v[i][j - 1] == 1) {
                        v[i][j - 1] = v[i][j] + 1;
                        changed = true;
                    }
                }
            }
        }

        // if no rotten orange found it means all
        // oranges rottened now
        if (!changed)
            break;
        changed = false;
        no++;
    }

    for (let i = 0; i < R; i++) {
        for (let j = 0; j < C; j++) {

            // if any orange is found to be
            // not rotten then ans is not possible
            if (v[i][j] == 1)
                return -1;
        }
    }

    // Because initial value for a rotten
    // orange was 2
    return no - 2;
}

// Driver code
let v = [ [ 2, 1, 0, 2, 1 ],
          [ 1, 0, 1, 2, 1 ],
          [ 1, 0, 0, 2, 1 ] 
        ];

console.log(rotOranges(v));

Output
2

Time Complexity: O((R*C) * (R *C)),

  • The matrix needs to be traversed again and again until there is no change in the matrix, that can happen max(R *C)/2 times.
  • So time complexity is O((R * C) * (R *C)).

Auxiliary Space: O(1), No extra space is required.

The idea is to use Breadth First Search. The condition of oranges getting rotten is when they come in contact with other rotten oranges. This is similar to a breadth-first search where the graph is divided into layers or circles and the search is done from lower or closer layers to deeper or higher layers.

In the previous approach, the idea was based on BFS but the implementation was poor and inefficient. To find the elements whose values are no the whole matrix had to be traversed. So time can be reduced by using this efficient approach of BFS.

Follow the steps below to solve the problem:

  • Create an empty queue Q.
  • Find all rotten oranges and enqueue them to Q. Also, enqueue a delimiter to indicate the beginning of the next time frame.
  • Run a loop While Q is not empty and do the following while the delimiter in Q is not reached
  • Dequeue an orange from the queue, and rot all adjacent oranges.
  • While rotting the adjacent, make sure that the time frame is incremented only once. And the time frame is not incremented if there are no adjacent oranges.
  • Dequeue the old delimiter and enqueue a new delimiter. The oranges rotten in the previous time frame lie between the two delimiters.
  • Return the last time frame.

Example: Below is the implementation of the above approach in JavaScript.

JavaScript
// JS program to find minimum
// time required to make all
// oranges rotten

// function to check whether a cell is valid 


function isvalid(i, j) {
  return (i >= 0 && j >= 0 && i < 3 && j < 5)
}

// Function to check whether the cell is delimiter
// which is (-1, -1)


function isdelim(temp) {
  return (temp[0] == -1 && temp[1] == -1)
}

// Function to check whether there is still a fresh
// orange remaining


function checkall(arr) {
  for (let i = 0; i < 3; i++)
    for (let j = 0; j < 5; j++)
      if (arr[i][j] == 1)
        return true
  return false
}

// This function finds if it is
// possible to rot all oranges or not.
// If possible, then it returns
// minimum time required to rot all,
// otherwise returns -1


function rotOranges(arr) {
  // Create a queue of cells
  let Q = []
  let temp = [0, 0]
  let ans = 1

  // Store all the cells having
  // rotten orange in first time frame
  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 5; j++) {
      if (arr[i][j] == 2) {
        temp[0] = i
        temp[1] = j
        Q.push([i, j])
      }
    }
  }

  // Separate these rotten oranges

  temp[0] = -1
  temp[1] = -1
  Q.push([-1, -1])

  // Process the grid while there are
  // rotten oranges in the Queue
  while (false) {
    // This flag is used to determine
    // whether even a single fresh
    // orange gets rotten due to rotten
    // oranges in current time
    // frame so we can increase
    // the count of the required time.
    flag = false
    console.log(Q.length)

    // Process all the rotten
    // oranges in current time frame.
    while (!isdelim(Q[0])) {
      temp = Q[0]
      console.log(Q.length)

      // Check right adjacent cell
      // that if it can be rotten
      if (isvalid(temp[0] + 1, temp[1]) && 
          arr[temp[0] + 1][temp[1]] == 1) {

        // If this is the first orange
        // to get rotten, increase
        // count && set the flag.
        if (!flag) {
          ans = ans + 1
          flag = true
        }

        // Make the orange rotten
        arr[temp[0] + 1][temp[1]] = 2

        // Append the adjacent orange to Queue
        temp[0] += 1
        Q.push(temp)

        temp[0] -= 1  // Move back to current cell
      }

      // Check left adjacent cell that if it can be rotten
      if (isvalid(temp[0] - 1, temp[1]) &&
        arr[temp[0] - 1][temp[1]] == 1) {
        if (!flag) {
          ans = ans + 1
          flag = true
        }
        arr[temp[0] - 1][temp[1]] = 2
        temp[0] -= 1

        //Append this cell to queue
        Q.push(temp)
        temp[0] += 1
      }

      // Check top adjacent cell that if it can be rotten
      if (isvalid(temp[0], temp[1] + 1) &&
          arr[temp[0]][temp[1] + 1] == 1) {
        if (!flag) {
          ans++;
          flag = true;
        }
        arr[temp[0]][temp[1] + 1] = 2
        temp[1] += 1

        //Push this cell to queue
        Q.push(temp)
        temp[1] -= 1
      }

      // Check bottom adjacent cell if it can be rotten
      if (isvalid(temp[0], temp[1] - 1)
        && arr[temp[0]][temp[1] - 1] == 1) {
        if (!flag) {
          ans++;
          flag = true;
        }
        arr[temp[0]][temp[1] - 1] = 2
        temp[1] -= 1
        //Append this cell to queue
        Q.push(temp)
      }
      Q.shift()

    }
    // Pop the delimiter
    Q.shift()

    // If oranges were rotten in
    // current frame than separate the
    // rotten oranges using delimiter
    // for the next frame for processing.
    if (Q.length == 0) {
      temp[0] = -1
      temp[1] = -1
      Q.push(temp)
    }

    // If Queue was empty than no rotten oranges 
    // left to process so exit
  }

  // Return -1 if all arranges 
  // could not rot, 
  // otherwise return ans.
  if (checkall(arr))
    return ans + 1
  return -1
}

// Driver program
let arr = [[2, 1, 0, 2, 1],
[1, 0, 1, 2, 1],
[1, 0, 0, 2, 1]]
let ans = rotOranges(arr)
console.log(ans)

Output
2

Time Complexity: O( R *C), Each element of the matrix can be inserted into the queue only once so the upper bound of iteration is O(R*C)

Auxiliary Space: O(R*C), To store the elements in a queue.




Reffered: https://www.geeksforgeeks.org


JavaScript

Related
How to Build a JavaScript App with ChatGPT? How to Build a JavaScript App with ChatGPT?
Infinite Scroll using JavaScript Intersection Observer API Infinite Scroll using JavaScript Intersection Observer API
How to create a Responsive Bottom Navigation Menu with CSS and JavaScript. How to create a Responsive Bottom Navigation Menu with CSS and JavaScript.
Compile-Time Reactivity for JavaScript Compile-Time Reactivity for JavaScript
Split a Sentence into Fixed-Length Blocks without Breaking Words in JavaScript Split a Sentence into Fixed-Length Blocks without Breaking Words in JavaScript

Type:
Geek
Category:
Coding
Sub Category:
Tutorial
Uploaded by:
Admin
Views:
18