user
Given an 

M
×
N
{\displaystyle {\displaystyle M\times N}}
 rectangular array of cells numbered 

c
e
l
l
[
0..
M
−
1
,
0..
N
−
1
]
{\displaystyle {\displaystyle \mathrm {cell} [0..M-1,0..N-1]}}
, assume 

M
{\displaystyle {\displaystyle M}}
 is horizontal and 

N
{\displaystyle {\displaystyle N}}
 is downwards. Each 

c
e
l
l
[
m
,
n
]
{\displaystyle {\displaystyle \mathrm {cell} [m,n]}}
 is bounded by (horizontal) walls 

h
w
a
l
l
[
m
,
n
]
{\displaystyle {\displaystyle \mathrm {hwall} [m,n]}}
 and 

h
w
a
l
l
[
m
+
1
,
n
]
{\displaystyle {\displaystyle \mathrm {hwall} [m+1,n]}}
; (vertical) walls 

v
w
a
l
l
[
m
,
n
]
{\displaystyle {\displaystyle \mathrm {vwall} [m,n]}}
 and 

v
w
a
l
l
[
m
,
n
+
1
]
{\displaystyle {\displaystyle \mathrm {vwall} [m,n+1]}}

Assume that the probability of any wall being present is a constant 

p
{\displaystyle {\displaystyle p}}
 where

:   0.0
    ≤
    p
    ≤
    1.0
    {\displaystyle {\displaystyle 0.0\leq p\leq 1.0}}

Except for the outer horizontal walls at 

m
=
0
{\displaystyle {\displaystyle m=0}}
 and 

m
=
M
{\displaystyle {\displaystyle m=M}}
 which are always present.

The task

Simulate pouring a fluid onto the top surface (

n
=
0
{\displaystyle {\displaystyle n=0}}
) where the fluid will enter any empty cell it is adjacent to if there is no wall between where it currently is and the cell on the other side of the (missing) wall.

The fluid does not move beyond the horizontal constraints of the grid.

The fluid may move “up” within the confines of the grid of cells. If the fluid reaches a bottom cell that has a missing bottom wall then the fluid can be said to 'drip' out the bottom at that point.

Given 

p
{\displaystyle {\displaystyle p}}
 repeat the percolation 

t
{\displaystyle {\displaystyle t}}
 times to estimate the proportion of times that the fluid can percolate to the bottom for any given 

p
{\displaystyle {\displaystyle p}}
.

Show how the probability of percolating through the random grid changes with 

p
{\displaystyle {\displaystyle p}}
 going from 

0.0
{\displaystyle {\displaystyle 0.0}}
 to 

1.0
{\displaystyle {\displaystyle 1.0}}
 in 

0.1
{\displaystyle {\displaystyle 0.1}}
 increments and with the number of repetitions to estimate the fraction at any given 

p
{\displaystyle {\displaystyle p}}
 as 

t
=
100
{\displaystyle {\displaystyle t=100}}
.

Use an 

M
=
10
,
N
=
10
{\displaystyle {\displaystyle M=10,N=10}}
 grid of cells for all cases.

Optionally depict fluid successfully percolating through a grid graphically.

Show all output on this page.
assistant
(formerly Perl 6)

**Works with**: Rakudo version 2017.02

Starts "filling" from the top left. Fluid flow favours directions in Down, Left, Right, Up order. I interpreted p to be porosity, so small p mean low permeability, large p means high permeability.

```
my @bond;
my $grid = 10;
my $geom = $grid - 1;
my $water = '▒';

enum Direction <DeadEnd Up Right Down Left>;

say 'Sample percolation at .6';
percolate .6;
.join.say for @bond;
say "\n";

my $tests = 100;
say "Doing $tests trials at each porosity:";
for .1, .2 ... 1 -> $p {
    printf "p = %0.1f: %0.2f\n", $p, (sum percolate($p) xx $tests) / $tests
}

sub percolate ( $prob ) {
    generate $prob;
    my @stack;
    my $current = [1;0];
    $current.&fill;

    loop {
        if my $dir = direction( $current ) {
            @stack.push: $current;
            $current = move $dir, $current
        }
        else {
            return False unless @stack;
            $current = @stack.pop
        }
        return True if $current[1] == +@bond - 1
    }

    sub direction( [$x, $y] ) {
        ( Down  if @bond[$y + 1][$x].contains: ' ' ) ||
        ( Left  if @bond[$y][$x - 1].contains: ' ' ) ||
        ( Right if @bond[$y][$x + 1].contains: ' ' ) ||
        ( Up    if @bond[$y - 1][$x].defined && @bond[$y - 1][$x].contains: ' ' ) ||
        DeadEnd
    }

    sub move ( $dir, @cur ) {
        my ( $x, $y ) = @cur;
        given $dir {
            when Up    { [$x,--$y].&fill xx 2 }
            when Down  { [$x,++$y].&fill xx 2 }
            when Left  { [--$x,$y].&fill xx 2 }
            when Right { [++$x,$y].&fill xx 2 }
        }
        [$x, $y]
    }

    sub fill ( [$x, $y] ) { @bond[$y;$x].=subst(' ', $water, :g) }
}

sub generate ( $prob = .5 ) {
    @bond = ();
    my $sp = '   ';
    append @bond, [flat '│', ($sp, ' ') xx $geom, $sp, '│'],
                  [flat '├', (h(), '┬') xx $geom, h(), '┤'];
    append @bond, [flat '│', ($sp, v()) xx $geom, $sp, '│'],
                  [flat '├', (h(), '┼') xx $geom, h(), '┤'] for ^$geom;
    append @bond, [flat '│', ($sp, v()) xx $geom, $sp, '│'],
                  [flat '├', (h(), '┴') xx $geom, h(), '┤'],
                  [flat '│', ($sp, ' ') xx $geom, $sp, '│'];

    sub h () { rand < $prob ?? $sp !! '───' }
    sub v () { rand < $prob ?? ' ' !! '│'   }
}

```

Output:

```
Sample percolation at .6
│▒▒▒                                    │
├▒▒▒┬   ┬───┬   ┬   ┬   ┬   ┬   ┬───┬   ┤
│▒▒▒▒▒▒▒                │   │           │
├───┼▒▒▒┼   ┼   ┼   ┼   ┼   ┼───┼   ┼   ┤
│▒▒▒▒▒▒▒▒▒▒▒│   │   │   │   │   │       │
├▒▒▒┼───┼▒▒▒┼   ┼───┼   ┼───┼   ┼   ┼   ┤
│▒▒▒│▒▒▒▒▒▒▒▒▒▒▒                │   │   │
├▒▒▒┼───┼───┼▒▒▒┼   ┼   ┼───┼   ┼   ┼   ┤
│▒▒▒│        ▒▒▒│   │   │           │   │
├───┼   ┼   ┼▒▒▒┼───┼   ┼   ┼   ┼   ┼───┤
│           │▒▒▒    │                   │
├   ┼───┼   ┼▒▒▒┼───┼───┼───┼───┼   ┼───┤
│           │▒▒▒│                       │
├───┼   ┼───┼▒▒▒┼───┼───┼───┼───┼   ┼───┤
│▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒        │       │       │
├▒▒▒┼▒▒▒┼───┼▒▒▒┼───┼   ┼───┼   ┼   ┼   ┤
│▒▒▒│▒▒▒▒▒▒▒│▒▒▒▒▒▒▒│                   │
├▒▒▒┼───┼───┼───┼───┼───┼   ┼   ┼   ┼   ┤
│▒▒▒▒▒▒▒    │       │   │               │
├▒▒▒┼▒▒▒┼───┼───┼   ┼───┼───┼   ┼   ┼   ┤
│▒▒▒│▒▒▒    │               │           │
├───┴▒▒▒┴   ┴   ┴   ┴───┴   ┴   ┴   ┴───┤
│    ▒▒▒                                │

Doing 100 trials at each porosity:
p = 0.1: 0.00
p = 0.2: 0.00
p = 0.3: 0.00
p = 0.4: 0.05
p = 0.5: 0.42
p = 0.6: 0.92
p = 0.7: 1.00
p = 0.8: 1.00
p = 0.9: 1.00
p = 1.0: 1.00
```