Katkat

Model Infection, Immunity, Delayed Death, and Burn Interventions on a Grid

OpenAIMachine Learning Engineer · Technical Screen

Last updated

Design and implement a discrete grid simulation modeling a five-stage disease progression with state countdowns, immunity, delayed mortality, and external burn interventions.

Problem Statement

Agricultural researchers need to simulate disease spread across an R x C field of crops to test containment strategies. Each plant in the grid exists in one of five distinct stages:

  • 0: DEAD — Inert plant; cannot infect, be infected, or recover.
  • 1: HEALTHY — Susceptible to infection.
  • 2: INFECTED — Actively contagious to its 4-directional (orthogonal) neighbors.
  • 3: IMMUNE — Temporary resistance; cannot be infected.
  • 4: DYING — Late-stage diseased; non-contagious; transitioning to DEAD.

Implement the CropSimulation class:

class CropSimulation:
    def __init__(self, grid: list[list[int]], config: dict):
        """
        grid: R x C matrix with initial states (0-4).
        config: Dictionary containing integer parameters:
            - "infect_duration": Days a plant stays INFECTED.
            - "immune_duration": Days a plant stays IMMUNE before returning to HEALTHY.
            - "dying_duration": Days a plant stays DYING before becoming DEAD.
        All newly infected plants start with full infect_duration, etc.
        If an initial cell is already INFECTED, IMMUNE, or DYING, assume it has
        just entered that state on day 0 with full duration.
        """
        pass

    def step(self) -> list[list[int]]:
        """
        Simulates 1 day of state transitions and returns the updated grid.
        """
        pass

    def burn_row(self, r: int) -> None:
        """
        Immediately incinerates row r, setting all its cells to DEAD (0).
        """
        pass

    def burn_col(self, c: int) -> None:
        """
        Immediately incinerates column c, setting all its cells to DEAD (0).
        """
        pass

Transition Rules (Simultaneous Update at each step):

  1. Infection Spread: A HEALTHY plant becomes INFECTED with timer infect_duration if at least one orthogonal neighbor was INFECTED at the beginning of the day.
  2. Infection Resolution: An INFECTED plant decrements its timer. When its timer expires (reaches 0 at the end of the day):
    • If strictly fewer than 2 orthogonal neighbors were INFECTED at the start of the day, the plant recovers and transitions to IMMUNE (timer = immune_duration).
    • Otherwise, the plant worsens and transitions to DYING (timer = dying_duration).
  3. Immunity Expiration: An IMMUNE plant decrements its timer. When its timer expires, it transitions back to HEALTHY.
  4. Delayed Death: A DYING plant decrements its timer. When its timer expires, it transitions to DEAD.
  5. Interventions: burn_row and burn_col immediately set all targeted cells to DEAD (0) and clear their timers. Interventions take effect immediately.

Example

grid = [
    [1, 1, 1],
    [1, 2, 1],
    [1, 1, 1]
]
config = {
    "infect_duration": 1,
    "immune_duration": 2,
    "dying_duration": 2
}

sim = CropSimulation(grid, config)

# Day 1:
# Center (1, 1) was INFECTED. It had 0 infected neighbors at start -> recovers to IMMUNE (3).
# All 4 orthogonal neighbors of center were HEALTHY -> become INFECTED (2).
# Corners remain HEALTHY (1).
assert sim.step() == [
    [1, 2, 1],
    [2, 3, 2],
    [1, 2, 1]
]

# Intervene by burning column 1
sim.burn_col(1)
assert sim.step()  # Continues simulation on subsequent step

Constraints

  • 1 <= R, C <= 100
  • 1 <= infect_duration, immune_duration, dying_duration <= 50
  • Number of calls to step, burn_row, and burn_col combined <= 1000.

Hints

Hint 1

Ensure all transitions in `step()` are evaluated against the grid state at the start of that step to avoid cascade artifacts within a single day.

Hint 2

Maintain a parallel grid or state structure tracking the remaining countdown days for each cell.

Hint 3

When an infected cell's timer reaches zero, its recovery or mortality condition depends on its neighbor counts from the beginning of that step, not after new infections spread.

Follow-up questions

  • How would you optimize the simulation if the grid is sparse (e.g., 10,000 x 10,000 with only a few thousand active plants)?
  • How would you support stochastic transition rules (e.g., 80% transmission rate, probabilistic recovery) deterministically for testing?
  • If burning a row had an economic cost and stopping the spread yielded a reward, how would you frame finding the optimal intervention sequence as a reinforcement learning or search problem?