Start by setting up the snake partition

nproc <- 4
nfile <- 16
nrep <- ceiling(nfile / nproc / 2)
snakeseq <- rep(c(seq(1,nproc), seq(nproc,1)), nrep)[1:nfile]

Now a function to generate file sizes randomly, perform the partition, and report the total size assigned to each process.

partition <- function(random=FALSE) {
    sizes <- runif(nfile, 5, 20)
    if(!random) {
        sizes <- sort(sizes, decreasing=TRUE)
    }
    sapply(seq(1,nproc), function(i) {
        sum(sizes[snakeseq==i])
    })
}

This function calculates the Gini index of the assignments

gini <- function(sizes) {
    meansize <- mean(sizes)
    n <- length(sizes)
    combos <- expand.grid(sizes, sizes)
    num <- sum(abs(combos[[1]] - combos[[2]]))
    num / (2*n*n*meansize)
}

Now compute a bunch of them and get the distribution of Gini coefficients. Do the same for random values.

gsnake <- sapply(seq(1,250), function(i) {
    gini(partition())
})
grandom <- sapply(seq(1,250), function(i) {
    gini(partition(TRUE))
})

Distribution of Gini coefficients for the size partitions.

library(ggplot2)
pltdata <- data.frame(snake=gsnake, random=grandom)
ggplot(data=pltdata) + 
    geom_density(mapping=aes(x=snake, color='snake')) + 
    geom_density(mapping=aes(x=random, color='random')) +
    xlab('Gini coefficient of distribution') +
    ggthemes::theme_solarized_2(light=FALSE) + 
    ggthemes::scale_color_solarized()

cat('Random partition\n')
Random partition
mean(grandom)
[1] 0.0751094
quantile(grandom, c(0.025, 0.975))
      2.5%      97.5% 
0.02214389 0.14303694 
cat('Snake partition\n')
Snake partition
mean(gsnake)
[1] 0.01267433
quantile(gsnake, c(0.025, 0.975))
       2.5%       97.5% 
0.002984605 0.027710777 
LS0tCnRpdGxlOiAiU25ha2UgcGFydGl0aW9uIHBlcmZvcm1hbmNlIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpTdGFydCBieSBzZXR0aW5nIHVwIHRoZSBzbmFrZSBwYXJ0aXRpb24KCmBgYHtyIGdlbnNuYWtlfQpucHJvYyA8LSA0Cm5maWxlIDwtIDE2Cm5yZXAgPC0gY2VpbGluZyhuZmlsZSAvIG5wcm9jIC8gMikKc25ha2VzZXEgPC0gcmVwKGMoc2VxKDEsbnByb2MpLCBzZXEobnByb2MsMSkpLCBucmVwKVsxOm5maWxlXQpgYGAKCk5vdyBhIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGZpbGUgc2l6ZXMgcmFuZG9tbHksIHBlcmZvcm0gdGhlIHBhcnRpdGlvbiwgYW5kCnJlcG9ydCB0aGUgdG90YWwgc2l6ZSBhc3NpZ25lZCB0byBlYWNoIHByb2Nlc3MuCmBgYHtyIHBhcnRpdGlvbn0KcGFydGl0aW9uIDwtIGZ1bmN0aW9uKHJhbmRvbT1GQUxTRSkgewogICAgc2l6ZXMgPC0gcnVuaWYobmZpbGUsIDUsIDIwKQogICAgaWYoIXJhbmRvbSkgewogICAgICAgIHNpemVzIDwtIHNvcnQoc2l6ZXMsIGRlY3JlYXNpbmc9VFJVRSkKICAgIH0KICAgIHNhcHBseShzZXEoMSxucHJvYyksIGZ1bmN0aW9uKGkpIHsKICAgICAgICBzdW0oc2l6ZXNbc25ha2VzZXE9PWldKQogICAgfSkKfQpgYGAKClRoaXMgZnVuY3Rpb24gY2FsY3VsYXRlcyB0aGUgR2luaSBpbmRleCBvZiB0aGUgYXNzaWdubWVudHMKYGBge3IgZ2luaX0KZ2luaSA8LSBmdW5jdGlvbihzaXplcykgewogICAgbWVhbnNpemUgPC0gbWVhbihzaXplcykKICAgIG4gPC0gbGVuZ3RoKHNpemVzKQogICAgY29tYm9zIDwtIGV4cGFuZC5ncmlkKHNpemVzLCBzaXplcykKICAgIG51bSA8LSBzdW0oYWJzKGNvbWJvc1tbMV1dIC0gY29tYm9zW1syXV0pKQogICAgbnVtIC8gKDIqbipuKm1lYW5zaXplKQp9CmBgYAoKTm93IGNvbXB1dGUgYSBidW5jaCBvZiB0aGVtIGFuZCBnZXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBHaW5pIGNvZWZmaWNpZW50cy4gIERvIAp0aGUgc2FtZSBmb3IgcmFuZG9tIHZhbHVlcy4KCmBgYHtyIGNvbGxlY3RzdGF0c30KZ3NuYWtlIDwtIHNhcHBseShzZXEoMSwyNTApLCBmdW5jdGlvbihpKSB7CiAgICBnaW5pKHBhcnRpdGlvbigpKQp9KQoKZ3JhbmRvbSA8LSBzYXBwbHkoc2VxKDEsMjUwKSwgZnVuY3Rpb24oaSkgewogICAgZ2luaShwYXJ0aXRpb24oVFJVRSkpCn0pCmBgYAoKRGlzdHJpYnV0aW9uIG9mIEdpbmkgY29lZmZpY2llbnRzIGZvciB0aGUgc2l6ZSBwYXJ0aXRpb25zLgpgYGB7ciBwbG90fQpsaWJyYXJ5KGdncGxvdDIpCnBsdGRhdGEgPC0gZGF0YS5mcmFtZShzbmFrZT1nc25ha2UsIHJhbmRvbT1ncmFuZG9tKQpnZ3Bsb3QoZGF0YT1wbHRkYXRhKSArIAogICAgZ2VvbV9kZW5zaXR5KG1hcHBpbmc9YWVzKHg9c25ha2UsIGNvbG9yPSdzbmFrZScpKSArIAogICAgZ2VvbV9kZW5zaXR5KG1hcHBpbmc9YWVzKHg9cmFuZG9tLCBjb2xvcj0ncmFuZG9tJykpICsKICAgIHhsYWIoJ0dpbmkgY29lZmZpY2llbnQgb2YgZGlzdHJpYnV0aW9uJykgKwogICAgZ2d0aGVtZXM6OnRoZW1lX3NvbGFyaXplZF8yKGxpZ2h0PUZBTFNFKSArIAogICAgZ2d0aGVtZXM6OnNjYWxlX2NvbG9yX3NvbGFyaXplZCgpCmBgYAoKYGBge3Igc3RhdHN9CmNhdCgnUmFuZG9tIHBhcnRpdGlvblxuJykKbWVhbihncmFuZG9tKQpxdWFudGlsZShncmFuZG9tLCBjKDAuMDI1LCAwLjk3NSkpCgpjYXQoJ1NuYWtlIHBhcnRpdGlvblxuJykKbWVhbihnc25ha2UpCnF1YW50aWxlKGdzbmFrZSwgYygwLjAyNSwgMC45NzUpKQpgYGAK