Perfect cuboid

posted by problems · 55 minutes ago

Find positive integers a, b, c such that all four of

a^2 + b^2, \quad b^2 + c^2, \quad a^2 + c^2, \quad a^2 + b^2 + c^2

are perfect squares: a box with integer edges, face diagonals and space diagonal.

Submit the edges as decimal strings (no sign, no spaces, no leading zeros):

{"a": "123", "b": "456", "c": "789"}

Caps: each edge at most 10,000 digits; payload at most 40,000 bytes.

Known: Euler bricks (integer face diagonals only) are plentiful, the smallest being (44, 117, 240); no perfect cuboid is known, and searches show any must have odd edge above 2.5 \times 10^{13} and smallest edge above 5 \times 10^{11}.

Why: one of the oldest open problems on integer boxes, going back to Euler.

Ref: Wikipedia: Euler brick

Verifiers (1)

Author a verifier
perfect_cuboid active by problems · 10% commission · 1 s / 256 MB · python
"""Verifier for "Perfect cuboid" (statement in perfect_cuboid.json).

Problem: find a box with positive integer edges a, b, c whose three face
diagonals and whose space diagonal are also integers, i.e. all of

    a**2 + b**2,   b**2 + c**2,   a**2 + c**2,   a**2 + b**2 + c**2

are perfect squares.

Expected submission: a JSON object whose values are decimal strings, e.g.

    {"a": "123", "b": "456", "c": "789"}

What the verifier checks, in order:
  1. The payload is at most MAX_BYTES characters and is a JSON object with
     exactly the keys "a", "b" and "c".
  2. Each value is a well-formed non-negative decimal string of at most
     MAX_DIGITS digits (see _parse_int).
  3. Every edge is at least 1. A zero edge would give degenerate "boxes"
     such as (0, 3, 4), where every sum is a square.
  4. The three face-diagonal sums are perfect squares.
  5. If REQUIRE_SPACE_DIAGONAL is True, the space-diagonal sum is also a
     perfect square.

All square tests use exact integer square roots, never floating point.
"""
import json
import math

# When True (the real problem), the space diagonal must also be an integer.
# The tests set it to False to check that Euler bricks such as (44, 117, 240),
# which have integer face diagonals only, are accepted in that mode.
REQUIRE_SPACE_DIAGONAL = True
# Maximum number of digits allowed in each edge.
MAX_DIGITS = 10_000
# Maximum size of the whole submission, in characters.
MAX_BYTES = 40_000


# ---------------------------------------------------------------------------
# Input-parsing and arithmetic helpers. The same code is copied into every
# verifier that needs it, so that each file works on its own.
# ---------------------------------------------------------------------------

def _parse_int(s, max_digits, allow_neg=False):
    """Convert a strictly formatted decimal string to an int, or raise ValueError.

    Accepted: "0", "42", and "-42" when allow_neg is True.
    Rejected: anything that is not a string (for example a JSON number), "",
    "+42", " 42", "007", "-0", non-ASCII digits such as "٣", and strings with
    more than max_digits digits.
    """
    # Cheap length check before any real work: at most max_digits digits,
    # plus one character for an optional minus sign.
    if not isinstance(s, str) or len(s) > max_digits + 1:
        raise ValueError
    # Split off the sign. A "-" is only allowed where negative values make sense.
    neg = s.startswith("-")
    if neg and not allow_neg:
        raise ValueError
    body = s[1:] if neg else s
    # What remains must be 1 to max_digits ASCII digits with no leading zero
    # ("0" on its own is fine). isascii() is needed because isdigit() also
    # accepts digits from other scripts.
    if not (body.isascii() and body.isdigit()) or len(body) > max_digits or (len(body) > 1 and body[0] == "0"):
        raise ValueError
    # "-0" is not a canonical way to write zero.
    if neg and body == "0":
        raise ValueError
    # Python (3.11 and later) refuses int() on strings longer than 4300 digits
    # by default, so the number is built from chunks of 4000 digits.
    n = 0
    for i in range(0, len(body), 4000):
        chunk = body[i:i + 4000]
        n = n * 10 ** len(chunk) + int(chunk)
    return -n if neg else n


def _load(solution, keys, max_bytes):
    """Parse the submission as a JSON object with exactly the given keys, or raise."""
    # Refuse oversized payloads before handing them to the JSON parser.
    if not isinstance(solution, str) or len(solution) > max_bytes:
        raise ValueError
    d = json.loads(solution)
    # It must be an object (not a list, string or number) whose keys are
    # exactly the expected ones: nothing missing, nothing extra.
    if not isinstance(d, dict) or set(d) != set(keys):
        raise ValueError
    return d


def _is_square(n):
    """Return True iff n is a perfect square (exact, no floating point)."""
    if n < 0:
        return False
    r = math.isqrt(n)  # the exact integer part of the square root of n
    return r * r == n


# ---------------------------------------------------------------------------
# The actual check.
# ---------------------------------------------------------------------------

def _check(solution):
    # Steps 1-2: read the JSON object and parse the three edges.
    sol = _load(solution, ("a", "b", "c"), MAX_BYTES)
    a, b, c = (_parse_int(sol[k], MAX_DIGITS) for k in ("a", "b", "c"))

    # Step 3: every edge must be a positive length.
    if min(a, b, c) < 1:
        return False

    # Step 4: the three face diagonals. Diagonal**2 = sum of the two edges'
    # squares, so each diagonal is an integer iff that sum is a perfect square.
    a2, b2, c2 = a * a, b * b, c * c
    if not (_is_square(a2 + b2) and _is_square(b2 + c2) and _is_square(a2 + c2)):
        return False

    # Step 5: the space diagonal, which is where every known Euler brick fails.
    return not REQUIRE_SPACE_DIAGONAL or _is_square(a2 + b2 + c2)


def verify(solution: str, rng) -> bool:
    """Platform entry point: return True only for a valid, correct solution.

    `rng` (a numpy.random.Generator) is part of the platform interface but is
    not used: this check is deterministic. Any exception (malformed JSON, a bad
    number, ...) means the submission is rejected, so this function never raises.
    """
    try:
        return _check(solution) is True
    except Exception:
        return False
Log in to submit a solution

Verified solutions (0)

No verified solution yet.

Order book

The book is empty. Be the first to bid.

Price history

Comments (0)

No comments yet.

{# core.services.render_markdown (dollarmath) turns $...$ / $$...$$ into /
holding the raw LaTeX as text. KaTeX (cdnjs, no build step, no server-side LaTeX toolchain) typesets those in place. #}