prompt:
The map is flipped north-south about the origin.

Input [lon, lat, lon0, lat0, lat1, lat2] degrees, sphere R = 6371000, lat1 != -lat2. n = (sin p1 + sin p2)/2; C = cos(p1)**2 + 2*n*sin(p1); rho = R*sqrt(C - 2*n*sin(phi))/n; rho0 likewise at lat0; theta = n*dlon with dlon wrapped to [-180, 180). x = rho*sin(theta), y = rho0 - rho*cos(theta), rounded to 2 decimals.

split: open-access


meaning: Fixture-count band, not measured model difficulty

deps: stdlib

prompt:
Equator points are rejected by both polar grids.

Input [lon, lat, pole, lon0, k0]. pole "N" accepts lat >= 0 and "S" accepts lat <= 0; other points return None. Sphere R = 6371000, dl = rad(lon - lon0). North: rho = 2*R*k0*tan(pi/4 - phi/2), x = rho*sin(dl), y = -rho*cos(dl). South: rho = 2*R*k0*tan(pi/4 + phi/2), x = rho*sin(dl), y = rho*cos(dl). Rounded to 2 decimals.

split: open-access


prompt:
Antarctic points are placed far from the south pole and the pole itself explodes.

Input [lon, lat, pole, lon0, k0]. pole "N" accepts lat >= 0 and "S" accepts lat <= 0; other points return None. Sphere R = 6371000, dl = rad(lon - lon0). North: rho = 2*R*k0*tan(pi/4 - phi/2), x = rho*sin(dl), y = -rho*cos(dl). South: rho = 2*R*k0*tan(pi/4 + phi/2), x = rho*sin(dl), y = rho*cos(dl). Rounded to 2 decimals.

split: open-access


prompt:
The south polar grid is mirrored top to bottom.

Input [lon, lat, pole, lon0, k0]. pole "N" accepts lat >= 0 and "S" accepts lat <= 0; other points return None. Sphere R = 6371000, dl = rad(lon - lon0). North: rho = 2*R*k0*tan(pi/4 - phi/2), x = rho*sin(dl), y = -rho*cos(dl). South: rho = 2*R*k0*tan(pi/4 + phi/2), x = rho*sin(dl), y = rho*cos(dl). Rounded to 2 decimals.

split: open-access


prompt:
Polar grids are mirrored left to right.

Input [lon, lat, pole, lon0, k0]. pole "N" accepts lat >= 0 and "S" accepts lat <= 0; other points return None. Sphere R = 6371000, dl = rad(lon - lon0). North: rho = 2*R*k0*tan(pi/4 - phi/2), x = rho*sin(dl), y = -rho*cos(dl). South: rho = 2*R*k0*tan(pi/4 + phi/2), x = rho*sin(dl), y = rho*cos(dl). Rounded to 2 decimals.

split: open-access


prompt:
North polar output is rotated by 90 degrees.

Input [lon, lat, pole, lon0, k0]. pole "N" accepts lat >= 0 and "S" accepts lat <= 0; other points return None. Sphere R = 6371000, dl = rad(lon - lon0). North: rho = 2*R*k0*tan(pi/4 - phi/2), x = rho*sin(dl), y = -rho*cos(dl). South: rho = 2*R*k0*tan(pi/4 + phi/2), x = rho*sin(dl), y = rho*cos(dl). Rounded to 2 decimals.

split: open-access


prompt:
North polar coordinates are half size.

Input [lon, lat, pole, lon0, k0]. pole "N" accepts lat >= 0 and "S" accepts lat <= 0; other points return None. Sphere R = 6371000, dl = rad(lon - lon0). North: rho = 2*R*k0*tan(pi/4 - phi/2), x = rho*sin(dl), y = -rho*cos(dl). South: rho = 2*R*k0*tan(pi/4 + phi/2), x = rho*sin(dl), y = rho*cos(dl). Rounded to 2 decimals.

split: open-access


prompt:
On a tilted globe, features behind the horizon near the poles are drawn and visible ones are hidden.

Input [lon, lat, lon0, lat0] degrees; sphere R = 6371000 viewed from infinity above (lon0, lat0). cos c = sin(p0)sin(p) + cos(p0)cos(p)cos(dl); points with cos c < 0 are on the far side and return None. Otherwise x = R cos(p) sin(dl), y = R (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)), rounded to 2 decimals.

split: open-access


prompt:
The visible cap is misplaced when the view centre is off the equator.

Input [lon, lat, lon0, lat0] degrees; sphere R = 6371000 viewed from infinity above (lon0, lat0). cos c = sin(p0)sin(p) + cos(p0)cos(p)cos(dl); points with cos c < 0 are on the far side and return None. Otherwise x = R cos(p) sin(dl), y = R (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)), rounded to 2 decimals.

split: open-access


prompt:
Latitude lines bow the wrong way on a tilted globe.

Input [lon, lat, lon0, lat0] degrees; sphere R = 6371000 viewed from infinity above (lon0, lat0). cos c = sin(p0)sin(p) + cos(p0)cos(p)cos(dl); points with cos c < 0 are on the far side and return None. Otherwise x = R cos(p) sin(dl), y = R (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)), rounded to 2 decimals.

split: open-access


prompt:
Eastings do not shrink toward the poles.

Input [lon, lat, lon0, lat0] degrees; sphere R = 6371000 viewed from infinity above (lon0, lat0). cos c = sin(p0)sin(p) + cos(p0)cos(p)cos(dl); points with cos c < 0 are on the far side and return None. Otherwise x = R cos(p) sin(dl), y = R (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)), rounded to 2 decimals.

split: open-access


prompt:
The globe tilt is wrong for any view not centred on the equator.

Input [lon, lat, lon0, lat0] degrees; sphere R = 6371000 viewed from infinity above (lon0, lat0). cos c = sin(p0)sin(p) + cos(p0)cos(p)cos(dl); points with cos c < 0 are on the far side and return None. Otherwise x = R cos(p) sin(dl), y = R (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)), rounded to 2 decimals.

split: open-access


prompt:
Points at or beside the antipode are plotted at absurd distances instead of being rejected.

Input [lon, lat, lon0, lat0]; sphere R = 6371000 centred on (lon0, lat0). cos c is clamped to [-1, 1], c = acos. Points with c > pi - 1e-6 (the antipode neighbourhood) return None. k = 1 at the centre (c < 1e-12) else c/sin c. x = R k cos(p) sin(dl); y = R k (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)). Return [x rounded to 1 decimal, y rounded to 1 decimal, hypot(x, y)/1000 km rounded to 3, azimuth clockwise from north in [0, 360) rounded to 4].

split: open-access


prompt:
Distant points are drawn much too close to the centre.

Input [lon, lat, lon0, lat0]; sphere R = 6371000 centred on (lon0, lat0). cos c is clamped to [-1, 1], c = acos. Points with c > pi - 1e-6 (the antipode neighbourhood) return None. k = 1 at the centre (c < 1e-12) else c/sin c. x = R k cos(p) sin(dl); y = R k (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)). Return [x rounded to 1 decimal, y rounded to 1 decimal, hypot(x, y)/1000 km rounded to 3, azimuth clockwise from north in [0, 360) rounded to 4].

split: open-access


prompt:
Bearings are measured counter-clockwise from east.

Input [lon, lat, lon0, lat0]; sphere R = 6371000 centred on (lon0, lat0). cos c is clamped to [-1, 1], c = acos. Points with c > pi - 1e-6 (the antipode neighbourhood) return None. k = 1 at the centre (c < 1e-12) else c/sin c. x = R k cos(p) sin(dl); y = R k (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)). Return [x rounded to 1 decimal, y rounded to 1 decimal, hypot(x, y)/1000 km rounded to 3, azimuth clockwise from north in [0, 360) rounded to 4].

split: open-access


prompt:
Westward bearings are reported as negative numbers.

Input [lon, lat, lon0, lat0]; sphere R = 6371000 centred on (lon0, lat0). cos c is clamped to [-1, 1], c = acos. Points with c > pi - 1e-6 (the antipode neighbourhood) return None. k = 1 at the centre (c < 1e-12) else c/sin c. x = R k cos(p) sin(dl); y = R k (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)). Return [x rounded to 1 decimal, y rounded to 1 decimal, hypot(x, y)/1000 km rounded to 3, azimuth clockwise from north in [0, 360) rounded to 4].

split: open-access


prompt:
Almost every point is rejected as antipodal or placed far away.

Input [lon, lat, lon0, lat0]; sphere R = 6371000 centred on (lon0, lat0). cos c is clamped to [-1, 1], c = acos. Points with c > pi - 1e-6 (the antipode neighbourhood) return None. k = 1 at the centre (c < 1e-12) else c/sin c. x = R k cos(p) sin(dl); y = R k (cos(p0) sin(p) - sin(p0) cos(p) cos(dl)). Return [x rounded to 1 decimal, y rounded to 1 decimal, hypot(x, y)/1000 km rounded to 3, azimuth clockwise from north in [0, 360) rounded to 4].

split: open-access


prompt:
Mid-latitude points jitter between two wrong positions depending on iteration parity.

Input [lon, lat, lon0]; sphere R = 6371000, dlon wrapped to [-180, 180). Solve 2t + sin 2t = pi sin(phi) by Newton from t = phi, at most 50 steps, stopping when the residual is below 1e-12, with derivative 2 + 2 cos 2t. x = R (2 sqrt 2 / pi) dlon cos t, y = R sqrt 2 sin t, rounded to 2 decimals.

split: open-access


prompt:
High-latitude points are misplaced by kilometres.

Input [lon, lat, lon0]; sphere R = 6371000, dlon wrapped to [-180, 180). Solve 2t + sin 2t = pi sin(phi) by Newton from t = phi, at most 50 steps, stopping when the residual is below 1e-12, with derivative 2 + 2 cos 2t. x = R (2 sqrt 2 / pi) dlon cos t, y = R sqrt 2 sin t, rounded to 2 decimals.

split: open-access


prompt:
Positions differ by metres from the converged solution.

Input [lon, lat, lon0]; sphere R = 6371000, dlon wrapped to [-180, 180). Solve 2t + sin 2t = pi sin(phi) by Newton from t = phi, at most 50 steps, stopping when the residual is below 1e-12, with derivative 2 + 2 cos 2t. x = R (2 sqrt 2 / pi) dlon cos t, y = R sqrt 2 sin t, rounded to 2 decimals.

split: open-access


prompt:
The outline is not an ellipse; high latitudes are too wide.

Input [lon, lat, lon0]; sphere R = 6371000, dlon wrapped to [-180, 180). Solve 2t + sin 2t = pi sin(phi) by Newton from t = phi, at most 50 steps, stopping when the residual is below 1e-12, with derivative 2 + 2 cos 2t. x = R (2 sqrt 2 / pi) dlon cos t, y = R sqrt 2 sin t, rounded to 2 decimals.

split: open-access


prompt:
The map is squashed vertically.

Input [lon, lat, lon0]; sphere R = 6371000, dlon wrapped to [-180, 180). Solve 2t + sin 2t = pi sin(phi) by Newton from t = phi, at most 50 steps, stopping when the residual is below 1e-12, with derivative 2 + 2 cos 2t. x = R (2 sqrt 2 / pi) dlon cos t, y = R sqrt 2 sin t, rounded to 2 decimals.

split: open-access


prompt:
Rotated or sheared rasters are sampled at the wrong pixels.

Input [gx, gy, gt, width, height] with a six-term affine gt: X = gt0 + col*gt1 + row*gt2, Y = gt3 + col*gt4 + row*gt5, where (gt0, gt3) is the outer corner of pixel (0, 0). Invert with the 2x2 determinant, take floor of the fractional column and row, and return [col, row] if inside [0, width) x [0, height), otherwise None (also None for a singular transform).

split: open-access


prompt:
Columns drift across rows of rotated rasters.

Input [gx, gy, gt, width, height] with a six-term affine gt: X = gt0 + col*gt1 + row*gt2, Y = gt3 + col*gt4 + row*gt5, where (gt0, gt3) is the outer corner of pixel (0, 0). Invert with the 2x2 determinant, take floor of the fractional column and row, and return [col, row] if inside [0, width) x [0, height), otherwise None (also None for a singular transform).

split: open-access


prompt:
Points just outside the left or top edge are sampled from the first column or row.

Input [gx, gy, gt, width, height] with a six-term affine gt: X = gt0 + col*gt1 + row*gt2, Y = gt3 + col*gt4 + row*gt5, where (gt0, gt3) is the outer corner of pixel (0, 0). Invert with the 2x2 determinant, take floor of the fractional column and row, and return [col, row] if inside [0, width) x [0, height), otherwise None (also None for a singular transform).

split: open-access


prompt:
Points just beyond the right or bottom edge return a pixel index equal to the raster size.

Input [gx, gy, gt, width, height] with a six-term affine gt: X = gt0 + col*gt1 + row*gt2, Y = gt3 + col*gt4 + row*gt5, where (gt0, gt3) is the outer corner of pixel (0, 0). Invert with the 2x2 determinant, take floor of the fractional column and row, and return [col, row] if inside [0, width) x [0, height), otherwise None (also None for a singular transform).

split: open-access


prompt:
Rows count upward from the origin for north-up rasters, sampling mirrored rows.

Input [gx, gy, gt, width, height] with a six-term affine gt: X = gt0 + col*gt1 + row*gt2, Y = gt3 + col*gt4 + row*gt5, where (gt0, gt3) is the outer corner of pixel (0, 0). Invert with the 2x2 determinant, take floor of the fractional column and row, and return [col, row] if inside [0, width) x [0, height), otherwise None (also None for a singular transform).

split: open-access


prompt:
Points in the left half of each pixel are assigned to the previous column.

Input [gx, gy, gt, width, height] with a six-term affine gt: X = gt0 + col*gt1 + row*gt2, Y = gt3 + col*gt4 + row*gt5, where (gt0, gt3) is the outer corner of pixel (0, 0). Invert with the 2x2 determinant, take floor of the fractional column and row, and return [col, row] if inside [0, width) x [0, height), otherwise None (also None for a singular transform).

split: open-access


prompt:
Rotated rasters are skewed the wrong way after import.

Input [lines, col, row] where lines are the six world-file values in file order A, D, B, E, C, F: A and E are the pixel sizes, D and B the rotation terms, and (C, F) the map coordinate of the centre of the upper-left pixel. Return the corner-based geotransform [C - A/2 - B/2, A, B, F - D/2 - E/2, D, E] followed by the centre of pixel (col, row): C + A*col + B*row and F + D*col + E*row; all rounded to 6 decimals.

split: open-access


prompt:
Imported rasters sit one pixel east of their true position.

Input [lines, col, row] where lines are the six world-file values in file order A, D, B, E, C, F: A and E are the pixel sizes, D and B the rotation terms, and (C, F) the map coordinate of the centre of the upper-left pixel. Return the corner-based geotransform [C - A/2 - B/2, A, B, F - D/2 - E/2, D, E] followed by the centre of pixel (col, row): C + A*col + B*row and F + D*col + E*row; all rounded to 6 decimals.

split: open-access


prompt:
North-up rasters flip upside down when converted.

Input [lines, col, row] where lines are the six world-file values in file order A, D, B, E, C, F: A and E are the pixel sizes, D and B the rotation terms, and (C, F) the map coordinate of the centre of the upper-left pixel. Return the corner-based geotransform [C - A/2 - B/2, A, B, F - D/2 - E/2, D, E] followed by the centre of pixel (col, row): C + A*col + B*row and F + D*col + E*row; all rounded to 6 decimals.

split: open-access


prompt:
Pixel-centre eastings are half a pixel west of where the world file puts them.

Input [lines, col, row] where lines are the six world-file values in file order A, D, B, E, C, F: A and E are the pixel sizes, D and B the rotation terms, and (C, F) the map coordinate of the centre of the upper-left pixel. Return the corner-based geotransform [C - A/2 - B/2, A, B, F - D/2 - E/2, D, E] followed by the centre of pixel (col, row): C + A*col + B*row and F + D*col + E*row; all rounded to 6 decimals.

split: open-access


prompt:
Pixel-centre northings follow the column index.

Input [lines, col, row] where lines are the six world-file values in file order A, D, B, E, C, F: A and E are the pixel sizes, D and B the rotation terms, and (C, F) the map coordinate of the centre of the upper-left pixel. Return the corner-based geotransform [C - A/2 - B/2, A, B, F - D/2 - E/2, D, E] followed by the centre of pixel (col, row): C + A*col + B*row and F + D*col + E*row; all rounded to 6 decimals.

split: open-access


prompt:
Tiny rotations shift coordinates by thousands of kilometres.

Input [X, Y, Z, tx, ty, tz, rx, ry, rz, s, convention] with metres, rotations in arc-seconds and scale in ppm. Rotations are converted to radians; for "coordinate_frame" they are negated, for "position_vector" used as is. m = 1 + s*1e-6. X' = tx + m(X - rz Y + ry Z); Y' = ty + m(rz X + Y - rx Z); Z' = tz + m(-ry X + rx Y + Z). Return [X', Y', Z'] rounded to 3 decimals.

split: open-access


prompt:
Published parameters apply the rotation in the opposite sense, leaving metre-level residuals.

Input [X, Y, Z, tx, ty, tz, rx, ry, rz, s, convention] with metres, rotations in arc-seconds and scale in ppm. Rotations are converted to radians; for "coordinate_frame" they are negated, for "position_vector" used as is. m = 1 + s*1e-6. X' = tx + m(X - rz Y + ry Z); Y' = ty + m(rz X + Y - rx Z); Z' = tz + m(-ry X + rx Y + Z). Return [X', Y', Z'] rounded to 3 decimals.

split: open-access


prompt:
Coordinate-frame shifts are right only when two of the rotations are zero.

Input [X, Y, Z, tx, ty, tz, rx, ry, rz, s, convention] with metres, rotations in arc-seconds and scale in ppm. Rotations are converted to radians; for "coordinate_frame" they are negated, for "position_vector" used as is. m = 1 + s*1e-6. X' = tx + m(X - rz Y + ry Z); Y' = ty + m(rz X + Y - rx Z); Z' = tz + m(-ry X + rx Y + Z). Return [X', Y', Z'] rounded to 3 decimals.

split: open-access


prompt:
Coordinates are scaled by several times their magnitude.

Input [X, Y, Z, tx, ty, tz, rx, ry, rz, s, convention] with metres, rotations in arc-seconds and scale in ppm. Rotations are converted to radians; for "coordinate_frame" they are negated, for "position_vector" used as is. m = 1 + s*1e-6. X' = tx + m(X - rz Y + ry Z); Y' = ty + m(rz X + Y - rx Z); Z' = tz + m(-ry X + rx Y + Z). Return [X', Y', Z'] rounded to 3 decimals.

split: open-access


prompt:
Y coordinates drift by metres when the x rotation is non-zero.

Input [X, Y, Z, tx, ty, tz, rx, ry, rz, s, convention] with metres, rotations in arc-seconds and scale in ppm. Rotations are converted to radians; for "coordinate_frame" they are negated, for "position_vector" used as is. m = 1 + s*1e-6. X' = tx + m(X - rz Y + ry Z); Y' = ty + m(rz X + Y - rx Z); Z' = tz + m(-ry X + rx Y + Z). Return [X', Y', Z'] rounded to 3 decimals.

split: open-access


prompt:
Z coordinates are off by the scale times the translation.

Input [X, Y, Z, tx, ty, tz, rx, ry, rz, s, convention] with metres, rotations in arc-seconds and scale in ppm. Rotations are converted to radians; for "coordinate_frame" they are negated, for "position_vector" used as is. m = 1 + s*1e-6. X' = tx + m(X - rz Y + ry Z); Y' = ty + m(rz X + Y - rx Z); Z' = tz + m(-ry X + rx Y + Z). Return [X', Y', Z'] rounded to 3 decimals.

split: open-access


prompt:
Holes are emitted with the same winding as the exterior, so renderers fill them.

Input: a polygon as a list of rings (exterior first, then holes), each a list of [x, y] integer positions. Every ring must be closed (first == last) with at least 4 positions, else return None; an empty polygon is None. Exterior rings are made counter-clockwise and holes clockwise by twice-signed-area sign; a reversed ring keeps its start vertex. Zero-area rings are left untouched. Return the rewritten rings.

split: open-access


prompt:
Degenerate collapsed rings are reversed although they have no orientation.

Input: a polygon as a list of rings (exterior first, then holes), each a list of [x, y] integer positions. Every ring must be closed (first == last) with at least 4 positions, else return None; an empty polygon is None. Exterior rings are made counter-clockwise and holes clockwise by twice-signed-area sign; a reversed ring keeps its start vertex. Zero-area rings are left untouched. Return the rewritten rings.

split: open-access


prompt:
Reoriented rings come out unclosed.

Input: a polygon as a list of rings (exterior first, then holes), each a list of [x, y] integer positions. Every ring must be closed (first == last) with at least 4 positions, else return None; an empty polygon is None. Exterior rings are made counter-clockwise and holes clockwise by twice-signed-area sign; a reversed ring keeps its start vertex. Zero-area rings are left untouched. Return the rewritten rings.

split: open-access


prompt:
Unclosed rings are silently accepted and reoriented.

Input: a polygon as a list of rings (exterior first, then holes), each a list of [x, y] integer positions. Every ring must be closed (first == last) with at least 4 positions, else return None; an empty polygon is None. Exterior rings are made counter-clockwise and holes clockwise by twice-signed-area sign; a reversed ring keeps its start vertex. Zero-area rings are left untouched. Return the rewritten rings.

split: open-access


prompt:
Two-vertex closed "rings" pass validation.

Input: a polygon as a list of rings (exterior first, then holes), each a list of [x, y] integer positions. Every ring must be closed (first == last) with at least 4 positions, else return None; an empty polygon is None. Exterior rings are made counter-clockwise and holes clockwise by twice-signed-area sign; a reversed ring keeps its start vertex. Zero-area rings are left untouched. Return the rewritten rings.

split: open-access


prompt:
Vertices exactly one tolerance away from the previous vertex survive cleaning.

Input [ring, eps] where ring is an open or closed list of integer [x, y] positions and eps >= 0. Walk the ring and drop a position whose Chebyshev distance to the last KEPT position is <= eps. Then repeatedly drop trailing kept positions within eps of the first kept position. If fewer than 3 positions remain return None, else return the kept positions closed by repeating the first.

split: open-access


prompt:
Diagonal jitter survives cleaning while axis-aligned jitter is removed.

Input [ring, eps] where ring is an open or closed list of integer [x, y] positions and eps >= 0. Walk the ring and drop a position whose Chebyshev distance to the last KEPT position is <= eps. Then repeatedly drop trailing kept positions within eps of the first kept position. If fewer than 3 positions remain return None, else return the kept positions closed by repeating the first.

split: open-access


prompt:
A run of small steps is collapsed entirely, cutting off a corner reached gradually.

Input [ring, eps] where ring is an open or closed list of integer [x, y] positions and eps >= 0. Walk the ring and drop a position whose Chebyshev distance to the last KEPT position is <= eps. Then repeatedly drop trailing kept positions within eps of the first kept position. If fewer than 3 positions remain return None, else return the kept positions closed by repeating the first.

split: open-access


prompt:
Rings end with a near-duplicate of their start vertex.

Input [ring, eps] where ring is an open or closed list of integer [x, y] positions and eps >= 0. Walk the ring and drop a position whose Chebyshev distance to the last KEPT position is <= eps. Then repeatedly drop trailing kept positions within eps of the first kept position. If fewer than 3 positions remain return None, else return the kept positions closed by repeating the first.

split: open-access


prompt:
Valid cleaned triangles are rejected.

Input [ring, eps] where ring is an open or closed list of integer [x, y] positions and eps >= 0. Walk the ring and drop a position whose Chebyshev distance to the last KEPT position is <= eps. Then repeatedly drop trailing kept positions within eps of the first kept position. If fewer than 3 positions remain return None, else return the kept positions closed by repeating the first.

split: open-access


prompt:
Points inside the second or later hole are reported as interior.

Input [point, rings]: exterior ring then hole rings, closed, integer coordinates. A point on any ring edge (exact cross product 0 and inside the closed segment bounding box) is "boundary". Otherwise a crossing-number test with the half-open rule (a.y > py) != (b.y > py) and ray toward +x decides containment: outside the exterior or inside any hole is "exterior", else "interior".

split: open-access


prompt:
Points on a hole edge are classified as interior or exterior depending on the ray.

Input [point, rings]: exterior ring then hole rings, closed, integer coordinates. A point on any ring edge (exact cross product 0 and inside the closed segment bounding box) is "boundary". Otherwise a crossing-number test with the half-open rule (a.y > py) != (b.y > py) and ray toward +x decides containment: outside the exterior or inside any hole is "exterior", else "interior".

split: open-access


prompt:
Points level with a polygon vertex flip between inside and outside.

Input [point, rings]: exterior ring then hole rings, closed, integer coordinates. A point on any ring edge (exact cross product 0 and inside the closed segment bounding box) is "boundary". Otherwise a crossing-number test with the half-open rule (a.y > py) != (b.y > py) and ray toward +x decides containment: outside the exterior or inside any hole is "exterior", else "interior".

split: open-access


prompt:
Points on axis-parallel edges and on vertices are not reported as boundary.

Input [point, rings]: exterior ring then hole rings, closed, integer coordinates. A point on any ring edge (exact cross product 0 and inside the closed segment bounding box) is "boundary". Otherwise a crossing-number test with the half-open rule (a.y > py) != (b.y > py) and ray toward +x decides containment: outside the exterior or inside any hole is "exterior", else "interior".

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m != '2':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #48', ['0FFFFFFF2', 'contains', 0, 0], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #28', ['1FF0FF102', 'within', 1, 1], True), ('control #49', ['0FFFFFFF2', 'equals', 0, 0], True)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #48', ['0FFFFFFF2', 'contains', 0, 0], True), ('control #85', ['0F2FF1FF2', 'crosses', 0, 2], True)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #49', ['0FFFFFFF2', 'equals', 0, 0], True), ('control #86', ['0F2FF1FF2', 'covers', 0, 2], True)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('control #51', ['0FFFFFFF2', 'covers', 0, 0], True), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m not in '12':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #48', ['0FFFFFFF2', 'contains', 0, 0], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #28', ['1FF0FF102', 'within', 1, 1], True), ('control #49', ['0FFFFFFF2', 'equals', 0, 0], True)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #48', ['0FFFFFFF2', 'contains', 0, 0], True), ('control #85', ['0F2FF1FF2', 'crosses', 0, 2], True)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #49', ['0FFFFFFF2', 'equals', 0, 0], True), ('control #86', ['0F2FF1FF2', 'covers', 0, 2], True)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('control #51', ['0FFFFFFF2', 'covers', 0, 0], True), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Line and point interactions never satisfy predicates that require a non-empty intersection.

Input [matrix, predicate, dimA, dimB] with a 9-character intersection matrix over "F012" (row-major II, IB, IE, BI, BB, BE, EI, EB, EE). Pattern characters: "*" anything, "T" any non-F value, "F" only F, "0"/"1"/"2" that exact dimension. disjoint = FF*FF****; intersects = not disjoint; touches (not both points) = FT******* or F**T***** or F***T****; within = T*F**F***; contains = T*****FF*; covers = any of T*****FF*, *T****FF*, ***T**FF*, ****T*FF*; overlaps needs equal dimensions and 1*T***T** for lines else T*T***T**; crosses = T*T****** if dimA < dimB, T*****T** if dimA > dimB, 0******** for two lines, otherwise false; equals = T*F**FFF*. Unknown predicates return None.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('regression #92', ['FF2F11212', 'touches', 2, 2], True), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #94', ['FF1F00212', 'touches', 1, 2], True), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #92', ['FF2F11212', 'touches', 2, 2], True), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('regression #92', ['FF2F11212', 'touches', 2, 2], True), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #94', ['FF1F00212', 'touches', 1, 2], True), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #92', ['FF2F11212', 'touches', 2, 2], True), ('regression #119', ['FF21F1212', 'touches', 2, 1], True)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Geometries that meet only boundary-to-boundary are not reported as touching.

Input [matrix, predicate, dimA, dimB] with a 9-character intersection matrix over "F012" (row-major II, IB, IE, BI, BB, BE, EI, EB, EE). Pattern characters: "*" anything, "T" any non-F value, "F" only F, "0"/"1"/"2" that exact dimension. disjoint = FF*FF****; intersects = not disjoint; touches (not both points) = FT******* or F**T***** or F***T****; within = T*F**F***; contains = T*****FF*; covers = any of T*****FF*, *T****FF*, ***T**FF*, ****T*FF*; overlaps needs equal dimensions and 1*T***T** for lines else T*T***T**; crosses = T*T****** if dimA < dimB, T*****T** if dimA > dimB, 0******** for two lines, otherwise false; equals = T*F**FFF*. Unknown predicates return None.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return True and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return da != 0 and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #93', ['F0FFFF102', 'touches', 0, 1], True), ('regression #121', ['F0FFFFFF2', 'touches', 0, 0], False)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Two points are reported as touching.

Input [matrix, predicate, dimA, dimB] with a 9-character intersection matrix over "F012" (row-major II, IB, IE, BI, BB, BE, EI, EB, EE). Pattern characters: "*" anything, "T" any non-F value, "F" only F, "0"/"1"/"2" that exact dimension. disjoint = FF*FF****; intersects = not disjoint; touches (not both points) = FT******* or F**T***** or F***T****; within = T*F**F***; contains = T*****FF*; covers = any of T*****FF*, *T****FF*, ***T**FF*, ****T*FF*; overlaps needs equal dimensions and 1*T***T** for lines else T*T***T**; crosses = T*T****** if dimA < dimB, T*****T** if dimA > dimB, 0******** for two lines, otherwise false; equals = T*F**FFF*. Unknown predicates return None.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('T*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da <= 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #112', ['0F0FFF0F2', 'overlaps', 0, 0], True), ('regression #115', ['0F1FF0102', 'overlaps', 1, 1], False)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Lines that meet at a single crossing point are reported as overlapping.

Input [matrix, predicate, dimA, dimB] with a 9-character intersection matrix over "F012" (row-major II, IB, IE, BI, BB, BE, EI, EB, EE). Pattern characters: "*" anything, "T" any non-F value, "F" only F, "0"/"1"/"2" that exact dimension. disjoint = FF*FF****; intersects = not disjoint; touches (not both points) = FT******* or F**T***** or F***T****; within = T*F**F***; contains = T*****FF*; covers = any of T*****FF*, *T****FF*, ***T**FF*, ****T*FF*; overlaps needs equal dimensions and 1*T***T** for lines else T*T***T**; crosses = T*T****** if dimA < dimB, T*****T** if dimA > dimB, 0******** for two lines, otherwise false; equals = T*F**FFF*. Unknown predicates return None.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if False:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #33', ['101FF0212', 'overlaps', 1, 2], False), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #54', ['1010F0212', 'overlaps', 1, 2], False), ('regression #124', ['2121F1212', 'overlaps', 2, 1], False)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False), ('regression #124', ['2121F1212', 'overlaps', 2, 1], False)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False), ('regression #124', ['2121F1212', 'overlaps', 2, 1], False)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('control #33', ['101FF0212', 'overlaps', 1, 2], False), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*', '****T*FF*'))
    if pred == 'overlaps':
        if da < db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #33', ['101FF0212', 'overlaps', 1, 2], False), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #54', ['1010F0212', 'overlaps', 1, 2], False), ('regression #124', ['2121F1212', 'overlaps', 2, 1], False)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False), ('regression #124', ['2121F1212', 'overlaps', 2, 1], False)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False), ('regression #124', ['2121F1212', 'overlaps', 2, 1], False)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('control #33', ['101FF0212', 'overlaps', 1, 2], False), ('regression #123', ['1020F1102', 'overlaps', 2, 1], False)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
A line lying partly inside a polygon is reported as overlapping it.

Input [matrix, predicate, dimA, dimB] with a 9-character intersection matrix over "F012" (row-major II, IB, IE, BI, BB, BE, EI, EB, EE). Pattern characters: "*" anything, "T" any non-F value, "F" only F, "0"/"1"/"2" that exact dimension. disjoint = FF*FF****; intersects = not disjoint; touches (not both points) = FT******* or F**T***** or F***T****; within = T*F**F***; contains = T*****FF*; covers = any of T*****FF*, *T****FF*, ***T**FF*, ****T*FF*; overlaps needs equal dimensions and 1*T***T** for lines else T*T***T**; crosses = T*T****** if dimA < dimB, T*****T** if dimA > dimB, 0******** for two lines, otherwise false; equals = T*F**FFF*. Unknown predicates return None.

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*',))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('regression #125', ['F1F0F0FF2', 'covers', 2, 1], True), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True), ('regression #128', ['FF20FFFF2', 'covers', 2, 0], True)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True), ('regression #129', ['F0FFF0FF2', 'covers', 1, 0], True)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #125', ['F1F0F0FF2', 'covers', 2, 1], True), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    matrix, pred, da, db = x
    def match(pattern):
        for m, p in zip(matrix, pattern):
            if p == '*':
                continue
            if p == 'T' and m == 'F':
                return False
            if p == 'F' and m != 'F':
                return False
            if p in '012' and m != p:
                return False
        return True
    if pred == 'disjoint':
        return match('FF*FF****')
    if pred == 'intersects':
        return not match('FF*FF****')
    if pred == 'touches':
        return (da, db) != (0, 0) and (match('FT*******') or match('F**T*****') or match('F***T****'))
    if pred == 'within':
        return match('T*F**F***')
    if pred == 'contains':
        return match('T*****FF*')
    if pred == 'covers':
        return any(match(p) for p in ('T*****FF*', '*T****FF*', '***T**FF*'))
    if pred == 'overlaps':
        if da != db:
            return False
        return match('1*T***T**') if da == 1 else match('T*T***T**')
    if pred == 'crosses':
        if da < db:
            return match('T*T******')
        if da > db:
            return match('T*****T**')
        return da == 1 and match('0********')
    if pred == 'equals':
        return match('T*F**FFF*')
    return None
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', ['FF2F11212', 'crosses', 2, 2], False), ('control #1', ['FF2F11212', 'intersects', 2, 2], True), ('control #2', ['FF2F11212', 'within', 2, 2], False), ('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('regression #125', ['F1F0F0FF2', 'covers', 2, 1], True), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True)], [('control #3', ['FF2F11212', 'touches', 2, 2], True), ('control #4', ['212101212', 'overlaps', 2, 2], True), ('control #5', ['212101212', 'crosses', 2, 2], False), ('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True)], [('control #6', ['212101212', 'touches', 2, 2], False), ('control #7', ['212101212', 'intersects', 2, 2], True), ('control #8', ['2FF1FF212', 'contains', 2, 2], False), ('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True), ('regression #128', ['FF20FFFF2', 'covers', 2, 0], True)], [('control #9', ['2FF1FF212', 'crosses', 2, 2], False), ('control #10', ['2FF1FF212', 'intersects', 2, 2], True), ('control #11', ['2FF1FF212', 'disjoint', 2, 2], False), ('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True), ('regression #129', ['F0FFF0FF2', 'covers', 1, 0], True)], [('control #12', ['212FF1FF2', 'intersects', 2, 2], True), ('control #13', ['212FF1FF2', 'contains', 2, 2], True), ('control #14', ['212FF1FF2', 'covers', 2, 2], True), ('control #15', ['212FF1FF2', 'disjoint', 2, 2], False), ('control #16', ['2FF1FF2F2', 'equals', 2, 2], False), ('control #17', ['2FF1FF2F2', 'disjoint', 2, 2], False), ('regression #125', ['F1F0F0FF2', 'covers', 2, 1], True), ('regression #126', ['FF2F1FFF2', 'covers', 2, 1], True)]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
A polygon does not cover a line that lies on its boundary.

Input [matrix, predicate, dimA, dimB] with a 9-character intersection matrix over "F012" (row-major II, IB, IE, BI, BB, BE, EI, EB, EE). Pattern characters: "*" anything, "T" any non-F value, "F" only F, "0"/"1"/"2" that exact dimension. disjoint = FF*FF****; intersects = not disjoint; touches (not both points) = FT******* or F**T***** or F***T****; within = T*F**F***; contains = T*****FF*; covers = any of T*****FF*, *T****FF*, ***T**FF*, ****T*FF*; overlaps needs equal dimensions and 1*T***T** for lines else T*T***T**; crosses = T*T****** if dimA < dimB, T*****T** if dimA > dimB, 0******** for two lines, otherwise false; equals = T*F**FFF*. Unknown predicates return None.

split: open-access


prompt:
Boxes that merely share a lower-left corner are reported as equal.

Input [a, b], closed boxes [minx, miny, maxx, maxy] with positive width and height. Return "equals" if identical, else "disjoint" if separated with no shared point, else "contains" if a covers b (shared edges allowed), "within" if b covers a, else "touches" if the boxes share only boundary, else "overlaps".

split: open-access


prompt:
Boxes sharing an edge or corner are reported as disjoint.

Input [a, b], closed boxes [minx, miny, maxx, maxy] with positive width and height. Return "equals" if identical, else "disjoint" if separated with no shared point, else "contains" if a covers b (shared edges allowed), "within" if b covers a, else "touches" if the boxes share only boundary, else "overlaps".

split: open-access


prompt:
A box flush against the inside of another is not reported as contained.

Input [a, b], closed boxes [minx, miny, maxx, maxy] with positive width and height. Return "equals" if identical, else "disjoint" if separated with no shared point, else "contains" if a covers b (shared edges allowed), "within" if b covers a, else "touches" if the boxes share only boundary, else "overlaps".

split: open-access


prompt:
A box poking out of the top of another is reported as within.

Input [a, b], closed boxes [minx, miny, maxx, maxy] with positive width and height. Return "equals" if identical, else "disjoint" if separated with no shared point, else "contains" if a covers b (shared edges allowed), "within" if b covers a, else "touches" if the boxes share only boundary, else "overlaps".

split: open-access


prompt:
Boxes stacked vertically are reported as overlapping.

Input [a, b], closed boxes [minx, miny, maxx, maxy] with positive width and height. Return "equals" if identical, else "disjoint" if separated with no shared point, else "contains" if a covers b (shared edges allowed), "within" if b covers a, else "touches" if the boxes share only boundary, else "overlaps".

split: open-access


prompt:
Reversed arcs pull in the neighbouring arc.

Input [arcs, transform, ring]. Each arc is a list of quantized delta positions (the first is absolute, later ones add to the running position within that arc). transform [sx, sy, tx, ty] maps q to q*s + t per axis; a null transform is the identity [1, 1, 0, 0]. A ring lists arc indexes; a negative index i means arc ~i (bitwise complement) traversed backwards. Arcs after the first contribute all but their first position, which duplicates the previous arc end. Return the stitched list of [x, y].

split: open-access


prompt:
Rings that use an arc backwards jump across the shape.

Input [arcs, transform, ring]. Each arc is a list of quantized delta positions (the first is absolute, later ones add to the running position within that arc). transform [sx, sy, tx, ty] maps q to q*s + t per axis; a null transform is the identity [1, 1, 0, 0]. A ring lists arc indexes; a negative index i means arc ~i (bitwise complement) traversed backwards. Arcs after the first contribute all but their first position, which duplicates the previous arc end. Return the stitched list of [x, y].

split: open-access


prompt:
Decoded arcs collapse around the origin.

Input [arcs, transform, ring]. Each arc is a list of quantized delta positions (the first is absolute, later ones add to the running position within that arc). transform [sx, sy, tx, ty] maps q to q*s + t per axis; a null transform is the identity [1, 1, 0, 0]. A ring lists arc indexes; a negative index i means arc ~i (bitwise complement) traversed backwards. Arcs after the first contribute all but their first position, which duplicates the previous arc end. Return the stitched list of [x, y].

split: open-access


prompt:
Decoded coordinates are offset by the translate times the scale.

Input [arcs, transform, ring]. Each arc is a list of quantized delta positions (the first is absolute, later ones add to the running position within that arc). transform [sx, sy, tx, ty] maps q to q*s + t per axis; a null transform is the identity [1, 1, 0, 0]. A ring lists arc indexes; a negative index i means arc ~i (bitwise complement) traversed backwards. Arcs after the first contribute all but their first position, which duplicates the previous arc end. Return the stitched list of [x, y].

split: open-access


prompt:
Unquantized topologies decode every position to the origin.

Input [arcs, transform, ring]. Each arc is a list of quantized delta positions (the first is absolute, later ones add to the running position within that arc). transform [sx, sy, tx, ty] maps q to q*s + t per axis; a null transform is the identity [1, 1, 0, 0]. A ring lists arc indexes; a negative index i means arc ~i (bitwise complement) traversed backwards. Arcs after the first contribute all but their first position, which duplicates the previous arc end. Return the stitched list of [x, y].

split: open-access


prompt:
Stitched rings lose their closing vertex and contain doubled junctions.

Input [arcs, transform, ring]. Each arc is a list of quantized delta positions (the first is absolute, later ones add to the running position within that arc). transform [sx, sy, tx, ty] maps q to q*s + t per axis; a null transform is the identity [1, 1, 0, 0]. A ring lists arc indexes; a negative index i means arc ~i (bitwise complement) traversed backwards. Arcs after the first contribute all but their first position, which duplicates the previous arc end. Return the stitched list of [x, y].

split: open-access


prompt:
Neighbouring polygons with the same winding are never rook-adjacent.

Input [polygons, mode] where each polygon is a closed ring of integer vertices on a noded coverage (shared borders use identical vertices). Rook neighbours share at least one non-degenerate edge irrespective of direction; queen neighbours share at least one vertex. Return, for each polygon index, the ascending list of neighbour indexes (never itself).

split: open-access


prompt:
Adjacency lists are one-sided: later polygons do not list earlier neighbours.

Input [polygons, mode] where each polygon is a closed ring of integer vertices on a noded coverage (shared borders use identical vertices). Rook neighbours share at least one non-degenerate edge irrespective of direction; queen neighbours share at least one vertex. Return, for each polygon index, the ascending list of neighbour indexes (never itself).

split: open-access


prompt:
Polygons meeting only at a corner are missing from queen neighbours.

Input [polygons, mode] where each polygon is a closed ring of integer vertices on a noded coverage (shared borders use identical vertices). Rook neighbours share at least one non-degenerate edge irrespective of direction; queen neighbours share at least one vertex. Return, for each polygon index, the ascending list of neighbour indexes (never itself).

split: open-access


prompt:
Polygons with a repeated corner vertex become rook neighbours of anything sharing that corner.

Input [polygons, mode] where each polygon is a closed ring of integer vertices on a noded coverage (shared borders use identical vertices). Rook neighbours share at least one non-degenerate edge irrespective of direction; queen neighbours share at least one vertex. Return, for each polygon index, the ascending list of neighbour indexes (never itself).

split: open-access


broken_source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ring = x
    if len(ring) < 4:
        return 'too_few_points'
    if ring[0] != ring[-1]:
        return 'not_closed'
    pts = ring[:-1]
    n = len(pts)
    for i in range(n):
        if pts[i] == pts[(i + 1) % n]:
            return 'repeated_point'
    for i in range(n):
        a, b, c = pts[i - 1], pts[i], pts[(i + 1) % n]
        cross = (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0])
        dot = (b[0] - a[0]) * (c[0] - b[0]) + (b[1] - a[1]) * (c[1] - b[1])
        if cross == 0 and dot < 0:
            return 'spike'
    def orient(p, q, r):
        v = (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0])
        return (v > 0) - (v < 0)
    def within(p, q, r):
        return min(p[0], r[0]) <= q[0] <= max(p[0], r[0]) and min(p[1], r[1]) <= q[1] <= max(p[1], r[1])
    def hit(p1, p2, p3, p4):
        o1, o2, o3, o4 = orient(p1, p2, p3), orient(p1, p2, p4), orient(p3, p4, p1), orient(p3, p4, p2)
        if o1 * o2 < 0 and o3 * o4 < 0:
            return True
        return (o1 == 0 and within(p1, p3, p2)) or (o2 == 0 and within(p1, p4, p2)) or (o3 == 0 and within(p3, p1, p4)) or (o4 == 0 and within(p3, p2, p4))
    for i in range(n):
        for j in range(i + 1, n):
            if j == i + 1:
                continue
            if hit(pts[i], pts[(i + 1) % n], pts[j], pts[(j + 1) % n]):
                return 'self_intersection'
    return 'valid'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], 'valid'), ('control #1', [[0, 0], [10, 0], [5, 8], [0, 0]], 'valid'), ('control #2', [[0, 0], [5, 0], [10, 0], [10, 10], [0, 10], [0, 0]], 'valid'), ('regression #3', [[0, 0], [10, 10], [10, 0], [0, 10], [0, 0]], 'self_intersection'), ('regression #4', [[0, 0], [10, 0], [10, 10], [10, 5], [0, 5], [0, 0]], 'spike'), ('regression #5', [[5, 0], [10, 0], [10, 10], [0, 10], [0, 0], [5, 0], [0, 0]], 'not_closed'), ('boundary #6', [[0, 0], [10, 0], [10, 10], [0, 0]], 'valid'), ('regression #22', [[0, 0], [10, 0], [0, 10], [10, 10], [0, 0]], 'self_intersection')], [('control #1', [[0, 0], [10, 0], [5, 8], [0, 0]], 'valid'), ('regression #4', [[0, 0], [10, 0], [10, 10], [10, 5], [0, 5], [0, 0]], 'spike'), ('regression #5', [[5, 0], [10, 0], [10, 10], [0, 10], [0, 0], [5, 0], [0, 0]], 'not_closed'), ('boundary #6', [[0, 0], [10, 0], [10, 10], [0, 0]], 'valid'), ('boundary #7', [[0, 0], [10, 0], [10, 10]], 'too_few_points'), ('boundary #8', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 1]], 'not_closed'), ('boundary #9', [[0, 0], [10, 0], [10, 0], [10, 10], [0, 0]], 'repeated_point'), ('regression #28', [[2, 0], [1, 0], [0, 3], [2, 1], [4, 1], [2, 2], [2, 0]], 'self_intersection')], [('control #2', [[0, 0], [5, 0], [10, 0], [10, 10], [0, 10], [0, 0]], 'valid'), ('boundary #7', [[0, 0], [10, 0], [10, 10]], 'too_few_points'), ('boundary #8', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 1]], 'not_closed'), ('boundary #9', [[0, 0], [10, 0], [10, 0], [10, 10], [0, 0]], 'repeated_point'), ('regression #10', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0], [0, 0]], 'repeated_point'), ('regression #11', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 5], [0, 12], [0, 0]], 'spike'), ('regression #12', [[0, 5], [0, 0], [10, 0], [10, 10], [0, 10], [0, 12], [0, 5]], 'spike'), ('regression #22', [[0, 0], [10, 0], [0, 10], [10, 10], [0, 0]], 'self_intersection')], [('boundary #6', [[0, 0], [10, 0], [10, 10], [0, 0]], 'valid'), ('regression #10', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0], [0, 0]], 'repeated_point'), ('regression #11', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 5], [0, 12], [0, 0]], 'spike'), ('regression #12', [[0, 5], [0, 0], [10, 0], [10, 10], [0, 10], [0, 12], [0, 5]], 'spike'), ('regression #13', [[0, 0], [4, 0], [4, 4], [8, 4], [8, 8], [4, 8], [4, 4], [0, 4], [0, 0]], 'self_intersection'), ('regression #14', [[0, 0], [10, 0], [10, 10], [5, 0], [0, 10], [0, 0]], 'self_intersection'), ('regression #15', [[0, 0], [10, 0], [10, 5], [2, 5], [6, 5], [6, 8], [0, 8], [0, 0]], 'spike'), ('regression #28', [[2, 0], [1, 0], [0, 3], [2, 1], [4, 1], [2, 2], [2, 0]], 'self_intersection')], [('regression #12', [[0, 5], [0, 0], [10, 0], [10, 10], [0, 10], [0, 12], [0, 5]], 'spike'), ('regression #13', [[0, 0], [4, 0], [4, 4], [8, 4], [8, 8], [4, 8], [4, 4], [0, 4], [0, 0]], 'self_intersection'), ('regression #14', [[0, 0], [10, 0], [10, 10], [5, 0], [0, 10], [0, 0]], 'self_intersection'), ('regression #15', [[0, 0], [10, 0], [10, 5], [2, 5], [6, 5], [6, 8], [0, 8], [0, 0]], 'spike'), ('control #16', [[0, 0], [6, 0], [6, 6], [3, 3], [0, 6], [0, 0]], 'valid'), ('regression #17', [[0, 0], [10, 0], [10, 10], [0, 10], [4, 10], [0, 0]], 'spike'), ('control #18', [[1, 1], [9, 2], [8, 9], [2, 7], [1, 1]], 'valid'), ('regression #22', [[0, 0], [10, 0], [0, 10], [10, 10], [0, 0]], 'self_intersection')]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

source:
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x):
    ring = x
    if len(ring) < 4:
        return 'too_few_points'
    if ring[0] != ring[-1]:
        return 'not_closed'
    pts = ring[:-1]
    n = len(pts)
    for i in range(n):
        if pts[i] == pts[(i + 1) % n]:
            return 'repeated_point'
    for i in range(n):
        a, b, c = pts[i - 1], pts[i], pts[(i + 1) % n]
        cross = (b[0] - a[0]) * (c[1] - b[1]) - (b[1] - a[1]) * (c[0] - b[0])
        dot = (b[0] - a[0]) * (c[0] - b[0]) + (b[1] - a[1]) * (c[1] - b[1])
        if cross == 0 and dot < 0:
            return 'spike'
    def orient(p, q, r):
        v = (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0])
        return (v > 0) - (v < 0)
    def within(p, q, r):
        return min(p[0], r[0]) <= q[0] <= max(p[0], r[0]) and min(p[1], r[1]) <= q[1] <= max(p[1], r[1])
    def hit(p1, p2, p3, p4):
        o1, o2, o3, o4 = orient(p1, p2, p3), orient(p1, p2, p4), orient(p3, p4, p1), orient(p3, p4, p2)
        if o1 * o2 < 0 and o3 * o4 < 0:
            return True
        return (o1 == 0 and within(p1, p3, p2)) or (o2 == 0 and within(p1, p4, p2)) or (o3 == 0 and within(p3, p1, p4)) or (o4 == 0 and within(p3, p2, p4))
    for i in range(n):
        for j in range(i + 1, n):
            if j == i + 1 or j == n - 1:
                continue
            if hit(pts[i], pts[(i + 1) % n], pts[j], pts[(j + 1) % n]):
                return 'self_intersection'
    return 'valid'
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('control #0', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0]], 'valid'), ('control #1', [[0, 0], [10, 0], [5, 8], [0, 0]], 'valid'), ('control #2', [[0, 0], [5, 0], [10, 0], [10, 10], [0, 10], [0, 0]], 'valid'), ('regression #3', [[0, 0], [10, 10], [10, 0], [0, 10], [0, 0]], 'self_intersection'), ('regression #4', [[0, 0], [10, 0], [10, 10], [10, 5], [0, 5], [0, 0]], 'spike'), ('regression #5', [[5, 0], [10, 0], [10, 10], [0, 10], [0, 0], [5, 0], [0, 0]], 'not_closed'), ('boundary #6', [[0, 0], [10, 0], [10, 10], [0, 0]], 'valid'), ('regression #22', [[0, 0], [10, 0], [0, 10], [10, 10], [0, 0]], 'self_intersection')], [('control #1', [[0, 0], [10, 0], [5, 8], [0, 0]], 'valid'), ('regression #4', [[0, 0], [10, 0], [10, 10], [10, 5], [0, 5], [0, 0]], 'spike'), ('regression #5', [[5, 0], [10, 0], [10, 10], [0, 10], [0, 0], [5, 0], [0, 0]], 'not_closed'), ('boundary #6', [[0, 0], [10, 0], [10, 10], [0, 0]], 'valid'), ('boundary #7', [[0, 0], [10, 0], [10, 10]], 'too_few_points'), ('boundary #8', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 1]], 'not_closed'), ('boundary #9', [[0, 0], [10, 0], [10, 0], [10, 10], [0, 0]], 'repeated_point'), ('regression #28', [[2, 0], [1, 0], [0, 3], [2, 1], [4, 1], [2, 2], [2, 0]], 'self_intersection')], [('control #2', [[0, 0], [5, 0], [10, 0], [10, 10], [0, 10], [0, 0]], 'valid'), ('boundary #7', [[0, 0], [10, 0], [10, 10]], 'too_few_points'), ('boundary #8', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 1]], 'not_closed'), ('boundary #9', [[0, 0], [10, 0], [10, 0], [10, 10], [0, 0]], 'repeated_point'), ('regression #10', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0], [0, 0]], 'repeated_point'), ('regression #11', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 5], [0, 12], [0, 0]], 'spike'), ('regression #12', [[0, 5], [0, 0], [10, 0], [10, 10], [0, 10], [0, 12], [0, 5]], 'spike'), ('regression #22', [[0, 0], [10, 0], [0, 10], [10, 10], [0, 0]], 'self_intersection')], [('boundary #6', [[0, 0], [10, 0], [10, 10], [0, 0]], 'valid'), ('regression #10', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 0], [0, 0]], 'repeated_point'), ('regression #11', [[0, 0], [10, 0], [10, 10], [0, 10], [0, 5], [0, 12], [0, 0]], 'spike'), ('regression #12', [[0, 5], [0, 0], [10, 0], [10, 10], [0, 10], [0, 12], [0, 5]], 'spike'), ('regression #13', [[0, 0], [4, 0], [4, 4], [8, 4], [8, 8], [4, 8], [4, 4], [0, 4], [0, 0]], 'self_intersection'), ('regression #14', [[0, 0], [10, 0], [10, 10], [5, 0], [0, 10], [0, 0]], 'self_intersection'), ('regression #15', [[0, 0], [10, 0], [10, 5], [2, 5], [6, 5], [6, 8], [0, 8], [0, 0]], 'spike'), ('regression #28', [[2, 0], [1, 0], [0, 3], [2, 1], [4, 1], [2, 2], [2, 0]], 'self_intersection')], [('regression #12', [[0, 5], [0, 0], [10, 0], [10, 10], [0, 10], [0, 12], [0, 5]], 'spike'), ('regression #13', [[0, 0], [4, 0], [4, 4], [8, 4], [8, 8], [4, 8], [4, 4], [0, 4], [0, 0]], 'self_intersection'), ('regression #14', [[0, 0], [10, 0], [10, 10], [5, 0], [0, 10], [0, 0]], 'self_intersection'), ('regression #15', [[0, 0], [10, 0], [10, 5], [2, 5], [6, 5], [6, 8], [0, 8], [0, 0]], 'spike'), ('control #16', [[0, 0], [6, 0], [6, 6], [3, 3], [0, 6], [0, 0]], 'valid'), ('regression #17', [[0, 0], [10, 0], [10, 10], [0, 10], [4, 10], [0, 0]], 'spike'), ('control #18', [[1, 1], [9, 2], [8, 9], [2, 7], [1, 1]], 'valid'), ('regression #22', [[0, 0], [10, 0], [0, 10], [10, 10], [0, 0]], 'self_intersection')]]
for label, args, expected in fixtures[N-1]:
    check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)

prompt:
Every valid ring is reported as self-intersecting.

Input: one ring as a list of integer [x, y]. Report the first failing check in this order: fewer than 4 positions "too_few_points"; first != last "not_closed"; two cyclically consecutive equal vertices "repeated_point"; a vertex where the boundary reverses direction along a line (collinear with a negative dot product of the incoming and outgoing edge, checked cyclically) "spike"; any two non-adjacent edges sharing a point (crossing, touching or collinear overlap) "self_intersection"; otherwise "valid".

split: open-access