All problems
HardRetrieval & Rankingv2026-06-30

Retrieval & Ranking · Hard

BM25

Score documents using term frequency, IDF, and length normalization.

Task

Implement bm25_scores(documents: list[list[str]], query_tokens: list[str], k1: float, b: float) -> list[float]. Compute one BM25 relevance score per tokenized document, in corpus order.

Requirements

  • documents is a list of already-tokenized documents, and query_tokens is already tokenized; compare tokens exactly and case-sensitively without splitting, lowercasing, stemming, or other normalization.
  • k1 is finite and non-negative, and b is finite and lies in the closed interval [0, 1].
  • Let N be the number of documents, document length be its token count, and average document length be the total number of corpus tokens divided by N.
  • For each distinct query token t, let tf(t, d) be its occurrence count in document d and df(t) be the number of documents containing it at least once.
  • Use IDF(t) = log(1 + (N - df(t) + 0.5) / (df(t) + 0.5)), where log is the natural logarithm.
  • Add IDF(t) * tf(t,d) * (k1 + 1) / (tf(t,d) + k1 * (1 - b + b * len(d) / avgdl)) for every distinct query token present in d.
  • Repeated query tokens have no additional effect: score each distinct query token exactly once.
  • Return scores in the same order as documents, including 0.0 for documents with no matching query token.
  • Return an empty list for an empty corpus. For an empty query, return one 0.0 per document.
  • A corpus whose documents are all empty has average length zero; return zero scores without dividing by zero.
  • Do not mutate documents or query_tokens.

Example

bm25_scores(
    [["the", "cat", "sat", "cat"], ["the", "dog", "sat"], ["dog"]],
    ["cat", "sat"],
    1.2,
    0.75,
)
# [1.5725612026838964, 0.44713858782297006, 0.0]
solution.pySign in to save
Public tests run locally in your browser.
Run your code to see public test results.