Distribuir igualmente e randomizar

by Luiz Silva

HTML

<ul>
    <li>C</li>
    <li>C++</li>
    <li>Java</li>
    <li>PHP</li>
    <li>JavaScript</li>
    <li>Lisp</li>
    <li>Scheme</li>
    <li>Haskell</li>
    <li>Lua</li>
    <li>Python</li>
    <li>Ruby</li>
    <li>Delphi</li>
    <li>Cobol</li>
</ul>

CSS

body {    
    margin: 0;   
    padding: 0;
}
ul {
    width: 500px;
    height: 350px;
    border: 1px solid red;
    margin: 0;
    padding: 0;
    text-align: center;
}

li {
    list-style: none;
    margin: 0;
    padding: 0;
    display: inline-block;
    font-size: 2em;
}

JavaScript

function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}
function rand(n) {
    return getRandomInt(-n, n);
}

//calcula tamanhos dos itens para distribuição
var itens = [];
var larguraTotal = 0;
$('li').each(function(i) {
    var $this = $(this);
    larguraTotal += $this.width();
    itens.push({
        item: $this,
        width: $this.width(),
        height: $this.height()
    });
});

//define a quantidade de linhas
var linhas = Math.ceil(Math.sqrt(itens.length));
var larguraMedia = larguraTotal / linhas;
//console.log(linhas, larguraMedia, larguraTotal);

//faz a distribuição dos elementos nas linhas de uma grid imaginária
var grid = [ [] ];
grid[0].largura = 0;
for (var i = 0, larguraConsumida = 0, linha = 0, coluna = 0, proximaQuebra = larguraMedia; i < itens.length; i++) {
    var item = itens[i];
    //quebra a linha, caso mais da metade do elemento ultrapasse a média
    if (larguraConsumida + item.width / 2 > proximaQuebra) {
        linha++;
        grid[linha] = [];
        grid[linha].largura = 0;
        coluna = 0;
        larguraLinha = 0;
        proximaQuebra = larguraMedia * (linha + 1);
    } else {
        coluna++;
    }
    //armazena a largura 
    grid[linha].largura += item.width;
    larguraConsumida += item.width;
    grid[linha].push(item);
    //console.log(item);
}

//coloca os elementos na posição final (uma célula do container)
var container = $('ul');
//a largura da célula (local onde o item deve ser inserido)
var larguraCelula = container.height() / grid.length;
for (var i = 0; i < grid.length; i++) {
    var linha = grid[i];
    //altura da célula (local onde o item deve ser inserido)
    var alturaCelula = container.width() / linha.length;
    //calcula o espaço horizontal que tem para randomizar, isto é, o espaço em branco até onde não enconsta no próximo elemento
    //deve dividir por 2 pela possibilidade do outro elemento também poder se aproximar, mas multiplicando por 0.4...