Twice on the Wire

An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.

Domain
Python
Difficulty
easy
Seniority
junior
Asked in
Visa

Problem

A card reader retransmits its last status ping whenever an ACK is dropped, so the raw stream arrives with the same status repeated back to back. Collapse each run of consecutive identical pings into a single entry, keeping the surviving pings in their original order.

A dropped ACK makes the reader say it again. Keep the signal, drop the echo.

Example 1

Input:

pings = ["online","online","degraded","online"]

Output:

["online","degraded","online"]

Example 2

Input:

pings = ["online","offline","online"]

Output:

["online","offline","online"]

Worked solution and explanation

Why this problem exists in real interviews

This is run-length collapse wearing a payments costume, and the whole thing turns on one word: consecutive. The skill being probed is whether you compare each ping to its PREVIOUS neighbor, not to a bag of everything seen so far. Almost everyone hears 'remove the duplicates' and reaches for set(pings) or dict.fromkeys(pings). That erases every repeat globally, so the last 'online' in the first example, a genuine event that arrived after a 'degraded', silently disappears. Get it wrong and your collapsed stream is missing real authorizations and the count no longer matches reality.


Break down the requirements

Step 1: Compare against the previous ping, not a seen-set

The rule is local: drop a ping only when it equals the one immediately before it. That is fundamentally different from global dedup. Keep the value you last emitted and skip while the next value matches it.

Step 2: Preserve order and non-adjacent repeats

A status that comes back later after something else in between is a brand-new event, so it must survive. The output is the sequence of run leaders in arrival order. Never sort, never hash the whole stream.

Step 3: Let empty and single-element inputs fall out for free

An empty stream returns an empty list and a one-element stream returns itself. A clean run-collapse handles both with no special branch, so resist adding guard clauses that only add noise.


The solution

groupby collapses consecutive runs in one pass
from itertools import groupby

def collapse_pings(pings):
    return [status for status, _ in groupby(pings)]
Global dedup (wrong)
list(dict.fromkeys(pings)) keeps first-seen order but removes EVERY later repeat. On ['online','online','degraded','online'] it returns ['online','degraded'], deleting the final real 'online'.
Consecutive collapse (right)
[k for k, _ in groupby(pings)] only merges adjacent equal values. Same input returns ['online','degraded','online'], preserving the genuine later event.

Common follow-up questions