Random walks are, well, very random. At any point in time, they can chose to take a step to the left, to the right, front or back.
The path of somebody walking a random walk of a 5000 steps on a plane looks like this, with the starting point being the blue dot, and the end of the path being the red dot:

Pretty chaotic.

But when you let them, these random walks will actually create beautiful, structured, patterns for you.

The code below is inspired by a book of Mark Buchanan, called Ubiquity. In this book it is shown that random events are not necessarily just the unstructured, chaotic, drunken trails, but can pretty amazingly lead to structured, beautiful patterns. This is officially called: “Diffusion-limited aggregation”.

What it is, step by step:

  1. A little particle sits, all by itself, in the middle of a large empty space.
  2. Another particle walks by. Following a random path.
  3. It keeps on walking this way. Until they meet.
  4. When they hit, the new particle sticks around, and does not move anymore.
  5. Then another particle walks in…and onother one, and another one.

When about eight thousand particles have found each other this way, the result is quite striking:

Code

To show how this image was generated, some code below:

nr <- 400; # even number of rows
nc <- 400; # even number of columns
n <- 10000; # number of random walk steps
count = 0; # needed for border seed setting
firstwalk = 1; # needed to calculate random walks

for(i in 1:10) {
# ---- create random walk starting at the origin of the matrix [0,0]
    x <- cumsum(sample(c(-1, 0, 1), n, TRUE))
    y <- cumsum(sample(c(-1, 0, 1), n, TRUE))

    # Is this the first walk?
    if(firstwalk==1){
       # randomly choose boundary point to start from
        if (count %% 4 == 0) {xs <- floor(runif(1,1,nr)); ys <- 0}
        if (count %% 4 == 1) {ys <- floor(runif(1,1,nc)); xs <- 0}
        if (count %% 4 == 2) {xs <- floor(runif(1,1,nr)); ys <- nc}
        if (count %% 4 == 3) {ys <- floor(runif(1,1,nr)); xs <- nr}
    } else {
        xs = rw[length(x),][1]; #last x coor of the previous rw
        ys = rw[length(x),][2]; #last y coor of the previous rw
    }
    x <- x+xs
    y <- y+ys

    # ---- Set random walk boundaries to stay confined within matrix
    for(i in 1:n){
        if (x[i] < 0) {x[i:n] <- x[i:n]+1}
        if (x[i] > nr) {x[i:n] <- x[i:n]-1}
        if (y[i] < 0) {y[i:n] <- y[i:n]+1}
        if (y[i] > nc) {y[i:n] <- y[i:n]-1}
        }
    # ---- random walk array:
    rw <- unname(cbind(x,y));
    
    # ---- detect when random walk hits a point of value 1 in m
    s <- unname(which(m==1, arr.ind=TRUE))
    sp <- paste0(s[,1],".",s[,2]);
    rwp <- paste0(rw[,1],".",rw[,2]);
    hit <- which(rwp%in%sp,arr.ind = TRUE)[1] # get first hit
    
    # act if there is a hit:
    if (!is.na(hit)) { 
        # set value = 1 at location of last step of rw prior to hitting
        m[rw[hit-1,1],rw[hit-1,2]] = 1;
        firstwalk = 1;
        count <- count + 1;
        cat("Hit number:", count, "\n")
    } else {
        # no hit: do another walk starting at end of this one
        firstwalk = 0;
    }
    
    # Show the random walks real time:
    par(mar=c(10,10,2,2))
    plot(x,y,xlim=c(0,nr),ylim=c(0,nc),type="l")
    points(x[1],y[1],"pch"=19,col = "blue") #begin point
    points(x[length(x)],y[length(y)],"pch"=19,col = "red") #end point
    points(s,"pch"=".",col = "gray") #matrix m values 1
} # end of for loop

## Hit number: 1

## Hit number: 2

## Hit number: 3

The current day and time is Tue Mar 07 11:07:45 2017