"""Explicit layouts for n = 3..60 cards, each with its sets counted directly
over the whole 81-card deck.

n <= 27: third.c's witness, inside the 27 cards whose fourth digit is 0.
n >= 28: all 27 cards with fourth digit 0, plus a cards with fourth digit 1 and
b with fourth digit 2 (each the best a or b cards of a third, from third.c).
Every pair across those two parts completes a set whose third card has fourth
digit 0, so the layout holds 117 + g(a) + g(b) + ab sets.
n = 60: the 60 cards left out of the 21-card layout with 3 sets in
out/few2.txt; they hold 450 - 3 = 447 sets.

  python3 witness.py > out/witnesses.txt
"""
from itertools import combinations
import os

here = os.path.dirname(os.path.abspath(__file__))
best = {}  # n -> (lines, cards as 3-digit strings)
with open(os.path.join(here, 'out', 'third.txt')) as f:
    rows = f.read().split('witnesses (n, lines, cards):')[1].split('\n')
for r in rows:
    if r.strip():
        n, lines, *cards = r.split()
        best[int(n)] = (int(lines), [c[:3] for c in cards])
best[0], best[1], best[2] = (0, []), (0, ['000']), (0, ['000', '100'])


def sets_in(cards):
    pts = set(cards)
    c = 0
    for x, y in combinations(cards, 2):
        z = ''.join(str((-int(a) - int(b)) % 3) for a, b in zip(x, y))
        if z in pts:
            c += 1
    assert c % 3 == 0
    return c // 3


def layout(n):
    if n == 60:
        with open(os.path.join(here, 'out', 'few2.txt')) as f:
            row = f.read().strip().split('\n')[-1]
        return [f'{i % 3}{i // 3 % 3}{i // 9 % 3}{i // 27}' for i in range(81) if row[i] == '0']
    if n <= 27:
        return [c + '0' for c in best[n][1]]
    a_best = max(range(max(0, n - 54), min(27, n - 27) + 1),
                 key=lambda a: best[a][0] + best[n - 27 - a][0] + a * (n - 27 - a))
    full = [f'{i % 3}{i // 3 % 3}{i // 9}' for i in range(27)]
    return [c + '0' for c in full] + [c + '1' for c in best[a_best][1]] + \
        [c + '2' for c in best[n - 27 - a_best][1]]


for n in range(3, 61):
    cards = layout(n)
    assert len(set(cards)) == n
    print(n, sets_in(cards), ' '.join(cards))
