Part A — Constrained cache (LRU-like)
Design an in-memory cache that supports the following operations:
-
get(key) -> value | null
-
put(key, value) -> void
Functional requirements
-
The cache has a fixed capacity
C
(number of entries). When inserting into a full cache, evict an entry based on a well-defined policy (e.g., least-recently-used).
-
get
and
put
should be efficient (target amortized
O(1)
).
Security/robustness requirements (discuss + implement)
-
High concurrency:
multiple threads may call
get/put
concurrently. Describe and/or implement a thread-safe approach.
-
Abuse scenarios:
discuss how the cache behaves under:
-
extremely hot keys (contention),
-
key-spamming (many unique keys),
-
intentionally malformed/oversized keys or values.
-
Failure handling:
define behavior for null/empty keys, capacity
C≤0
, memory pressure, and unexpected exceptions.
Part B — Secure string validation (IP-like)
Write a function classifyAddress(s: string) -> "IPv4" | "IPv6" | "Neither".
Core rules (typical IPv4/IPv6 validation)
-
IPv4: four decimal segments separated by
.
, each
0..255
, no leading
+/-
, no extra spaces; handle leading zeros per your chosen policy but state it clearly.
-
IPv6: eight hex segments separated by
:
, each
1..4
hex chars (
0-9
,
a-f
,
A-F
).
Security constraints (must address)
-
Bypass resistance:
your parser must not accept inputs that can trick naive implementations (e.g., hidden whitespace, mixed separators, Unicode lookalikes, overflow like
9999999999
, empty segments, trailing separators).
-
Performance under abnormal traffic:
avoid worst-case blowups (e.g., pathological long strings). State time and space complexity and any length limits you enforce.
Return the classification string for each input.