Cache Hit Ledger
MediumOnline Assessment
Replay a log of requests against a small cache that evicts the least frequently used entry, and report what happened to each request.
The cache holds at most capacity keys. Each cached key has a use count, and the cache remembers how recently each key was used.
A request is either a key k (a lookup) or !k (an invalidation).
- Lookup of
k, key is cached: the result is"HIT". Its use count goes up by 1 and it becomes the most recently used key. - Lookup of
k, key is not cached: the key is inserted with use count 1 as the most recently used key. If the cache was full, first evict the key with the lowest use count; if several keys share that count, evict the least recently used of them. The result is"MISS"if nothing was evicted and"EVICT x"if keyxwas evicted. Ifcapacityis 0 nothing is ever stored and the result is"MISS". - Invalidation
!k: ifkis cached it is removed (result"DROP"), and if it later returns it starts again with use count 1. Ifkis not cached the result is"NOOP".
Aging: after every period-th lookup (invalidations are not counted), once that lookup has been fully processed, every cached key's use count becomes (count + 1) // 2, rounding up. Recency is not affected.
Input: capacity, period, and requests, a list of strings.
Output: a list [results, keys]: results has one result string per request in order, and keys is the sorted list of keys cached at the end.
Example 1
- Input:
- [2,100,["a","b","a","c","b","a"]]
- Output:
- [["MISS","MISS","HIT","EVICT b","EVICT c","HIT"],["a","b"]]
- Explanation
- Capacity 2 and aging far in the future.
aandbfill the cache.ais a hit and now has use count 2.cmisses on a full cache:b(count 1) is the least used, so it is evicted.bmisses again andc(count 1) is evicted, becauseahas count 2. The finalais a hit.
Example 2
- Input:
- [2,100,["x","y","x","!x","!x","x","z"]]
- Output:
- [["MISS","MISS","HIT","DROP","NOOP","MISS","EVICT y"],["x","z"]]
- Explanation
- Capacity 2.
xandyfill the cache with count 1 each.xis a hit (count 2).!xremoves it (DROP), so!xa second time does nothing (NOOP).xcomes back as a fresh miss with count 1 and no eviction since there was a free slot.zthen finds the cache full withyandxboth at count 1:ywas used less recently, soyis evicted.
Example 3
- Input:
- [2,3,["a","a","a","b","b","c","a"]]
- Output:
- [["MISS","HIT","HIT","MISS","HIT","EVICT a","EVICT b"],["a","c"]]
- Explanation
- Aging happens after every 3rd lookup.
a a a: the third lookup brings a to count 3, and the aging step right after it makes it 2.bis a miss andba hit (count 2).cmisses on a full cache whereaandbboth have count 2;awas used less recently, soEVICT a. That was the 6th lookup, so aging runs again: b becomes 1 and c becomes 1. The lastamisses; b and c tie at 1 andbis older, soEVICT b.
Constraints
- 0 ≤ capacity ≤ 20
- 1 ≤ period ≤ 109
- 0 ≤ requests.length ≤ 300; every request is a lowercase key (1 to 6 letters), optionally preceded by a single
!