function fillWithSquares(cols, rows) {
const maxSize = Math.min(cols, rows) - 1;
const pick = probabilityPick(d3.range(1, maxSize + 1).map((n) => [n, 1]));
const cells = [];
const occupied = [];
for (let row = 0; row < rows; row++) {
occupied[row] = [];
for (let col = 0; col < cols; col++) {
cells.push({ col, row });
occupied[row][col] = false;
}
}
d3.shuffle(cells);
const squares = [];
const fit = (size) => {
for (let icell = 0; icell < cells.length; icell++) {
const { row, col } = cells[icell];
if (col + size <= cols && row + size <= rows) {
let ok = true;
for (let nc = 0; ok && nc < size; nc++) {
for (let nr = 0; ok && nr < size; nr++) {
if (occupied[row + nr][col + nc]) ok = false;
}
}
if (ok) {
for (let nc = 0; ok && nc < size; nc++) {
for (let nr = 0; ok && nr < size; nr++) {
occupied[row + nr][col + nc] = true;
}
}
squares.push({ row, col, size });
for (let k = cells.length - 1; k >= 0; k--) {
const { col, row } = cells[k];
if (occupied[row][col]) cells.splice(k, 1);
}
return true;
}
}
}
return false;
};
let tries = (rows * cols) ** 2;
while (tries-- > 0) {
const size = pick();
if (fit(size) && cells.length == 0) break;
}
return squares;
}