TheAlgorithms/Python · error · ValueError

a gon ring should have a length that is a multiple of 3

Error message

a gon ring should have a length that is a multiple of 3

What it means

Raised by is_magic_gon() in project_euler/problem_068/sol1.py when the numbers list length is not a multiple of 3. The gon ring is represented as triplets (outer, inner_a, inner_b) per side, so the list must have exactly 3 * gon_side entries; any other length makes the slicing logic meaningless and is rejected.

Source

Thrown at project_euler/problem_068/sol1.py:123

    """
    Check if the solution set is a magic n-gon ring
    Check that the first number is the smallest number on the outer ring
    Take a list, and check if the sum of each 3 numbers chunk is equal to the same total

    >>> is_magic_gon([4, 2, 3, 5, 3, 1, 6, 1, 2])
    True
    >>> is_magic_gon([4, 3, 2, 6, 2, 1, 5, 1, 3])
    True
    >>> is_magic_gon([2, 3, 5, 4, 5, 1, 6, 1, 3])
    True
    >>> is_magic_gon([1, 2, 3, 4, 5, 6, 7, 8, 9])
    False
    >>> is_magic_gon([1])
    Traceback (most recent call last):
    ValueError: a gon ring should have a length that is a multiple of 3
    """
    if len(numbers) % 3 != 0:
        raise ValueError("a gon ring should have a length that is a multiple of 3")

    if min(numbers[::3]) != numbers[0]:
        return False

    total = sum(numbers[:3])

    return all(sum(numbers[i : i + 3]) == total for i in range(3, len(numbers), 3))


if __name__ == "__main__":
    print(solution())

View on GitHub (pinned to f5988cc097)

Solutions

  1. Pass generate_gon_ring(gon_side, perm) output, which is always 3*gon_side long.
  2. Check length before calling: assert len(numbers) == 3 * gon_side.
  3. If building rings manually, append exactly three entries per side.

Example fix

# before
numbers = list(perm)  # 2*gon_side flat permutation
is_magic_gon(numbers)  # ValueError

# after
numbers = generate_gon_ring(gon_side, list(perm))
is_magic_gon(numbers)
Defensive patterns

Strategy: validation

Validate before calling

ring = generate_gon_ring(gon_side, list(perm))
assert len(ring) == 3 * gon_side
ok = is_magic_gon(ring)

Type guard

def is_gon_ring_shaped(numbers, gon_side) -> bool:
    return isinstance(numbers, list) and len(numbers) == 3 * gon_side

Try / catch

try:
    ok = is_magic_gon(numbers)
except ValueError:
    logger.error("ring length %d not a multiple of 3", len(numbers))
    raise

Prevention

When it happens

Trigger: is_magic_gon([1]) (length 1), is_magic_gon([1,2,3,4]) (length 4), or building a 4-gon ring but passing a 9-element list (should be 12). Passing a flat permutation of 2*gon_side numbers instead of the expanded 3*gon_side ring also triggers it.

Common situations: Calling is_magic_gon directly with raw permutations instead of generate_gon_ring output; changing gon_side but reusing a hardcoded ring list; off-by-one when slicing concatenated triplets.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/c93baf732d033048. Report an issue: GitHub.