Build your own vector database
The two structures HNSW rests on·18 min

Assign levels (seeded)

0 / 1
# grade this stage (from your course directory)
npx theinference test --stage assign-levels --watch

Turn the formula into code. Draw one level per element, in the fixed insertion order 0..n-1, using the seeded mulberry32(seed) PRNG. This array is the skeleton of the entire tower.

The determinism keystone

Same seed + same call order ⇒ the same level array on every machine. This is what makes the whole course deterministic: the graph is a pure function of (vectors, seed, params). Call the PRNG exactly once per element, in id order — no extra draws, no reordering.

What to build

Your task

Implement runAssignLevels

Implement assignLevel(rng, mL) and assignAllLevels(seed, n, M) in src/levels.ts, then expose runAssignLevels(seed, n, M) returning the level array (one integer per element).

tests/adapters.ts
export function runAssignLevels(seed: number, n: number, M: number): number[] {
  // mL = 1/ln(M); rng = mulberry32(seed)
  // for i in 0..n-1: levels[i] = floor(-ln(rng()) * mL)
}
How it's graded

Adapter mode: the level array is compared integer-exact (atol 0) to the reference, which uses the identical mulberry32 + formula + clamp. One stray PRNG call shifts every subsequent draw and fails the whole array.