O(1) neighbor lookup
# grade this stage (from your course directory)
npx theinference test --stage neighbors --watchNow the payoff API: hop to neighbors, optionally filtered by relationship type and direction — without ever scanning the global relationship list. Read outgoing/incoming per dir, filter by type (or all if null), map each relationship to its other endpoint, dedupe, and sort.
Implement runNeighbors
This is your first adapter step — the harness calls runNeighbors directly and compares the returned number[] to a fixture. Implement store.neighbors(nodeId, type, dir) returning sorted, deduped neighbor node ids, and wire the adapter to it. The fixture asks for Kevin Bacon's ACTED_IN OUT neighbors — the movie ids he acted in.
import type { Dir } from "./src/types.ts";
export function runNeighbors(nodeId: number, type: string | null, dir: Dir): number[] {
return store().neighbors(nodeId, type, dir);
}
// in src/store.ts:
neighbors(nodeId: number, type: string | null, dir: Dir): number[] {
const out = new Set<number>();
const a = this.adj.get(nodeId);
if (!a) return [];
if (dir === "OUT" || dir === "BOTH")
for (const rid of a.outgoing) {
const r = this.relById.get(rid)!;
if (type === null || r.type === type) out.add(r.endNode);
}
if (dir === "IN" || dir === "BOTH")
for (const rid of a.incoming) {
const r = this.relById.get(rid)!;
if (type === null || r.type === type) out.add(r.startNode);
}
return [...out].sort((x, y) => x - y);
}
Adapter mode: the harness loads the graph (from THEINFERENCE_KGDB_GRAPH), calls runNeighbors(0, 'ACTED_IN', 'OUT'), and compares your number[] to the fixture by exact match. Kevin Bacon (id 0) acted in three movies, so the answer is a length-3 sorted id array.