Percolation Simulation - Part 2

Percolation simulations are easy!

Part 2

Part 1 - Part 2 - Part 3

For this part we are going to give our "rock" some impermeable strata. To do this we will add stripes of zero going diagonally across the array. In a later version we will introduce more complex random seeds for creating the impermeable rock, but for now, we will just use the modulus of 5 to give us some nice stripes.

Once we have done that, we will write some code that will iterate through the array and create the clusters. Once the clusters have been created we will count how many clusters were created and how many cells each cluster consists of.

And finally we will output all this useful info to the screen so the user can get draw conclusions from the simulation run.

Some additional notes:
The action of percolation is done by looking at the array cells above, below, left and right of the current cell and if the value in the cells around the current cell is greater than the one in the current cell, make the value of the current cell the same as that higher value.
We do not want the process to run away if it cant complete so we add a maximum number of iterations equal to the WIDTH multiplied by the HEIGHT.
Because there is no point keeping the run going once all the possible clusters have been found we abort the iteration if no changes are made in one complete pass of the whole array.
We use a hash table to store the cluster counts.

The Rust code for part 2

use std::collections::HashMap;

fn print_array(array:&Vec>, height: usize, width: usize){
    //function to print out the array to the teminal
        for i in 0..height{
            for j in 0..width{
                print!("{:0>3} ",array[i][j]);
            }
            println!("");
        }
    // end print_array function
    }

// Function to count clusters
fn count_clusters(array:&Vec>, height: usize, width: usize) -> HashMap {
    let mut clusters = HashMap::new();

    for i in 0..height{
        for j in 0..width{
            if array[i][j] > 0 {
                *clusters.entry(array[i][j]).or_insert(0) += 1;
            }
        }
    }
    clusters
//end count_cluster function
}

// Function to sort clusters
fn sort_clusters(clusters: &HashMap) -> Vec<(usize, usize)> {
    let mut sorted_clusters: Vec<_> = clusters.iter().collect();
    sorted_clusters.sort_by(|a, b| b.1.cmp(a.1));
    sorted_clusters.into_iter().map(|(&key, &value)| (key, value)).collect()
//end sort_cluster function
}

   
fn main() {
//define array, constants and variables
	const WIDTH: usize = 24;
	const HEIGHT: usize  = 16;
	const N: usize = WIDTH * HEIGHT;
	let mut n = 0;
	let mut change:usize = 0;
	let mut loops:usize = 0;
   
//define array and populat with zeros
	let mut array = vec![vec![0; WIDTH]; HEIGHT];
   
//populate array with consecutive numbers where 0 is rock and give it a rock boarder
	for i in 1..HEIGHT-1{
		for j in 1..WIDTH-1{
			if ((i*HEIGHT)+j)%5>0{
				array[i][j]=(i*HEIGHT)+j;
			}
		}
	}
   
//print array
	print_array(&array, HEIGHT, WIDTH);
   
   
//perculate array
	while n < N {
		for i in 1..HEIGHT-1{
			for j in 1..WIDTH-1{
				if array[i][j] > 0{
					if array[i][j-1]>array[i][j] {array[i][j]=array[i][j-1];change+=1;}
					if array[i][j+1]>array[i][j] {array[i][j]=array[i][j+1];change+=1;}
					if array[i-1][j]>array[i][j] {array[i][j]=array[i-1][j];change+=1;}
					if array[i+1][j]>array[i][j] {array[i][j]=array[i+1][j];change+=1;}
				}
			}
		}
		loops+=1;
		if change > 0 {  
			n+=1;
			change = 0;
		} else {
			n = N;
		}
	}
   
//print array
	println!("");
	print_array(&array, HEIGHT, WIDTH);
	println!("");

//count the clusters
	let clusters = count_clusters(&array, HEIGHT, WIDTH);
	let sorted_clusters = sort_clusters(&clusters);
	for (cluster, size) in sorted_clusters.iter() {
		println!("Cluster {:0>3} size: {}", cluster, size);
	}
	println!("");
	println!("Total clusters: {}", clusters.len());
	println!("");
	println!("Percolation completed in: {} loops (Max loops {})", loops, N);
//end of program
}
   
                

The code output

me@pi:~/rust/percolate-part2$ cargo run
Compiling percolate-part2 v0.1.0 (/home/ubuntu/rust/percolate-part2)
Finished dev [unoptimized + debuginfo] target(s) in 0.81s
Running `target/debug/percolate-part2`
000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
000 017 018 019 000 021 022 023 024 000 026 027 028 029 000 031 032 033 034 000 036 037 038 000
000 033 034 000 036 037 038 039 000 041 042 043 044 000 046 047 048 049 000 051 052 053 054 000
000 049 000 051 052 053 054 000 056 057 058 059 000 061 062 063 064 000 066 067 068 069 000 000
000 000 066 067 068 069 000 071 072 073 074 000 076 077 078 079 000 081 082 083 084 000 086 000
000 081 082 083 084 000 086 087 088 089 000 091 092 093 094 000 096 097 098 099 000 101 102 000
000 097 098 099 000 101 102 103 104 000 106 107 108 109 000 111 112 113 114 000 116 117 118 000
000 113 114 000 116 117 118 119 000 121 122 123 124 000 126 127 128 129 000 131 132 133 134 000
000 129 000 131 132 133 134 000 136 137 138 139 000 141 142 143 144 000 146 147 148 149 000 000
000 000 146 147 148 149 000 151 152 153 154 000 156 157 158 159 000 161 162 163 164 000 166 000
000 161 162 163 164 000 166 167 168 169 000 171 172 173 174 000 176 177 178 179 000 181 182 000
000 177 178 179 000 181 182 183 184 000 186 187 188 189 000 191 192 193 194 000 196 197 198 000
000 193 194 000 196 197 198 199 000 201 202 203 204 000 206 207 208 209 000 211 212 213 214 000
000 209 000 211 212 213 214 000 216 217 218 219 000 221 222 223 224 000 226 227 228 229 000 000
000 000 226 227 228 229 000 231 232 233 234 000 236 237 238 239 000 241 242 243 244 000 246 000
000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000

000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
000 049 049 049 000 129 129 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 000
000 049 049 000 129 129 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000
000 049 000 129 129 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 000
000 000 129 129 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 000
000 129 129 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 000
000 129 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 000
000 129 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000
000 129 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 000
000 000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 244 000
000 209 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 244 244 000
000 209 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 244 244 244 000
000 209 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 244 244 244 244 000
000 209 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 244 244 244 244 000 000
000 000 229 229 229 229 000 234 234 234 234 000 239 239 239 239 000 244 244 244 244 000 246 000
000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000

Cluster 229 size: 56
Cluster 234 size: 55
Cluster 209 size: 46
Cluster 239 size: 38
Cluster 129 size: 26
Cluster 244 size: 18
Cluster 049 size: 6
Cluster 246 size: 1

Total clusters: 8

Percolation completed in: 14 loops (Max loops 384)
me@pi:~/rust/percolate-part2$
                

Mission Accomplished

And there we have it, step two complete, you now have impermeable strata in you rock, you can identify clusters and say how big each cluster is. We still can not actually identify percolation

Part 1 - Part 2 - Part 3