Q: After the system has percolated, my PercolationVisualizer colors in light blue all sites connected to open sites on the bottom (in addition to those connected to open sites on the top). Is this “backwash” acceptable?
A: No, this is likely a bug in Percolation. It is only a minor deduction (because it impacts only the visualizer and not the experiment to estimate the percolation threshold), so don’t go crazy trying to get this detail. However, many students consider this to be the most challenging and creative part of the assignment (especially if you limit yourself to one union–find object).
/** A full site is an open site that can be connected to an open site in the * top row via a chain of neighboring (left, right, up, down) open sites. */ publicbooleanisFull(int row, int col) { validate(row, col); return connectTop[uf.find(xyTo1D(row, col))]; }
/** Introduce 2 virtual sites (and connections to top and bottom). * Percolates if virtual top site is connected to virtual bottom site. */ publicbooleanpercolates() { return percolateFlag; }
privateintxyTo1D(int row, int col) { validate(row, col); return size * (row - 1) + col - 1; }
publicclassPercolation { privateboolean[] grid; privateboolean[] connectBottom; private WeightedQuickUnionUF uf; privatefinalint size; privatefinalint virtualTop; privateint numberOfOpenSites; // creates n-by-n grid, with all sites initially blocked publicPercolation(int n) { validate(n); grid = newboolean[n*n]; // last 1 use as virtualTop connectBottom = newboolean[n*n+1]; uf = newWeightedQuickUnionUF(n*n+1); size = n; virtualTop = n*n; numberOfOpenSites = 0; } // opens the site (row, col) if it is not open already publicvoidopen(int row, int col) { validate(row, col); intcenter= xyTo1D(row, col); // if (row, col) is already opened if (grid[center]) { return ; } // else not opened grid[center] = true; numberOfOpenSites++; intabove= xyTo1D(row-1, col); intbelow= xyTo1D(row+1, col); intleft= xyTo1D(row, col-1); intright= xyTo1D(row, col+1); // if (row, col) is on the bottom, set connectBottom[] true if (row == size) { connectBottom[center] = true; } // judge if exist a union operation that union a tree whose root has connectBottom[root] == true booleanbottomFlag=false; // check above, (row - 1, col) if (row > 1 && grid[above]) { if (connectBottom[uf.find(center)] || connectBottom[uf.find(above)]) { bottomFlag = true; } uf.union(center, above); } // check below, (row + 1, col) if (row < size && grid[below]) { if (connectBottom[uf.find(center)] || connectBottom[uf.find(below)]) { bottomFlag = true; } uf.union(center, below); } // check left, (row, col - 1) if (col > 1 && grid[left]) { if (connectBottom[uf.find(center)] || connectBottom[uf.find(left)]) { bottomFlag = true; } uf.union(center, left); } // check right, (row, col + 1) if (col < size && grid[right]) { if (connectBottom[uf.find(center)] || connectBottom[uf.find(right)]) { bottomFlag = true; } uf.union(center, right); } // if row == 1, should have one more union: union with virtual top if (row == 1) { if (connectBottom[uf.find(center)] || connectBottom[uf.find(virtualTop)]) { bottomFlag = true; } uf.union(center, virtualTop); } // if bottom Flag is true, then set connectBottom[root of center] to true after all union ops if (bottomFlag) { connectBottom[uf.find(center)] = true; } } // is the site (row, col) open? publicbooleanisOpen(int row, int col) { validate(row, col); return grid[xyTo1D(row, col)]; } // is the site (row, col) full? publicbooleanisFull(int row, int col) { validate(row, col); return isOpen(row, col) && uf.connected(xyTo1D(row, col), virtualTop); } // returns the number of open sites publicintnumberOfOpenSites() { return numberOfOpenSites; } // does the system percolate? publicbooleanpercolates() { return connectBottom[uf.find(virtualTop)]; } // mapping 2D coordinates to 1D coordinates privateintxyTo1D(int row, int col) { return (row - 1)*size + (col - 1); } privatevoidvalidate(int n) { if (n <= 0) { thrownewIllegalArgumentException("ERROR: grid size n must be greater than 0"); } } privatevoidvalidate(int row, int col) { if (row < 1 || row > size || col < 1 || col > size) { thrownewIllegalArgumentException("ERROR: given (row, col) is outside prescribed range"); } } // test client (optional) publicstaticvoidmain(String[] args) { } }