# `solver/greedy/greedy.ts` — deterministic greedy set-cover _(no submodules)_ ## Purpose This module provides the greedy selector that drives the primary covering strategy. `enhancedGreedyCover` picks rectangles from a candidate pool using a deterministic three-key score (covered count, efficiency, centroid proximity). `perIslandCover` runs the same selector independently on each 4-connected island so the algorithm never wastes budget on rectangles that span the transparent gap between two disjoint islands. ## Features - Three-key score: `covered * 1000 + efficiency * 100 + proximity * 10`. The factors are deliberately spaced so a more-covering rect always beats a more-efficient one, and ties are broken by centroid proximity. - Falls back to emitting `1×1` rectangles for any residual uncovered pixels — guarantees the cover is complete even when no candidate intersects the residual. - `perIslandCover` filters the candidate pool per island so the selector never considers a spanning rect; this halves selection work on multi-island colours. ## Usage: Basic ```ts import { dualAxisMaximalRects, enhancedGreedyCover, } from "@suaveplan/emblem-solver/solver"; const candidates = dualAxisMaximalRects(available, rows, cols); const cover = enhancedGreedyCover(candidates, required, cols, rows); ``` ## Usage: Advanced ```ts import { analyseGrid, perIslandCover, dualAxisMaximalRects, } from "@suaveplan/emblem-solver"; const a = analyseGrid(pixels, w, h); const info = a.colourAnalysis.get("255,0,0")!; const candidates = dualAxisMaximalRects(available, h, w); const cover = perIslandCover(info.islands, candidates, w, h); ``` ## API Reference | Symbol | Kind | Description | |---|---|---| | `enhancedGreedyCover(candidates, required, w, h)` | fn | Greedy cover with three-key score | | `perIslandCover(islands, candidates, w, h)` | fn | Independent cover per island | ## Implementation Notes The centroid term is computed against the running set of *uncovered* required pixels, not the original set — this keeps selections clustered even as the residual shrinks. We use a precomputed `maxDist = sqrt(w² + h²)` so the proximity term is normalised to `[0, 1]`; without this, the third tiebreaker could dominate the second on large grids. `perIslandCover` materialises a fresh `boolean[][]` per island; this is acceptable because the typical island count is small (≤ 10 on the upstream fixtures) and the allocation cost is dominated by the cover work inside.