Home # fifteen

values
A visualization of the famous Fifteen puzzle, where the hash of the input is used to move the tiles around.

## 🔗 Layout

A lot of these pieces work on canvases of all sizes and shapes (as long as they’re rectangular). Many pieces can reasonably centered in a “square” based on the minimum of the width and height of the canvas, but for this piece I wanted to intelligently lay out the individual bits.
Given a width, height, and number of things, attempt to product an aesthetically-pleasing layout as defined by:
• The number of rows
• The number of columns
• The size of each item
• The space between each item
function computeIdealLayout(w, h, grids) {
const idealNegativeSpace = (w * h) / 2
let bestLayout = {
negativeSpace: Infinity,
}

for (
let columns = 1;
columns < grids.length;
columns++
) {
for (
let puzzleSize = 8;
puzzleSize < 200;
puzzleSize += 4
) {
for (
let padding = puzzleSize / 4;
) {
let rows = Math.ceil(
grids.length / columns
)
let layoutWidth =
columns * puzzleSize +
let layoutHeight =
rows * puzzleSize +

// Doesn't fit, continue
if (
layoutWidth > w ||
layoutHeight > h
) {
continue
}

const negativeSpace =
// Size of the canvas
w * h -
// Subtract the area of the puzzles
puzzleSize *
puzzleSize *
columns *
rows

if (
Math.abs(
idealNegativeSpace -
negativeSpace
) <
Math.abs(
idealNegativeSpace -
bestLayout.negativeSpace
)
) {
bestLayout = {
negativeSpace,
columns,
rows,
layoutWidth,
layoutHeight,
}
We then pick the candidate whose whitespace is closest to 1/2 of the entire area of the canvas. This can be tweaked as we see fit (see idealNegativeSpace).