50 lines
1.3 KiB
Python
50 lines
1.3 KiB
Python
"""
|
|
core/wheeling.py
|
|
----------------
|
|
Full-cover number wheeling.
|
|
|
|
wheel_count(numbers, k) — C(n, k) ticket count preview
|
|
wheel_full(numbers, k) — all C(n, k) sorted combinations
|
|
|
|
Raises ValueError for invalid inputs or if result exceeds MAX_TICKETS.
|
|
"""
|
|
|
|
from itertools import combinations
|
|
from math import comb
|
|
|
|
MAX_TICKETS = 200
|
|
|
|
|
|
def wheel_count(numbers: list | set, k: int) -> int:
|
|
"""Return how many tickets a full wheel would produce (C(n, k))."""
|
|
n = len(set(numbers))
|
|
if k < 1 or k > n:
|
|
return 0
|
|
return comb(n, k)
|
|
|
|
|
|
def wheel_full(numbers: list | set, k: int) -> list[list[int]]:
|
|
"""
|
|
Generate all C(n, k) combinations from *numbers*, each sorted ascending.
|
|
Duplicates in input are removed before wheeling.
|
|
Raises ValueError if k is out of range or count > MAX_TICKETS.
|
|
"""
|
|
pool = sorted(set(numbers))
|
|
n = len(pool)
|
|
|
|
if k < 1:
|
|
raise ValueError("Pick count must be at least 1.")
|
|
if k > n:
|
|
raise ValueError(
|
|
f"Pick count ({k}) exceeds the number pool size ({n})."
|
|
)
|
|
|
|
count = comb(n, k)
|
|
if count > MAX_TICKETS:
|
|
raise ValueError(
|
|
f"Wheel would produce {count:,} tickets (max {MAX_TICKETS:,}). "
|
|
f"Reduce your pool or pick count."
|
|
)
|
|
|
|
return [sorted(combo) for combo in combinations(pool, k)]
|