Reasoning Into CodeArunank Divya Sharan · Python edition← Arunank’s portfolio
Module 01 · Execution Grammar and State Mutation

006. Longest Positive Streak

Bridge · Download this solution · All solutions and shared helpers

Problem

Return the length of the longest contiguous run of strictly positive integers. Zero and negative values break a run. Empty input and an input with no positive value return zero. A run consists of adjacent positions, not a subsequence chosen by skipping failures.

Examples

Example 1

positive_streak([-1, 2, 3, -2, 4])
=> 2

The final run is shorter than the earlier run.

Example 2

positive_streak([])
=> 0

There is no nonempty run.

Example 3

positive_streak([1, 0, 2, 3])
=> 2

Zero breaks the first run.

Reveal the worked solution and reasoning

Why this mechanism works

Separate the run that is still alive from the best completed or ongoing run. The current run has only two possible transitions: extend on a positive event, or reset on a break. The global best is updated after that transition so a run ending at the final element is included.

State and boundaries

current is the positive suffix length of the processed prefix. best is the largest such suffix observed so far.

Protocol

  1. Initialize current and best to zero.
  2. Extend current for a positive value.
  3. Otherwise reset current to zero.
  4. Update best from current after the branch.
  5. Return best.

Visualization

values:  -1  2  3 -2  4
current:  0  1  2  0  1
best:     0  1  2  2  2

Python implementation

def positive_streak(nums):
    current = best = 0
    for value in nums:
        current = current + 1 if value > 0 else 0
        best = max(best, current)
    return best

Worked execution

Recorded state changes after statements; L numbers refer to the solution file. Long traces are explicitly condensed.

positive_streak([-1, 2, 3, -2, 4])

L2 positive_streak: current = best = 0
nums=[-1, 2, 3, -2, 4]; current=0; best=0

L3 positive_streak: for value in nums:
nums=[-1, 2, 3, -2, 4]; current=0; best=0; value=-1

L3 positive_streak: for value in nums:
nums=[-1, 2, 3, -2, 4]; current=0; best=0; value=2

L4 positive_streak: current = current + 1 if value > 0 else 0
nums=[-1, 2, 3, -2, 4]; current=1; best=0; value=2

L5 positive_streak: best = max(best, current)
nums=[-1, 2, 3, -2, 4]; current=1; best=1; value=2

L3 positive_streak: for value in nums:
nums=[-1, 2, 3, -2, 4]; current=1; best=1; value=3

L4 positive_streak: current = current + 1 if value > 0 else 0
nums=[-1, 2, 3, -2, 4]; current=2; best=1; value=3

L5 positive_streak: best = max(best, current)
nums=[-1, 2, 3, -2, 4]; current=2; best=2; value=3

L3 positive_streak: for value in nums:
nums=[-1, 2, 3, -2, 4]; current=2; best=2; value=-2

L4 positive_streak: current = current + 1 if value > 0 else 0
nums=[-1, 2, 3, -2, 4]; current=0; best=2; value=-2

L3 positive_streak: for value in nums:
nums=[-1, 2, 3, -2, 4]; current=0; best=2; value=4

L4 positive_streak: current = current + 1 if value > 0 else 0
nums=[-1, 2, 3, -2, 4]; current=1; best=2; value=4

Result: 2. The final run is shorter than the earlier run.

positive_streak([])

L2 positive_streak: current = best = 0
nums=[]; current=0; best=0

Result: 0. There is no nonempty run.

Why the solution is correct

A positive value extends exactly the preceding positive suffix; a nonpositive value leaves no positive suffix. Every maximal positive run appears as current at its final index. Taking the maximum of these suffix lengths finds the longest run.

Time and space

O(n) time and O(1) auxiliary space.

Common mistakes

Resetting best destroys earlier successful runs. Counting all positive values ignores contiguity.

Reasoning card

State: current is the positive suffix length of the processed prefix. best is the largest such suffix observed so far.

Invariant: current is the positive streak ending at the current value.

Decision to rehearse: Extend or reset, then update the global best.

Finish: Return best

Transfer exercise

Return the first longest run's half-open interval as well as its length.