Lock trace impossibility

Write codeEasy15 min

Your task

A render farm audits the lock trace its job runner recorded. Each event is a string "worker|action|lock", for example "w2|lock|mesh_cache", and the action is either "lock" or "unlock". The locks are reentrant: a worker that already holds a lock may lock it again, which raises its hold count by one, and every unlock lowers that count by one. A lock becomes free only when its count falls back to zero. An event is impossible when a worker locks a lock that a different worker currently holds, or unlocks a lock that is free or held by someone else. Read the events in order and return the 1-based position of the first impossible event, or 0 when the whole trace is consistent. Locks still held at the end are fine.

Examples

first_trace_defect(events: list[str]) -> int
Example 1
Inputfirst_trace_defect(["w1|lock|mesh", "w1|lock|mesh", "w1|unlock|mesh", "w2|lock|mesh"])
Output4
Example 2
Inputfirst_trace_defect(["w1|lock|mesh", "w1|unlock|mesh", "w2|lock|mesh", "w2|unlock|mesh"])
Output0
Example 3
Inputfirst_trace_defect(["w3|lock|shader", "w4|unlock|shader"])
Output2