Rolled back read detection

Write codeEasy18 minOracle style

Your task

An audit tool replays a storage log to find reads that saw data the writer later threw away. Each event is a string of fields joined by a vertical bar: "t3|write|balance|500" sets a key, "t7|read|balance" reads one, and "t3|commit" or "t3|abort" ends a transaction. Values are plain text and never contain a bar. Every key keeps a stack of versions. A write pushes one, and an abort drops every version that transaction wrote, so the key falls back to its previous version. A read sees the top version of its key, or nothing when the key has none. A read is rolled back when the version it saw came from a different transaction that aborts later in the log. A transaction the log never ends counts as open, not aborted. Return one string per rolled back read, in log order, written as the reader, the key and the value seen, joined by bars.

Examples

rolled_back_reads(events: list[str]) -> list[str]
Example 1
Inputrolled_back_reads(["t1|write|balance|500", "t2|read|balance", "t1|abort", "t2|commit"])
Output["t2|balance|500"]
Example 2
Inputrolled_back_reads(["t1|write|stock|9", "t1|commit", "t2|read|stock", "t2|commit"])
Output[]
Example 3
Inputrolled_back_reads(["t1|write|price|300", "t1|read|price", "t1|abort"])
Output[]