File-parsing labs Code
Ten original Python labs shaped like the NPE coding screen · fixtures inline · expected output hidden until you try
Lab 1 · Count host failures from a file 25 min
Read a UTF-8 host,status file without a header. Ignore blank lines. Strip whitespace; normalize hostnames to lowercase and statuses to uppercase. Valid statuses are UP/DOWN. Report the failure count for every host seen in a valid row, including zero, plus the 1-based line numbers of malformed rows. A valid row has exactly two nonempty fields.
Skills: with open · line iteration · dict counts · validation
events.csv
WEB-01,UP
db-01,DOWN
web-01,DOWN
badline
web-01,DOWN
cache-01,UP
Edge cases to test: empty file, only UP records, unknown status, extra separator, blank hostname.
Expected output
{
"failures": {
"web-01": 2,
"db-01": 1,
"cache-01": 0
},
"invalidLines": [
5
]
}Target complexity: O(n) input processing; O(u + e) output/state for distinct hosts and error lines.
Follow-up: For 20 GB of input, what grows with file size? If error output is also huge, stream errors to another file.
Lab 2 · Aggregate quoted CSV fields 25 min
Read CSV with interface,bytes columns. Interface names may contain commas inside quoted fields. Sum nonnegative integer bytes per interface. Report invalid data-row numbers, counted from one after the header. Do not use split(',').
Skills: csv.DictReader · numeric parsing · aggregation
traffic.csv
interface,bytes
"edge,west",100
eth0,25
"edge,west",50
eth0,oops
eth1,-1
Edge cases to test: quoted comma, zero bytes, negative number, missing field, non-integer number.
Expected output
{
"bytes": {
"edge,west": 150,
"eth0": 25
},
"invalidDataRows": [
4,
5
]
}Target complexity: O(n) rows, O(u + e) state/output.
Follow-up: Write the report as CSV and explain newline='' when using Python's csv module.
Lab 3 · Keep the latest health record 30 min
Read JSON Lines; each nonblank line is one object with host,ts,status. ts is an integer, status is UP/DOWN and host is nonempty. Keep the largest ts per host; ties use the later input line. Return downHosts sorted alphabetically and latestTs per valid host. Count invalid nonblank lines. Normalize hostnames to lowercase.
Skills: json.loads · nested records · dictionary replacement · tie policy
health.jsonl
{"host":"web","ts":20,"status":"UP"}
{"host":"web","ts":10,"status":"DOWN"}
{"host":"db","ts":15,"status":"UP"}
{"host":"db","ts":15,"status":"DOWN"}
{bad json}
Edge cases to test: out-of-order timestamps, equal timestamps, missing field, malformed JSON, JSON array instead of object.
Expected output
{
"downHosts": [
"db"
],
"latestTs": {
"web": 20,
"db": 15
},
"invalidLines": 1
}Target complexity: O(n + u log u) including sorted output; O(u) state.
Follow-up: Explain why a single JSON array and JSON Lines have different streaming requirements.
Lab 4 · Find the busiest clients 30 min
Read a whitespace-delimited file with one client IP string per line. Treat each nonblank line as an identifier. Return the k most frequent identifiers ordered by descending count then ascending identifier. k may exceed the number of distinct values; k=0 returns an empty list.
Skills: Counter · sorting keys · top k · complexity
clients.txt
192.0.2.2
192.0.2.1
192.0.2.2
192.0.2.3
192.0.2.1
192.0.2.2
Parameters: {"k": 2}
Edge cases to test: all counts tied, k=0, empty file, k larger than unique count.
Expected output
[
[
"192.0.2.2",
3
],
[
"192.0.2.1",
2
]
]Target complexity: Start O(n + u log u); discuss O(n + u log k) ranking with a size-k heap.
Follow-up: Do not claim O(k) total memory: the frequency map still stores u distinct keys.
Lab 5 · Compare two configuration snapshots 30 min
Each JSON file maps interface names to objects containing mtu and adminUp. Return sorted added, removed and changed interface names. For interfaces in both snapshots, changed means either of those two fields differs. Assume this lab's input schema is valid; extra fields should not affect the result.
Skills: json.load · sets · dictionary lookup · stable output
before.json
{"eth0":{"mtu":1500,"adminUp":true},"eth1":{"mtu":1500,"adminUp":true},"eth2":{"mtu":9000,"adminUp":false}}
after.json
{"eth0":{"mtu":9000,"adminUp":true},"eth2":{"mtu":9000,"adminUp":false},"eth3":{"mtu":1500,"adminUp":true}}
Edge cases to test: identical snapshots, one empty snapshot, boolean change only, ignored extra field.
Expected output
{
"added": [
"eth3"
],
"removed": [
"eth1"
],
"changed": [
"eth0"
]
}Target complexity: O(a+b) comparison plus sorting output; O(a+b) loaded snapshots.
Follow-up: How would you report which fields changed without mutating either input?
Lab 6 · Track consecutive failures per host 35 min
Read host,status records in observation order. Records from different hosts can interleave. Return each host's longest consecutive run of DOWN observations in that host's own subsequence. UP resets only that host's current run. Assume valid input.
Skills: per-key state · single pass · invariants
status.csv
a,DOWN
b,DOWN
a,DOWN
a,UP
b,DOWN
a,DOWN
b,UP
Edge cases to test: all UP, all DOWN, interleaved hosts, last run is longest, one observation.
Expected output
{
"a": 2,
"b": 2
}Target complexity: O(n) time, O(u) state.
Follow-up: Explain why storing only one global run counter fails.
Lab 7 · Join inventory with traffic 35 min
inventory.csv contains unique host,region rows. traffic.csv contains host,bytes rows, possibly repeated. Sum bytes by region. Unknown hosts go into an UNKNOWN region. The inputs have valid schemas and nonnegative integer bytes. Return the region totals.
Skills: two-file join · hashmap indexing · aggregation · missing keys
inventory.csv
host,region
a,us
b,eu
c,us
traffic.csv
host,bytes
a,10
b,20
a,5
d,7
Edge cases to test: unknown host, inventory host without traffic, empty traffic file, repeated host.
Expected output
{
"us": 15,
"eu": 20,
"UNKNOWN": 7
}Target complexity: O(i+t) time; O(i+r) working state with inventory indexed and traffic streamed.
Follow-up: Why is repeatedly rescanning inventory for each traffic row wasteful?
Lab 8 · Match addresses to the most specific prefix 40 min
routes.csv contains unique valid IPv4 network CIDRs and labels. destinations.txt contains valid IPv4 addresses. For each address return the label of its most specific matching prefix, or null if none match. Use Python's standard ipaddress module. Preserve destination order.
Skills: ipaddress · parsing · longest-prefix match · correctness before optimization
routes.csv
prefix,label
0.0.0.0/0,default
192.0.2.0/24,site
192.0.2.128/26,rack
destinations.txt
192.0.2.130
192.0.2.10
198.51.100.9
Edge cases to test: /32 host route, no matching route, overlapping prefixes, boundary address.
Expected output
[
"rack",
"site",
"default"
]Target complexity: O(q*r) straightforward scan with O(r) parsed routes. Discuss a trie only after the working solution.
Follow-up: Write the same membership check for one IPv4 prefix using integers and a mask.
Lab 9 · Merge two sorted log files 35 min
Two files each contain sorted timestamp,message CSV rows without headers. Timestamps are nondecreasing integers. Merge into one output stream in ascending timestamp order; equal timestamps from the left file come first. Preserve within-file order and do not load the entire files.
Skills: iterators · two pointers · stable ordering · streaming output
left.csv
1,a
3,c
5,e
right.csv
2,b
3,d
6,f
Edge cases to test: one empty file, all timestamps equal, one file exhausted early, negative timestamps.
Expected output
[
[
1,
"a"
],
[
2,
"b"
],
[
3,
"c"
],
[
3,
"d"
],
[
5,
"e"
],
[
6,
"f"
]
]Target complexity: O(a+b) time and O(1) working records, excluding output if streamed.
Follow-up: Extend to k sorted logs with a heap and explain tie-breaking.
Lab 10 · Detect repeated failures in a time window 45 min
Read timestamp,host,status rows sorted by timestamp. At each DOWN row, include all DOWN events for that host with timestamp in the inclusive interval [t-window,t]. Emit [t,host,count] whenever that count is at least threshold. UP rows do not reset or remove earlier events; they do not produce alerts. Assume valid rows.
Skills: deque · per-host state · sliding window · boundary tests
events.csv
0,a,DOWN
2,b,DOWN
4,a,DOWN
6,a,UP
10,a,DOWN
11,a,DOWN
Parameters: {"window": 10, "threshold": 3}
Edge cases to test: event exactly at t-window, multiple events with same timestamp, interleaved hosts, UP during window, no alerts.
Expected output
[
[
10,
"a",
3
],
[
11,
"a",
3
]
]Target complexity: Each DOWN event enters and leaves a deque at most once: O(n) time. State depends on retained events and host count, not automatically O(1).
Follow-up: Use this as a 45-minute rehearsal: clarify for 5 minutes, implement/test for 30, explain complexity and a modification for 10.