-
Notifications
You must be signed in to change notification settings - Fork 0
/
Percolation.mine.java
146 lines (107 loc) · 5.39 KB
/
Percolation.mine.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//
// in a grid randomly composed of rock and sand , what percentage of squares need to be permeable for the top to percolate to the bottom?
//
// guessing that maintaining the tree has a higher cost than simply doing a connectivity sweep on a plain 2D array
// alternatively, do floodfill every time a space gets opened, but not actually filling unless we hit more fluid or the top
// XXX the "going back up" thing isn't working
public class Percolation {
private int grid_size;
private int[][] grid;
public Percolation(int N) {
// create an N by N grid, with all sites blocked XXX
// XXX to do the weighted-quick-union thing, probably have to use two arrays, one for open/blocked/conducting and one for the tree structure
this(N, 1.0);
}
public Percolation(int N, double p) {
// p is the chance that any site will be blocked
if(N <= 0) throw new java.lang.IllegalArgumentException();
grid_size = N;
grid = new int[N][];
for(int y = 0; y < N; y++) {
grid[y] = new int[N];
for(int x = 0; x < N; x++) {
grid[y][x] = StdRandom.bernoulli(p) ? 1 : 0;
}
}
}
private void check_coordinates(int y, int x) {
// bounds checking
if(x < 1 || x > grid_size || y < 1 || y > grid_size ) throw new java.lang.IllegalArgumentException();
}
public void open(int y, int x) {
// open site (row y, column x) if it is not open already
check_coordinates(y, x);
grid[y][x] = 0;
}
public boolean isOpen(int y, int x) {
// is site x, y clear?
check_coordinates(y, x);
x--; y--; // 0 based indices
return grid[y][x] == 0 ? true : false;
}
public boolean isFull(int y, int x) {
// is site x, y occupied? or rather, is it not blocked and filled with liquid?
check_coordinates(y, x);
x--; y--; // 0 based indices
return grid[y][x] == 2 ? true : false;
}
public boolean percolates() {
// does the system percolate?
// could use floodfill (on each open top space, iteratively)
// could do a more directed, simplified version of that, line by line, more game of life style
// yeah, let's try that
// this is pretty clearly N^2
// yeah, that's making route finding more attractive
int[] flowing = new int[grid_size];
for(int i = 0; i < grid_size; i++) flowing[i] = 1; // start off with liquid flowing down at every square
line_by_line:
for(int line = 0; line < grid_size; line++) {
// debug
String s = "";
for( int i = 0; i < grid_size; i++ ) {
s = s + ( grid[line][i] == 0 ? " " : "X" );
}
// step 1, remove squares from flowing[] that are blocked in grid[line][] (blocked=1)
// if this leaves no open sites, there's no connectivity XXX
int flowing_squares = 0;
for( int i = 0; i < grid_size; i++ ) {
if( grid[line][i] == 1 ) flowing[i] = 0;
flowing_squares += flowing[i];
}
if( flowing_squares == 0 ) return false;
// step 2, add squares to flowing[] that are open in grid[line][] and adjacent to flowing water in flowing[]
// sweep to the right then sweep to the left
// for( int i = 1; i < grid_size; i++ ) if( flowing[i-1] == 1 && grid[line][i] == 0 ) flowing[i] = 1;
// for( int i = grid_size-2 /* one left of the leftmost element */; i >= 0; i-- ) if( flowing[i+1] == 1 && grid[line][i] == 0 ) flowing[i] = 1;
// step 3, send water back uphill again. freak out and back up if we notice that we've spilled left/right under an open spot above us.
// flowing[] is really non directional with respect to up/down.
boolean have_to_go_back_up = false;
for( int i = 1; i < grid_size; i++ ) if( flowing[i] == 1 && grid[line][i] == 0 ) grid[line][i] = 2; // XXX testing ... argh, no, this will cost us speed!
for( int i = 1; i < grid_size; i++ ) if( flowing[i-1] == 1 && ( grid[line][i] == 0 || grid[line][i] == 2 ) ) {
// spill to the right
if( line > 1 && flowing[i] == 0 && grid[line-1][i] == 0 ) have_to_go_back_up = true;
flowing[i] = 1;
grid[line][i] = 2; // XXX testing
}
for( int i = grid_size-2 /* one left of the leftmost element */; i >= 0; i-- ) if( flowing[i+1] == 1 && ( grid[line][i] == 0 || grid[line][i] == 2 ) ) {
// spill to the left
if( line > 1 && flowing[i] == 0 && grid[line-1][i] == 0 ) have_to_go_back_up = true;
flowing[i] = 1;
grid[line][i] = 2; // XXX testing
}
if( have_to_go_back_up ) { System.out.println("had to go back up"); line--; continue line_by_line; }
// debug, continued
s = s + " ";
for( int i = 0; i < grid_size; i++ ) {
s = s + ( flowing[i] == 0 ? " " : "~" );
}
System.out.println(s);
}
// if we haven't yet aborted due to complete lack of flow across an entire line, then there is flow
return true;
}
public static void main(String[] args) {
Percolation p = new Percolation(50, 0.5);
p.percolates();
}
}