"""Try an elegant 6-day construction: pick ONE base partition P of the 4x6 grid and take the 6 days to be P rotated by the column-shift sigma (c -> c+1 mod 6). Person (r,c) <-> index 6r+c. sigma fixes rows. If some P makes the 6 rotations cover all 276 pairs, that's a fully symmetric construction.""" import random, json from itertools import combinations from lib import verify, all_pairs N = 24 def idx(r, c): return 6 * r + c def rc(p): return divmod(p, 6) def sigma(p, k=1): r, c = rc(p) return idx(r, (c + k) % 6) def rotate_partition(P, k): return [[sigma(p, k) for p in boat] for boat in P] def covered_by(P): cov = set() for k in range(6): day = rotate_partition(P, k) for boat in day: for a, b in combinations(sorted(boat), 2): cov.add((a, b)) return cov def random_partition(rng): people = list(range(N)); rng.shuffle(people) return [people[i*6:(i+1)*6] for i in range(4)] def search(trials=300000, seed=0): rng = random.Random(seed) need = all_pairs() best = None; best_missing = 999 for t in range(trials): P = random_partition(rng) cov = covered_by(P) miss = len(need - cov) if miss < best_missing: best_missing = miss; best = [b[:] for b in P] if miss == 0: return best, 0, t return best, best_missing, trials if __name__ == "__main__": P, miss, t = search() print("best missing for cyclic-6 (single base, 6 column-rotations):", miss, "at trial", t) if miss == 0: days = [rotate_partition(P, k) for k in range(6)] days = [[sorted(b) for b in day] for day in days] ok, info = verify(days) print("verify:", ok, "excess:", info['repeat_excess']) print("base partition P (as 4x6-grid indices):", [sorted(b) for b in P]) json.dump(days, open("solution6_cyclic.json", "w")) print("saved solution6_cyclic.json")