Magic Collage

Pick a canvas shape and the layout snaps to it. Every arrangement of every photo is searched by one dynamic program written in Go, running here in your browser.

Loading the Go engine (3 MB)…
smallest photo – of the canvas cropped – – layouts searched in –

Under the hood

The dynamic program
-- one layout step (the functor)
F X  = Leaf photo | Split cut X X

-- how photos shrink (projections)
coalg  {photos} → Leaf p
                | Split H A B
                | Split V A B

-- aspect monoid on a cut
H : a = a₁ + a₂
V : 1/a = 1/a₁ + 1/a₂

-- how answers combine (semiring)
alg    Lift(Count × TopK₃)
  Count  (+, ×)     layouts
  TopK₃  (max, min) smallest photo

-- dynamorphism = DP, memoised
rec  = ⊕ ∘ map(alg ∘ F rec) ∘ coalg
state = (photo subset, aspect bucket)

Resizing the canvas never re-solves. The answer is a vector indexed by aspect ratio, so a new canvas shape is a lookup.

Laws, checked live in your browser
LawCountTopK₃Count × TopK₃
Waiting for the engine…
Checking the DP against brute force…