In-Memory Database with TTL and Historical Lookup
Problem statement
For this exercise, implement the four-level in-memory database through the batch interface below. Earlier-level operations remain available after later levels are added.
Levels 1 through 3 operations
For this exercise, the earlier levels use the following complete operation family. The database stores integer values in records identified by a string key; every record contains string field names.
set(timestamp, key, field, value): set or replace the field with a non-expiring integer value.get(timestamp, key, field): return the visible value, orNonewhen the record or field is absent or expired.compare_and_set(timestamp, key, field, expected_value, new_value): replace the visible value only when it equalsexpected_value, and return whether the replacement happened.compare_and_delete(timestamp, key, field, expected_value): delete the visible field only when its value equalsexpected_value, and return whether the deletion happened.scan(timestamp, key): return every visible field asfield(value), sorted lexicographically by field name.scan_by_prefix(timestamp, key, prefix): return only the visible fields whose names begin withprefix, using the same formatting and order.set_with_ttl(timestamp, key, field, value, ttl): set or replace the field. The new value is visible during the half-open interval[timestamp, timestamp + ttl).compare_and_set_with_ttl(timestamp, key, field, expected_value, new_value, ttl): perform the conditional replacement and, on success, give the new value the supplied TTL.- All reads, scans, comparisons, and deletions treat an expired value as absent.
Level 4
The database should support look back get operation.
get_when(self, timestamp: int, key: str, field: str, at_timestamp: int) -> int | None— should return the value offieldatat_timestampfrom the record associated withkey. Ifat_timestampis0, perform thegetoperation described in Level 1. It is guaranteed thatat_timestampwill not be greater thantimestamp. If the specifiedfieldor record did not exist at the given timestamp, returnNone.
Examples The example below shows how these operations should work (the section is scrollable to the right):
Queries
set_with_ttl(1, "A", "B", 3, 10)
compare_and_set_with_ttl(4, "A", "B", 3, 7, 9)
get(10, "A", "B")
get_when(13, "A", "B", 3)
get_when(15, "A", "B", 13)
Explanations
database state: {"A": {"B": 3}} with {"B": 3} expiring at timestamp 11
returns True; database state: {"A": {"B": 7}}
updates field "B" to {"B": 7} expiring at timestamp 13
returns 7; field "B" in record "A" had a value of 7 at timestamp 10
returns 3; field "B" in record "A" had a value of 3 at timestamp 3
returns None; field "B" in record "A" expired at timestamp 13[execution time limit] 3 seconds[memory limit] 4g
FastPrep practice interface
Complete runHistoricalDatabase. Process the rows of operations in order. The second item in every row is a strictly increasing timestamp. Return one string array for every input row.
["SET", timestamp, key, field, value]: callsetand return an empty array.["GET", timestamp, key, field]: callgetand return a one-item array containing the value, or an empty array forNone.["COMPARE_AND_SET", timestamp, key, field, expectedValue, newValue]: callcompare_and_setand return["true"]or["false"].["COMPARE_AND_DELETE", timestamp, key, field, expectedValue]: callcompare_and_deleteand return["true"]or["false"].["SCAN", timestamp, key]: callscanand return its formatted list.["SCAN_BY_PREFIX", timestamp, key, prefix]: callscan_by_prefixand return its formatted list.["SET_WITH_TTL", timestamp, key, field, value, ttl]: callset_with_ttland return an empty array.["COMPARE_AND_SET_WITH_TTL", timestamp, key, field, expectedValue, newValue, ttl]: callcompare_and_set_with_ttland return["true"]or["false"].["GET_WHEN", timestamp, key, field, atTimestamp]: callget_whenand return a one-item array containing the value, or an empty array forNone.- Overwrites and successful deletions end the previous version at their timestamp but do not erase earlier history. An older value never reappears after a later version expires.
Function
runHistoricalDatabase(operations: String[][]) → String[][]Examples
Example 1
operations = [["SET_WITH_TTL","1","A","B","3","10"],["COMPARE_AND_SET_WITH_TTL","4","A","B","3","7","9"],["GET","10","A","B"],["GET_WHEN","13","A","B","3"],["GET_WHEN","15","A","B","13"]]return = [[],["true"],["7"],["3"],[]]The value 3 is first visible on [1,11). The successful TTL compare-and-set writes 7 on [4,13), so the current read at timestamp 10 returns 7, the historical read at timestamp 3 returns 3, and the read at the exact expiration timestamp 13 returns no value.
Example 2
operations = [["SET","1","user2","age","18"],["SET","2","user2","height","180"],["SET","3","user2","address","1"],["SCAN","4","user2"],["SCAN_BY_PREFIX","5","user2","a"],["COMPARE_AND_SET","6","user2","age","18","19"],["COMPARE_AND_DELETE","7","user2","height","181"],["GET","8","user2","age"]]return = [[],[],[],["address(1)","age(18)","height(180)"],["address(1)","age(18)"],["true"],["false"],["19"]]The full scan sorts address, age, and height by field name. The prefix scan keeps only the two fields beginning with a. The conditional update of age succeeds, while deleting height with the wrong expected value fails.
Constraints
1 <= operations.length <= 2000.- Every operation row has exactly the format listed in the statement.
- Timestamps are base-10 integers in
[1, 10^9]and strictly increase across the input. atTimestampis in[0, timestamp].- Every
ttlis in[1, 10^9]. - Values are canonical signed 32-bit decimal integers.
- Keys, fields, and prefixes contain
1through50case-sensitive English letters or digits. - The source execution time limit is
3seconds and the source memory limit is4GB.