Breadth-first search
# grade this stage (from your course directory)
npx theinference test --stage bfs --watchImplement BFS that returns every reachable node and its hop-distance from a start node, stopping past maxHops. Classic queue-based BFS: a dist map, expand the frontier ring by ring, mark each node visited on enqueue.
Implement runBfsDistances
This is an adapter step. Implement bfs(store, startId, maxHops, type, dir) returning rows {node, dist} sorted by (dist, node); the adapter flattens them to [node, dist] pairs. The fixture runs BFS from Kevin Bacon (id 0), ACTED_IN, BOTH, maxHops=2 — his movies at distance 1, his co-stars at distance 2 (19 rows total).
export function bfs(store, startId, maxHops, type, dir) {
const dist = new Map([[startId, 0]]);
let frontier = [startId], d = 0;
while (frontier.length && d < maxHops) {
const next = [];
for (const cur of frontier)
for (const nb of store.neighbors(cur, type, dir))
if (!dist.has(nb)) { dist.set(nb, d + 1); next.push(nb); } // visited on ENQUEUE
frontier = next; d++;
}
return [...dist].map(([node, dd]) => ({ node, dist: dd }))
.sort((a, b) => a.dist - b.dist || a.node - b.node);
}
Mark a node visited when you first reach it (enqueue), not when you process it (dequeue). Otherwise the same node enters the frontier multiple times — its distance and your runtime both blow up. This is the #1 BFS bug.
Adapter mode: the harness calls runBfsDistances(0, 2, 'ACTED_IN', 'BOTH') and compares your [node, dist] rows to the fixture (shape [19, 2]), sorted by (dist, node). Distance 0 is the start itself.