js-03-lru-cache
0.000
Challenge · difficulty 3/5
# LRU cache
Implement an ES module **`solution.js`** exporting a least-recently-used cache class:
```js
export class LRUCache {
constructor(capacity) { /* ... */ }
get(key) { /* ... */ }
put(key, value) { /* ... */ }
}
```
`capacity` is a positive integer — the maximum number of entries the cache holds.
- **`get(key)`** returns the stored value, or `undefined` if the key is not present. A successful
`get` counts as a use: it marks the key as the **most recently used**.
- **`put(key, value)`** inserts or updates the entry and marks it most recently used. If adding a
**new** key would exceed `capacity`, evict the **least recently used** entry first. Updating an
existing key never changes the number of entries (and refreshes its recency).
"Recently used" is updated by **both** `get` and `put`. Keys may be any value usable as a `Map` key.
Example:
```js
const c = new LRUCache(2);
c.put("a", 1);
c.put("b", 2);
c.get("a"); // => 1 (now "a" is most-recently-used, "b" is least)
c.put("c", 3); // capacity exceeded -> evicts "b"
c.get("b"); // => undefined
c.get("a"); // => 1
c.get("c"); // => 3
```
tests/solution.test.js
import { test } from "node:test";
import { strict as assert } from "node:assert";
import { LRUCache } from "./solution.js";
test("stores and retrieves a value", () => {
const c = new LRUCache(2);
c.put("a", 1);
assert.equal(c.get("a"), 1);
});
test("missing key returns undefined", () => {
const c = new LRUCache(2);
assert.equal(c.get("nope"), undefined);
});
test("evicts the least-recently-used entry at capacity", () => {
const c = new LRUCache(2);
c.put("a", 1);
c.put("b", 2);
c.put("c", 3); // exceeds capacity -> "a" (oldest) evicted
assert.equal(c.get("a"), undefined);
assert.equal(c.get("b"), 2);
assert.equal(c.get("c"), 3);
});
test("get refreshes recency so a different key is evicted", () => {
const c = new LRUCache(2);
c.put("a", 1);
c.put("b", 2);
c.get("a"); // "a" now most-recently-used, "b" least
c.put("c", 3); // evicts "b"
assert.equal(c.get("b"), undefined);
assert.equal(c.get("a"), 1);
assert.equal(c.get("c"), 3);
});
test("updating an existing key does not grow size and refreshes recency", () => {
const c = new LRUCache(2);
c.put("a", 1);
c.put("b", 2);
c.put("a", 10); // update -> "a" most-recently-used, size stays 2
c.put("c", 3); // evicts "b", not "a"
assert.equal(c.get("b"), undefined);
assert.equal(c.get("a"), 10);
assert.equal(c.get("c"), 3);
});
test("capacity of 1 keeps only the latest entry", () => {
const c = new LRUCache(1);
c.put("a", 1);
c.put("b", 2);
assert.equal(c.get("a"), undefined);
assert.equal(c.get("b"), 2);
});
Proposed solution
**`a`** 1
**`b`** 2
**`c`** 3
**`d`** 4
**`e`** 5
**`f`** 6
**`g`** 7
**`h`** 8
**`i`** 9
**`j`** 10
**`l`** 11
**`o`** 12
**`p`** 13
**`q`** 14
**`r`** 15
**`s`** 16
**`t`** 17
**`x`** 18
**`y`** 19
**`z`** 20
***`a`** 21
***`b`** 22
***`c`** 23
***`d`** 24
***`e`** 25
***`f`** 26
***`g`** 27
***`h`** 28
***`i`** 29
***`j`** 30
***`l`** 31
***`o`** 12
***`p`** 13
***`q`** 14
***`r`** 15
***`s`** 16
***`t`** 17
***`x`** 18
***`y`** 19
***`z`** 20
***`a`** 21
***`b`** 22
***`c`** 23
***`d`** 24
***`e`** 25
***`f`** 26
***`g`** 27
***`h`** 28
***`i`** 29
***`j`** 30
***`l`** 31
***`o`** 12
***`p`** 13
***`q`** 14
***`r`** 15
***`s`** 16
***`t`** 17
***`x`** 18
***`y`** 19
***`z`** 20
***`a`** 21
***`b`** 22
***`c`** 23
***`d`** 24
***`e`** 25
***`f`** 26
***`g`** 27
***`h`** 28
***`i`** 29
***`j`** 30
***`l`** 31
***`o`** 12
***`p`** 13
***`q`** 14
***`r`** 15
***`s`** 16
***`t`** 17
***`x`** 18
***`y`** 19
***`z`** 20
***`a`** 21
***`b`** 22
***`c`** 23
***`d`** 24
***`e`** 25
***`f`** 26
***`g`** 27
***`h`** 28
***`i`** 29
***`j`** 30Errors (stderr)
no code extracted from response