Skip to content

LAMBDA idea: GRIDSHAPE #83

@jimmytacks

Description

@jimmytacks

Origin

Synced from Notion: LAMBDA: GRIDSHAPE

Content

Problem

GRIDAREA (see sibling idea) extracts rectangular neighborhoods from a grid. But many eSports cases need non-rectangular shapes — a diamond (Manhattan distance ≤ N), a cross/plus pattern, a ring (perimeter only), or an arbitrary custom shape. Currently there's no clean way to extract values matching an irregular pattern centered on a cell. You'd have to hand-build the coordinates each time.

Proposed LAMBDA

=GRIDSHAPE(center, grid, mask)

Extracts values from grid at positions defined by a binary mask array centered on center. The mask is a 2D array of 0s and 1s describing which cells relative to the center should be included. Automatically handles edge clamping — mask cells that would fall outside the grid are ignored.

Parameters

Parameter Required Description
center Yes Cell reference — the center of the shape
grid Yes The full grid range
mask Yes A 2D array of 0s and 1s. The center element of the mask aligns with center. 1 = include this cell, 0 = exclude. Must have odd rows and odd columns so there is a true center.

Returns

A 2D array the same dimensions as mask, containing grid values where mask=1, and 0 (or empty) where mask=0. Positions that fall outside the grid boundary are treated as 0 regardless of mask value.

Example

Diamond (Manhattan distance ≤ 1):

mask = {0,1,0; 1,1,1; 0,1,0}
=SUM(GRIDSHAPE(D4, A1:Z100, mask))  → sum of D4 + its 4 cardinal neighbors

Plus/cross (arm length 2):

mask = {0,0,1,0,0; 0,0,1,0,0; 1,1,1,1,1; 0,0,1,0,0; 0,0,1,0,0}

Ring (3×3 perimeter, excluding center):

mask = {1,1,1; 1,0,1; 1,1,1}
=SUM(GRIDSHAPE(D4, grid, mask))  → sum of 8 neighbors, excluding center

Knight's move neighborhood:

mask = {0,1,0,1,0; 1,0,0,0,1; 0,0,0,0,0; 1,0,0,0,1; 0,1,0,1,0}

Notes

  • Approach: Compute the offset of each mask cell relative to the mask center. For each mask=1 position, calculate the target row/col in the grid. If the target is within grid bounds, extract the value; otherwise return 0. Could use MAP over the mask with INDEX into the grid.
  • Formula sketch:
=LAMBDA(center, grid, mask,
  LET(
    mr, ROWS(mask), mc, COLUMNS(mask),
    hmr, INT(mr/2), hmc, INT(mc/2),
    gR1, ROW(grid), gC1, COLUMN(grid),
    gR2, gR1+ROWS(grid)-1, gC2, gC1+COLUMNS(grid)-1,
    cR, ROW(center), cC, COLUMN(center),
    rIdx, SEQUENCE(mr,,1)-hmr-1, cIdx, SEQUENCE(,mc,1)-hmc-1,
    tR, cR+rIdx, tC, cC+cIdx,
    inBounds, (tR>=gR1)*(tR<=gR2)*(tC>=gC1)*(tC<=gC2),
    MAP(SEQUENCE(mr), SEQUENCE(,mc), LAMBDA(r,c,
      LET(m, INDEX(mask,r,c), ib, INDEX(inBounds,r,c),
        IF(m*ib, INDEX(grid, INDEX(tR,r)-gR1+1, INDEX(tC,,c)-gC1+1), 0))))
  ))
  • Relation to existing LAMBDAs: Natural companion to GRIDAREA (rectangular extraction) and KNIGHTDELTAS (provides the delta pattern for knight moves). The KNIGHTDELTAS array could be converted to a mask for use with GRIDSHAPE.
  • Design consideration: Should the return be the full masked grid (with 0s) or a flat list of just the included values? The full grid preserves spatial structure (useful for further grid operations); a flat list is better for simple aggregation. Could offer both via an optional parameter, or just return the full grid since the user can always TOCOL+filter.
  • Pre-built mask helpers: Consider companion LAMBDAs like DIAMONDMASK(radius), CROSSMASK(arm), RINGMASK(size) that generate common mask patterns.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or improvementlambda-ideaLAMBDA function idea for the backlogstatus: backlogNot yet started

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions