code: import java.awt.Point;
  import java.util.*;
  
  public class ZhangSuen {
  
      final static String[] image = {
          "                                                          ",
          " #################                   #############        ",
          " ##################               ################        ",
          " ###################            ##################        ",
          " ########     #######          ###################        ",
          "   ######     #######         #######       ######        ",
          "   ######     #######        #######                      ",
          "   #################         #######                      ",
          "   ################          #######                      ",
          "   #################         #######                      ",
          "   ######     #######        #######                      ",
          "   ######     #######        #######                      ",
          "   ######     #######         #######       ######        ",
          " ########     #######          ###################        ",
          " ########     ####### ######    ################## ###### ",
          " ########     ####### ######      ################ ###### ",
          " ########     ####### ######         ############# ###### ",
          "                                                          "};
  
      final static int[][] nbrs = {{0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1},
          {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}};
  
      final static int[][][] nbrGroups = {{{0, 2, 4}, {2, 4, 6}}, {{0, 2, 6},
          {0, 4, 6}}};
  
      static List<Point> toWhite = new ArrayList<>();
      static char[][] grid;
  
      public static void main(String[] args) {
          grid = new char[image.length][];
          for (int r = 0; r < image.length; r++)
              grid[r] = image[r].toCharArray();
  
          thinImage();
      }
  
      static void thinImage() {
          boolean firstStep = false;
          boolean hasChanged;
  
          do {
              hasChanged = false;
              firstStep = !firstStep;
  
              for (int r = 1; r < grid.length - 1; r++) {
                  for (int c = 1; c < grid[0].length - 1; c++) {
  
                      if (grid[r][c] != '#')
                          continue;
  
                      int nn = numNeighbors(r, c);
                      if (nn < 2 || nn > 6)
                          continue;
  
                      if (numTransitions(r, c) != 1)
                          continue;
  
                      if (!atLeastOneIsWhite(r, c, firstStep ? 0 : 1))
                          continue;
  
                      toWhite.add(new Point(c, r));
                      hasChanged = true;
                  }
              }
  
              for (Point p : toWhite)
                  grid[p.y][p.x] = ' ';
              toWhite.clear();
  
          } while (firstStep || hasChanged);
  
          printResult();
      }
  
      static int numNeighbors(int r, int c) {
          int count = 0;
          for (int i = 0; i < nbrs.length - 1; i++)
              if (grid[r + nbrs[i][1]][c + nbrs[i][0]] == '#')
                  count++;
          return count;
      }
  
      static int numTransitions(int r, int c) {
          int count = 0;
          for (int i = 0; i < nbrs.length - 1; i++)
              if (grid[r + nbrs[i][1]][c + nbrs[i][0]] == ' ') {
                  if (grid[r + nbrs[i + 1][1]][c + nbrs[i + 1][0]] == '#')
                      count++;
              }
          return count;
      }
  
      static boolean atLeastOneIsWhite(int r, int c, int step) {
          int count = 0;
          int[][] group = nbrGroups[step];
          for (int i = 0; i < 2; i++)
              for (int j = 0; j < group[i].length; j++) {
                  int[] nbr = nbrs[group[i][j]];
                  if (grid[r + nbr[1]][c + nbr[0]] == ' ') {
                      count++;
                      break;
                  }
              }
          return count > 1;
      }
  
      static void printResult() {
          for (char[] row : grid)
              System.out.println(row);
      }
  }
  