Skip to main content

From a Requirement to a Program

What this concept is​

Systematic design connects a requirement to a data model, examples, function contracts, an implementation and evidence. It is a way to decide what to write before guessing at code. A program can execute successfully while answering the wrong question.

Why it matters here​

The tracker already separates parsing, calculation and storage. Now use that separation to handle a requirement that cannot be solved by renaming a variable: identify a run of consecutive qualifying sessions. This lesson follows the original six lessons; use ordinary lists and loops, not a new framework.

Concrete example​

Suppose the request is: “Show my longest streak of sessions meeting a target.” Ask what a session means, whether equality qualifies, whether order matters, and whether an empty history is allowed. Here is the agreed contract:

  • Input is a list of whole study minutes in 1..240, already validated at the boundary, plus a whole target in 1..240.
  • Every list entry is a separate session, including repeated durations. This is a session streak, not a calendar-day streak: there are no dates.
  • An entry qualifies when it is greater than or equal to the target.
  • Return the longest consecutive qualifying run, or zero for an empty list. Do not change the input.

Predict examples before implementation: [25, 25, 10, 30] at target 25 gives 2; [25, 10, 25] gives 1; [24] gives 0; [25] gives 1. The first example separates longest run from total qualifying count (3). The second exposes an implementation that forgets to reset a run.

Two pieces of state have different meanings: current is the qualifying suffix of the processed prefix; best is the longest run anywhere in that prefix. Both begin at zero.

def longest_run(sessions, target):
current = 0
best = 0
for minutes in sessions:
if minutes >= target:
current += 1
best = max(best, current)
else:
current = 0
return best

assert longest_run([25, 25, 10, 30], 25) == 2
assert longest_run([], 25) == 0

After processing the example, (current, best) is (1,1), (2,2), (0,2), (1,2). Explain why a nonqualifying session resets only current. The loop visits every input once and retains two counters. Formal loop proofs arrive later; for now explain what each counter means after any prefix.

Common confusion / misconception​

A set destroys both multiplicity and sequence. A total qualifying count ignores adjacency. A calendar streak cannot be inferred from durations alone. A function's documented precondition is not runtime validation: parsing and loading must actually establish it before calling this function. Do not claim this function rejects arbitrary malformed input.

How to use it​

For your next problem, write a six-part design note: requirement in your words; input model and valid states; output and errors; manually calculated cases; decomposition and state meanings; implementation and checks. Keep it short enough to update when the requirement changes. Separate a pure calculation from input/output so you can investigate each boundary independently.

Check yourself​

For [30, 10, 30, 30, 30] at target 30, the result is 3. If the target changes to 31, it is 0. Neither answer requires sorting. Explain why sorting would change the question.

Mini drill or application​

Design a function returning the earliest starting index of the longest qualifying run, or None when no session qualifies. Write examples for a tie, an empty list and a run ending at the final entry before coding. For [25,25,10,25,25] at 25, the answer is 0. Explain which state you need in addition to current and best. This drill does not add persistence or change the original tracker file format.

Read this only if stuck​

Use the function-design discussion in How to Design Programs as selective reading, not another full course. Its teaching language differs from our Python exercises. For syntax, revisit Python control flow. The example and tasks above are original curriculum material.