description: You have received data from a Bubble bot. You know your task is to make factory facilities, but before you even start, you need to know how big the factory is and how many rooms it has. When you look at the data you see that you have the dimensions of the construction, which is in rectangle shape: N x M. 
  
  Then in the next N lines you have M numbers. These numbers represent factory tiles and they can go from 0 to 15. Each of these numbers should be looked in its binary form. Because from each number you know on which side the tile has walls. For example number 10 in it's binary form is 1010, which means that it has a wall from the North side, it doesn't have a wall from the East, it has a wall on the South side and it doesn't have a wall on the West side. So it goes North, East, South, West. 
  
  It is guaranteed that the construction always has walls on it's edges. The input will be correct. 
  
  Your task is to print the size of the rooms from biggest to smallest. 
  
  Input
  
  The first line has two numbers which are N and M, the size of the construction. Both are integers: 
  
  n (1 ≤ n ≤ 10^3)
  
  m (1 ≤ m ≤ 10^3)
  
  Next N x M numbers represent each tile of construction.
  
  Output
  
  Once you finish processing the data your output consists of one line sorted from biggest to smallest room sizes. 
  
  Example
  
  Input
  
  
  4 5
  9 14 11 12 13
  5 15 11 6 7
  5 9 14 9 14
  3 2 14 3 14
  
  
  Output
  
  
  9 4 4 2 1 
solution: import java.io.*;
  import java.util.*;
  
  import static java.lang.Math.*;
  
  public class _1600J {
      static  int count, vis[][], grid[][][];
  
      static void MainCode() {
          n = ni();
          m = ni();
          grid = new int[n][m][4];
          for (int i = 0; i < n; i++) {
              for (int j = 0; j < m; j++) {
                  char[] ch = getBinaryString(ni()).toCharArray();
                  if (ch[0] == '0') grid[i][j][0] = 1;
                  if (ch[1] == '0') grid[i][j][1] = 1;
                  if (ch[2] == '0') grid[i][j][2] = 1;
                  if (ch[3] == '0') grid[i][j][3] = 1;
              }
          }
          ArrayList<Integer> answers = new ArrayList<>();
          vis = new int[n][m];
          for (int i = 0; i < n; i++) {
              for(int j=0;j<m;j++) {
                  if (vis[i][j] == 0) {
                      count = 0;
                      dfs(i,j);
                      answers.add(-count);
                  }
              }
          }
          Collections.sort(answers);
          for (int i : answers) p(-i);
      }
  
      static void dfs(int x, int y) {
          if(vis[x][y] ==1)return;
          count++;
          vis[x][y] = 1;
          if(grid[x][y][0] == 1)dfs(x-1,y);
          if(grid[x][y][1] == 1)dfs(x, y + 1);
          if(grid[x][y][2] == 1)dfs(x + 1, y);
          if(grid[x][y][3] == 1)dfs(x, y - 1);
      }
  
      static String getBinaryString(int i) {
          StringBuilder s = new StringBuilder();
          for (int j = 3; j >= 0; j--) {
              if (((i >> j) & 1) == 1) {
                  s.append(1);
                  i -= (1 << j);
              } else s.append(0);
          }
          return s.toString();
      }
  
      //----------------------------------------The main code ends here------------------------------------------------------
      /*-------------------------------------------------------------------------------------------------------------------*/
      //-----------------------------------------Rest's all dust-------------------------------------------------------------
  
      static int mod9 = 1_000_000_007;
      static int n, m, l, k, t;
      static AwesomeInput input;
      static PrintWriter pw;
  
      static long power(long a, long b) {
          long x = max(a, b);
          if (b == 0) return 1;
          if ((b & 1) == 1) return a * power(a * a, b >> 1);
          return power(a * a, b >> 1);
      }
  
      // The Awesome Input Code is a fast IO method //
      static class AwesomeInput {
          private InputStream letsDoIT;
          private byte[] buf = new byte[1024];
          private int curChar;
          private int numChars;
          private SpaceCharFilter filter;
  
          private AwesomeInput(InputStream incoming) {
              this.letsDoIT = incoming;
          }
  
          public int read() {
              if (numChars == -1)
                  throw new InputMismatchException();
              if (curChar >= numChars) {
                  curChar = 0;
                  try {
                      numChars = letsDoIT.read(buf);
                  } catch (IOException e) {
                      throw new InputMismatchException();
                  }
                  if (numChars <= 0)
                      return -1;
              }
              return buf[curChar++];
          }
  
          private long ForLong() {
              int c = read();
              while (isSpaceChar(c))
                  c = read();
              int sgn = 1;
              if (c == '-') {
                  sgn = -1;
                  c = read();
              }
              long res = 0;
              do {
                  if (c < '0' || c > '9')
                      throw new InputMismatchException();
                  res *= 10;
                  res += c - '0';
                  c = read();
              }
              while (!isSpaceChar(c));
              return res * sgn;
          }
  
          private String ForString() {
              int c = read();
              while (isSpaceChar(c))
                  c = read();
              StringBuilder res = new StringBuilder();
              do {
                  res.appendCodePoint(c);
                  c = read();
              }
              while (!isSpaceChar(c));
  
              return res.toString();
          }
  
          public boolean isSpaceChar(int c) {
              if (filter != null)
                  return filter.isSpaceChar(c);
              return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
          }
  
          public interface SpaceCharFilter {
              boolean isSpaceChar(int ch);
          }
      }
  
      // functions to take input//
      static int ni() {
          return (int) input.ForLong();
      }
  
      static String ns() {
          return input.ForString();
      }
  
      static long nl() {
          return input.ForLong();
      }
  
      //functions to give output
      static void pl() {
          pw.println();
      }
  
      static void p(Object o) {
          pw.print(o + " ");
      }
  
      static void pws(Object o) {
          pw.print(o + "");
      }
  
      static void pl(Object o) {
          pw.println(o);
      }
  
      // Fast Sort is Radix Sort
      public static int[] fastSort(int[] f) {
          int n = f.length;
          int[] to = new int[n];
          {
              int[] b = new int[65537];
              for (int i = 0; i < n; i++) b[1 + (f[i] & 0xffff)]++;
              for (int i = 1; i <= 65536; i++) b[i] += b[i - 1];
              for (int i = 0; i < n; i++) to[b[f[i] & 0xffff]++] = f[i];
              int[] d = f;
              f = to;
              to = d;
          }
          {
              int[] b = new int[65537];
              for (int i = 0; i < n; i++) b[1 + (f[i] >>> 16)]++;
              for (int i = 1; i <= 65536; i++) b[i] += b[i - 1];
              for (int i = 0; i < n; i++) to[b[f[i] >>> 16]++] = f[i];
              int[] d = f;
              f = to;
              to = d;
          }
          return f;
      }
  
      public static void main(String[] args) {      //threading has been used to increase the stack size.
          try {
              input = new AwesomeInput(System.in);
              pw = new PrintWriter(System.out, true);
              input = new AwesomeInput(new FileInputStream(new File("input.txt")));
              pw = new PrintWriter(new BufferedWriter(new FileWriter(new File("output.txt"))), true);
  
          } catch (Exception e) {
          }
  
          new Thread(null, null, "MyThread", 1 << 25)  //the last parameter is stack size desired.
          {
              public void run() {
                  try {
                      double s = System.currentTimeMillis();
                      MainCode();
                      //System.out.println(("\nExecution Time : " + ((double) System.currentTimeMillis() - s) / 1000) + " s");
                      pw.flush();
                      pw.close();
                  } catch (Exception e) {
                      e.printStackTrace();
                      System.exit(1);
                  }
              }
          }.start();
      }
  }