Evidence Region Validator

Evidence Region Validator

A course-materials assistant answers questions about PDF handouts. Each answer cites the page region it relied on, so the reader can open the handout with that area highlighted. The citation is part of the model's output, so it is untrusted input. The expected document revision and the page count come from the document store, which the application trusts; they are never taken from the model.

Implement validateRegion(region, expectedRevision, pageCount). If every check passes, return a new object { documentRevision, pageIndex, box } built from the validated values. Any other field in region is dropped, and neither region nor its box is modified. If a check fails, throw an Error whose message is exactly the text in the table below.

Coordinate convention

  • pageIndex is zero-based: a document with 3 pages has pages 0, 1, and 2.
  • box is [x0, y0, x1, y1] in normalized page coordinates, with the origin at the upper-left corner of the unrotated page. x runs from 0 (left edge) to 1 (right edge), and y from 0 (top edge) to 1 (bottom edge).
  • A valid box has positive width and height and stays inside the page. Touching an edge is allowed, so [0, 0, 1, 1] is the whole page.

Checks, in order

Run the checks in this order and throw at the first one that fails.

OrderMessageFails when
1Invalid expected revisionexpectedRevision is not a string, or is the empty string
2Invalid page countpageCount is not an integer of at least 1 (a boolean is not an integer)
3Region must be an objectregion is not a non-array object, for example null, an array, or a string
4Wrong document revisionregion.documentRevision is not exactly equal to expectedRevision (a missing revision is not equal)
5Invalid page indexregion.pageIndex is not an integer with 0 <= pageIndex < pageCount
6Expected four coordinatesregion.box is not an array of length 4
7Coordinates must be finite numbersany of the four values is not a finite number: NaN, Infinity, true, "0.5", null, and so on (in Python: not an int or float that converts to a finite float)
8Invalid normalized rectanglethe box does not satisfy both 0 <= x0 < x1 <= 1 and 0 <= y0 < y1 <= 1

Check 7 looks at all four values before check 8 runs, so [0.6, 0.2, 0.1, NaN] fails with the finite-number message even though its x range is also reversed.

Fixture

Every row uses expected revision "handout-v2" and page count 3.

RowRegion revisionPage indexBoxOther input fields
R1"handout-v2"2[0.1, 0.2, 0.6, 0.25]none
R2"handout-v1"2[0.1, 0.2, 0.6, 0.25]none
R3"handout-v2"3[0.1, 0.2, 0.6, 0.25]none
R4"handout-v2"0[0, 0, 1, 1]none
R5"handout-v2"2[0.6, 0.2, 0.1, 0.25]none
R6"handout-v2"-1[0.1, 0.2, 0.6, 0.25]none
R7"handout-v2"2[0.1, 0.2, 0.1, 0.25]none
R8"handout-v2"2[0.1, NaN, 0.6, 0.25]none
R9"handout-v2"2[0, 0, 1.2, 0.5]none
R10"handout-v2"true[0.1, 0.2, 0.6, 0.25]none
R11"handout-v2"2[true, 0.2, 0.6, 0.25]none
R12"handout-v1"5[0.1, 0.2, 0.6, 0.25]none
R13"handout-v2"2[0.1, 0.2, 0.6]none
R14"handout-v2"1[0.25, 0.5, 0.75, 0.625]label: "answer key", verified: true

Work out each row's result from the checks above. The tests assert all fourteen: a returned record must match exactly, with no extra fields, and an error must carry the exact message of the first check that fails.

Examples

JavaScript
validateRegion(
    { documentRevision: 'notes-r3', pageIndex: 4, box: [0.5, 0.75, 1, 1], quote: 'loop invariant' },
    'notes-r3',
    5,
);
// { documentRevision: 'notes-r3', pageIndex: 4, box: [0.5, 0.75, 1, 1] }
// quote is dropped, and x1 = y1 = 1 is allowed because a box may touch the page edge.

validateRegion({ documentRevision: 'notes-r3', pageIndex: 5, box: [0.1, 0.2, 0.6, 0.25] }, 'notes-r3', 5);
// throws Error('Invalid page index'): a 5-page document has pages 0 to 4.

validateRegion({ documentRevision: 'handout-v2', pageIndex: 2, box: [0, 0, true, 0.5] }, 'handout-v2', 3);
// throws Error('Coordinates must be finite numbers'): true is not a number, even though true <= 1.

Python

Implement validate_region(region, expected_revision, page_count) with the same checks, order, and messages, raising ValueError. region is a dict, and box may be a list or a tuple.

JavaScriptPython
expectedRevision (argument)expected_revision
pageCount (argument)page_count
documentRevision (input and result key)document_revision
pageIndex (input and result key)page_index
box (input and result key)box
  • bool is a subclass of int in Python, so True and False must be rejected explicitly as a page count, a page index, or a coordinate.
  • A page count or page index must be an int. A coordinate may be an int or a float that converts to a finite float.
  • The returned box is always a new list of four float values, even when the input was a tuple or used 0 and 1.
  • A huge int such as 10**400 has no float value: float(10**400) and math.isfinite(10**400) both raise OverflowError. It fails check 7 with Coordinates must be finite numbers, never with a crash. (In JavaScript the same literal is already Infinity, which fails the same check.)

Constraints

  • region comes from model output and can be any JSON value.
  • expectedRevision and pageCount come from trusted metadata, but they are still checked first.
  • Do not modify region or its box.

Expected complexity

O(1) time and O(1) extra space: a fixed number of checks over four coordinates.

MEDIUM
AI Engineering
Multimodal AI
Citations & Grounding
OCR
Intermediate

0 views

Solution

Hints

Hint 1
Hint 2
Premium
Hint 3
Premium