Typorithm · easy

Broadcasting and explicit column alignment

pythonnumpynumerical-computingindependent-practice
Saved on this device
Full lesson · 4 learning steps Open any exercise for focused practice
1

Step 1 of 4 · intro card

Broadcasting and explicit column alignment

0%

Concept and contract

Apply one offset per feature without accidentally treating that vector as one value per observation.

Broadcasting combines compatible shapes by comparing their trailing dimensions. Dimensions are compatible when they are equal or one of them is one; missing leading dimensions behave as size one. This is a shape rule, not a rule about companies or dates. A matrix shaped (observations, features) and a vector shaped (features,) can therefore combine column by column without manually repeating the vector.

The worked contract adds one finite offset per column of a non-empty numerical matrix. It validates the offset length against the feature axis. An equally long vector of observation-level values would require a different explicit shape, typically (observations, 1), and must not be substituted because the example happens to be square.

Mechanism and worked example

The function constructs two float64 arrays, checks rank and alignment, and evaluates data + offsets.

The function constructs two float64 arrays, checks rank and alignment, and evaluates data + offsets. NumPy conceptually expands the smaller shape for the operation without requiring a separately tiled input buffer. The result is still a newly computed matrix. Trace a two-by-three example: each row receives the same three column offsets, and the original row order remains unchanged.

Broadcasting avoids unnecessary repeated operands, but it does not make the result free. Combining a column vector and a row vector can create a large outer-shaped result. Before accepting an expression, calculate the output shape and estimate its number of elements rather than judging only the size of each operand.

Complete worked example

python

import numpy as np

def inspect_example(rows, offsets):
    data = np.asarray(rows, dtype=np.float64)
    offsets = np.asarray(offsets, dtype=np.float64)
    if data.ndim != 2 or 0 in data.shape or offsets.ndim != 1:
        raise ValueError("expected a matrix and a feature vector")
    if offsets.size != data.shape[1] or not np.isfinite(data).all() or not np.isfinite(offsets).all():
        raise ValueError("offsets must match finite feature columns")
    return data + offsets
Reasoning
The function constructs two float64 arrays, checks rank and alignment, and evaluates data + offsets. NumPy conceptually expands the smaller shape for the operation without requiring a separately tiled input buffer. The result is still a newly computed matrix. Trace a two-by-three example: each row receives the same three column offsets, and the original row order remains unchanged. Broadcasting avoids unnecessary repeated operands, but it does not make the result free. Combining a column vector and a row vector can create a large outer-shaped result. Before accepting an expression, calculate the output shape and estimate its number of elements rather than judging only the size of each operand.
Open in local Python playground ↗

Focused decision: context is in the complete example

python

if offsets.size != data.shape[1]:
    raise ValueError("one offset per column")
adjusted = data + offsets
Focused decision
Type this short numerical decision after reading its complete context. The complete imports, array construction, validation, and result checks remain in the worked example. Typing records practice; only the downloadable computer lab executes Python.

Counterexamples and common mistakes

The controlled mistake inserts a column axis into the offsets.

The controlled mistake inserts a column axis into the offsets. On a square matrix, the operation still succeeds but applies offsets along rows instead of columns. On a rectangular matrix it may fail outright. Both behaviors are useful counterexamples: a valid result can be semantically wrong, and a shape error can reveal an assumption that small square fixtures hid.

Do not use tile or resize just to silence a compatibility error. Repeating or truncating measurements changes their relationship to observations. Also reject non-finite offsets before arithmetic; propagating an invalid adjustment across every row makes the resulting matrix less informative, not more complete.

Controlled mistake: inspect the failing numerical contract

python

import numpy as np

def inspect_example(rows, offsets):
    data = np.asarray(rows, dtype=np.float64)
    offsets = np.asarray(offsets, dtype=np.float64)
    if data.ndim != 2 or 0 in data.shape or offsets.ndim != 1:
        raise ValueError("expected a matrix and a feature vector")
    if offsets.size != data.shape[1] or not np.isfinite(data).all() or not np.isfinite(offsets).all():
        raise ValueError("offsets must match finite feature columns")
    return data + offsets[:, None]
Reasoning
The controlled mistake inserts a column axis into the offsets. On a square matrix, the operation still succeeds but applies offsets along rows instead of columns. On a rectangular matrix it may fail outright. Both behaviors are useful counterexamples: a valid result can be semantically wrong, and a shape error can reveal an assumption that small square fixtures hid. Do not use tile or resize just to silence a compatibility error. Repeating or truncating measurements changes their relationship to observations. Also reject non-finite offsets before arithmetic; propagating an invalid adjustment across every row makes the resulting matrix less informative, not more complete.
Open in local Python playground ↗

Independent practice

Change addition to subtraction while preserving column alignment, dtype, validation and output shape.

Change addition to subtraction while preserving column alignment, dtype, validation and output shape. This small task models removing a known per-feature baseline. It does not estimate that baseline from the current observations; estimating reference values is a separate statistical decision covered near the end of the course.

Predict the result for a rectangular matrix and a vector with distinct offsets. Include a negative offset so that blindly clipping outputs or using absolute values cannot pass. Keep the check against data.shape[1], not the number of rows.

Step 1: Subtract the per-column offsets instead of adding them. Step 2: Retain the working imports, input validation and array shapes. Change the stated policy, run the supplied practice cases, then explain the newly accepted or rejected boundary.

Practice starter: solve before reading the solution

python

import numpy as np

def inspect_example(rows, offsets):
    data = np.asarray(rows, dtype=np.float64)
    offsets = np.asarray(offsets, dtype=np.float64)
    if data.ndim != 2 or 0 in data.shape or offsets.ndim != 1:
        raise ValueError("expected a matrix and a feature vector")
    if offsets.size != data.shape[1] or not np.isfinite(data).all() or not np.isfinite(offsets).all():
        raise ValueError("offsets must match finite feature columns")
    return data + offsets

# Independent task: Subtract the per-column offsets instead of adding them.
Reasoning
Subtract the per-column offsets instead of adding them.
Open in local Python playground ↗
  • Hint 1: Keep offsets one-dimensional so it aligns with the trailing feature axis.
  • Hint 2: Change + to - in the return expression.

Solution, tests and trade-offs

The solution changes only the arithmetic operator.

The solution changes only the arithmetic operator. The practice suite checks a rectangular matrix, a single observation and an invalid offset length. A square case alone would be too weak because row-wise and column-wise broadcasting can have identical valid shapes. All successful results remain float64 matrices with exactly one output for every input coordinate.

State the memory trade-off accurately: no explicit tile is needed for the operand, but an output buffer is allocated. In-place arithmetic can impose additional dtype and ownership constraints and is not interchangeable with this independent-result contract.

Practice solution and acceptance checks

python

import numpy as np

def inspect_example(rows, offsets):
    data = np.asarray(rows, dtype=np.float64)
    offsets = np.asarray(offsets, dtype=np.float64)
    if data.ndim != 2 or 0 in data.shape or offsets.ndim != 1:
        raise ValueError("expected a matrix and a feature vector")
    if offsets.size != data.shape[1] or not np.isfinite(data).all() or not np.isfinite(offsets).all():
        raise ValueError("offsets must match finite feature columns")
    return data - offsets
Reasoning
The solution changes only the arithmetic operator. The practice suite checks a rectangular matrix, a single observation and an invalid offset length. A square case alone would be too weak because row-wise and column-wise broadcasting can have identical valid shapes. All successful results remain float64 matrices with exactly one output for every input coordinate. State the memory trade-off accurately: no explicit tile is needed for the operand, but an output buffer is allocated. In-place arithmetic can impose additional dtype and ownership constraints and is not interchangeable with this independent-result contract.
Open in local Python playground ↗

Interview reasoning and next step

In an interview, compare shapes (3, 2), (2,), (3, 1) and (1, 2), then predict the result shape before discussing values.

In an interview, compare shapes (3, 2), (2,), (3, 1) and (1, 2), then predict the result shape before discussing values. Explain why business alignment needs validation beyond NumPy shape compatibility. Give an example in which an accidental outer operation creates far more elements than either input.

On the PC, type the short column-aligned expression and reconstruct it from the shape contract. The app questions ask which axis receives the offsets. Next, reduce an axis and decide which dimensions should remain for later aligned operations.

Optional stretch — after the core task works: Add one independently reasoned boundary case and explain its expected value before running it.

Computer practice: https://applydjinn.com/typorithm/numpy-lab-20261106.zip. Install pinned dependencies in an isolated Python environment. Run verify.py, then change the working exercise baseline and run --practice np-broadcasting. The real NumPy arrays, numerical contracts, random state checks and temporary numeric files use owned fixtures only. No production database, feed, account or paid service is used. This lab executes Python; the PC typing trainer and native reading progress do not execute it.

Apply one offset per feature without accidentally treating that vector as one value per observation.