#include <stdio.h>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
#include <numeric>
#include <stdio.h>
#include <string.h>
#include <assert.h>
using namespace std;
static const double EPS = 1e-9;
int ROUND(double x) { return (int)(x+0.5); }
bool ISINT(double x) { return fabs(ROUND(x)-x)<=EPS; }
bool ISEQUAL(double x,double y) { return fabs(x-y)<=EPS*max(1.0,max(fabs(x),fabs(y))); }
double SQSUM(double x,double y) { return x*x+y*y; }
template<class T> bool INRANGE(T x,T a,T b) { return a<=x&&x<=b; }
#define PI (acos(-1))
#define ARRAY_NUM(a) (sizeof(a)/sizeof(a[0]))
#define NG (-1)
#define BIG (123456789)
#define BIGBIG (987654321987654321LL)
#define SZ(a) ((int)((a).size()))
#define SQ(a) ((a)*(a))
typedef long long ll;
typedef unsigned long long ull;
#define FOR(v,i) for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i)
// BEGIN CUT HERE
#undef FOR
#define FOR(v,i) for(auto i=(v).begin();i!=(v).end();++i)
// END CUT HERE
class Dinic
{
public:
Dinic(int input_maxv) : maxv(input_maxv)
{
G.resize(input_maxv);
level.resize(input_maxv);
iter.resize(input_maxv);
}
void add_edge_both(int from, int to, int cap)
{
const int rev_from = SZ(G[from]);
const int rev_to = SZ(G[to]);
G[from].push_back(edge(to,cap,rev_to));
G[to].push_back(edge(from,cap,rev_from));
}
void add_edge(int from, int to, int cap)
{
const int rev_from = SZ(G[from]);
const int rev_to = SZ(G[to]);
G[from].push_back(edge(to,cap,rev_to));
G[to].push_back(edge(from,0,rev_from));
}
// sããtã¸ã®æ大æµãæ±ãã
int max_flow(int s, int t)
{
int flow = 0;
for(;;)
{
bfs(s);
if(level[t]<0) break;
fill(iter.begin(),iter.end(),0);
int f;
while( (f=dfs(s,t,DINIC_INF))>0)
{
flow += f;
}
}
return flow;
}
// ãã¼ãsãã辿ããç¯å²ãæ±ããï¼ãã以ä¸æµããªãã¨ããcap=0ã¯ããªã³ã¯ããªããªãï¼
// ï¼æµãçµãã£ããã¨sourceãããã©ããç¯å²ããæå°ã«ããæã®så´ããã©ããªãæ³ãtå´ããã®å¢çãã«ããããã¨ãããï¼
vector <bool> get_nodes_in_group(int s)
{
vector <bool> ret(maxv);
queue<int> que;
que.push(s);
while(!que.empty())
{
int v = que.front();
que.pop();
ret[v]=true;
for(int i=0;i<SZ(G[v]);i++)
{
edge &e = G[v][i];
if(e.cap>0 && !ret[e.to])
{
que.push(e.to);
}
}
}
return ret;
}
void disp()
{
for (int v = 0; v < maxv; v++)
{
printf("%d:",v);
for(int i=0;i<SZ(G[v]);i++)
{
if(G[v][i].init_cap>0)
{
printf("->%d(%d),",G[v][i].to,G[v][i].init_cap);
}
}
printf("\n");
}
}
private:
// sããã®æçè·é¢ãBFSã§è¨ç®ãã
void bfs(int s)
{
fill(level.begin(),level.end(),NG);
queue<int> que;
level[s]=0;
que.push(s);
while(!que.empty())
{
int v = que.front();
que.pop();
for(int i=0;i<SZ(G[v]);i++)
{
edge &e = G[v][i];
if(e.cap>0 && level[e.to]<0)
{
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
}
// å¢å ãã¹ãDFSã§æ¢ã
int dfs(int v, int t, int f)
{
if(v==t) return f;
for (int &i=iter[v];i<SZ(G[v]);i++)
{
edge& e = G[v][i];
if(e.cap>0 && level[v]<level[e.to])
{
int d = dfs(e.to, t, min(f, e.cap));
if(d>0)
{
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
static const int DINIC_INF = INT_MAX; // 容éãllã«ãããã¨ãã¯ããããå¤ãã
struct edge
{
edge(int input_to, int input_cap, int input_rev) : to(input_to), cap(input_cap), rev(input_rev), init_cap(input_cap) {}
int to; // è¡å
int cap; // 容é
int rev; // é辺
int init_cap; // åæ容éï¼ãããã°ç¨ï¼
};
int maxv;
vector < vector <edge> > G; // ã°ã©ãã®é£æ¥ãªã¹ã
vector < int > level; // sããã®è·é¢
vector < int > iter; // ã©ãã¾ã§èª¿ã¹çµãã£ãã
};
int main()
{
int T;
cin >> T;
for (int testcase = 0; testcase < T; testcase++)
{
int M,N;
cin >> M >> N;
const int S = M*N;
const int T = S+1;
const int V = T+1;
vector <string> vs;
for (int y = 0; y < M; y++)
{
string s;
cin >> s;
vs.push_back(s);
}
const static int dy[] = {-1, 0, 1, 0}; // U,R,D,L
const static int dx[] = { 0, 1, 0,-1};
Dinic* dinic = new Dinic(V);
int default_score = 0;
for (int y = 0; y < M; y++)
{
for (int x = 0; x < N; x++)
{
const int now = y*N+x;
if((x+y)%2==0)
{
if(vs[y][x]=='?')
{
default_score += 4;
// dinic->add_edge(S,now,0);
dinic->add_edge(now,T,4);
for(int d = 0; d < 4; d++)
{
const int ny = y+dy[d];
const int nx = x+dx[d];
const int next = ny*N+nx;
if(INRANGE(ny,0,M-1)&&INRANGE(nx,0,N-1))
{
if(vs[ny][nx]=='#' || vs[ny][nx]=='?')
{
dinic->add_edge(next,now,2);
}
}
}
}
else if (vs[y][x]=='#')
{
default_score += 4;
dinic->add_edge(now,T,BIG);
for(int d = 0; d < 4; d++)
{
const int ny = y+dy[d];
const int nx = x+dx[d];
if(INRANGE(ny,0,M-1)&&INRANGE(nx,0,N-1))
{
if(vs[ny][nx]=='#')
{
default_score -= 2;
}
}
}
}
}
else
{
if(vs[y][x]=='?')
{
default_score += 4;
dinic->add_edge(S,now,4);
// dinic->add_edge(now,T,0);
for(int d = 0; d < 4; d++)
{
const int ny = y+dy[d];
const int nx = x+dx[d];
const int next = ny*N+nx;
if(INRANGE(ny,0,M-1)&&INRANGE(nx,0,N-1))
{
if(vs[ny][nx]=='#')
{
dinic->add_edge(now,next,2);
}
}
}
}
else if (vs[y][x]=='#')
{
default_score += 4;
dinic->add_edge(S,now,BIG);
}
}
}
}
printf("Case #%d: %d\n",testcase+1,default_score - dinic->max_flow(S,T));
delete dinic;
}
return 0;
}
I2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxjc3RkaW8+CiNpbmNsdWRlIDxjc3RkbGliPgojaW5jbHVkZSA8Y21hdGg+CiNpbmNsdWRlIDxjbGltaXRzPgojaW5jbHVkZSA8Y2Zsb2F0PgojaW5jbHVkZSA8bWFwPgojaW5jbHVkZSA8dXRpbGl0eT4KI2luY2x1ZGUgPHNldD4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWVtb3J5PgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8dmVjdG9yPgojaW5jbHVkZSA8YWxnb3JpdGhtPgojaW5jbHVkZSA8ZnVuY3Rpb25hbD4KI2luY2x1ZGUgPHNzdHJlYW0+CiNpbmNsdWRlIDxjb21wbGV4PgojaW5jbHVkZSA8c3RhY2s+CiNpbmNsdWRlIDxxdWV1ZT4KI2luY2x1ZGUgPG51bWVyaWM+CiNpbmNsdWRlIDxzdGRpby5oPgojaW5jbHVkZSA8c3RyaW5nLmg+CiNpbmNsdWRlIDxhc3NlcnQuaD4KCnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnN0YXRpYyBjb25zdCBkb3VibGUgRVBTID0gMWUtOTsKaW50IFJPVU5EKGRvdWJsZSB4KSB7IHJldHVybiAoaW50KSh4KzAuNSk7IH0KYm9vbCBJU0lOVChkb3VibGUgeCkgeyByZXR1cm4gZmFicyhST1VORCh4KS14KTw9RVBTOyB9CmJvb2wgSVNFUVVBTChkb3VibGUgeCxkb3VibGUgeSkgeyByZXR1cm4gZmFicyh4LXkpPD1FUFMqbWF4KDEuMCxtYXgoZmFicyh4KSxmYWJzKHkpKSk7IH0KZG91YmxlIFNRU1VNKGRvdWJsZSB4LGRvdWJsZSB5KSB7IHJldHVybiB4KngreSp5OyB9CnRlbXBsYXRlPGNsYXNzIFQ+IGJvb2wgSU5SQU5HRShUIHgsVCBhLFQgYikgeyByZXR1cm4gYTw9eCYmeDw9YjsgfQojZGVmaW5lIFBJCShhY29zKC0xKSkKI2RlZmluZSBBUlJBWV9OVU0oYSkgKHNpemVvZihhKS9zaXplb2YoYVswXSkpIAojZGVmaW5lIE5HICgtMSkKI2RlZmluZSBCSUcgKDEyMzQ1Njc4OSkKI2RlZmluZSBCSUdCSUcgKDk4NzY1NDMyMTk4NzY1NDMyMUxMKQojZGVmaW5lIFNaKGEpICgoaW50KSgoYSkuc2l6ZSgpKSkKI2RlZmluZSBTUShhKSAoKGEpKihhKSkKdHlwZWRlZiBsb25nIGxvbmcgbGw7CnR5cGVkZWYgdW5zaWduZWQgbG9uZyBsb25nIHVsbDsKCiNkZWZpbmUgRk9SKHYsaSkgZm9yKF9fdHlwZW9mKCh2KS5iZWdpbigpKWk9KHYpLmJlZ2luKCk7aSE9KHYpLmVuZCgpOysraSkKLy8gQkVHSU4gQ1VUIEhFUkUKI3VuZGVmIEZPUgojZGVmaW5lIEZPUih2LGkpIGZvcihhdXRvIGk9KHYpLmJlZ2luKCk7aSE9KHYpLmVuZCgpOysraSkKLy8gRU5EIENVVCBIRVJFCgogCmNsYXNzIERpbmljCnsKcHVibGljOgogICAgRGluaWMoaW50IGlucHV0X21heHYpIDogbWF4dihpbnB1dF9tYXh2KQogICAgewogICAgICAgIEcucmVzaXplKGlucHV0X21heHYpOwogICAgICAgIGxldmVsLnJlc2l6ZShpbnB1dF9tYXh2KTsKICAgICAgICBpdGVyLnJlc2l6ZShpbnB1dF9tYXh2KTsKICAgIH0KIAogICAgdm9pZCBhZGRfZWRnZV9ib3RoKGludCBmcm9tLCBpbnQgdG8sIGludCBjYXApCiAgICB7CiAgICAgICAgY29uc3QgaW50IHJldl9mcm9tICA9IFNaKEdbZnJvbV0pOwogICAgICAgIGNvbnN0IGludCByZXZfdG8gICAgPSBTWihHW3RvXSk7CiAgICAgICAgR1tmcm9tXS5wdXNoX2JhY2soZWRnZSh0byxjYXAscmV2X3RvKSk7CiAgICAgICAgR1t0b10ucHVzaF9iYWNrKGVkZ2UoZnJvbSxjYXAscmV2X2Zyb20pKTsKICAgIH0KIAogICAgdm9pZCBhZGRfZWRnZShpbnQgZnJvbSwgaW50IHRvLCBpbnQgY2FwKQogICAgewogICAgICAgIGNvbnN0IGludCByZXZfZnJvbSAgPSBTWihHW2Zyb21dKTsKICAgICAgICBjb25zdCBpbnQgcmV2X3RvICAgID0gU1ooR1t0b10pOwogICAgICAgIEdbZnJvbV0ucHVzaF9iYWNrKGVkZ2UodG8sY2FwLHJldl90bykpOwogICAgICAgIEdbdG9dLnB1c2hfYmFjayhlZGdlKGZyb20sMCxyZXZfZnJvbSkpOwogICAgfQogCiAgICAvLyBzw6PCgcKLw6PCgsKJdMOjwoHCuMOjwoHCrsOmwpzCgMOlwqTCp8OmwrXCgcOjwoLCksOmwrHCgsOjwoLCgcOjwoLCiwogICAgaW50IG1heF9mbG93KGludCBzLCBpbnQgdCkKICAgIHsKICAgICAgICBpbnQgZmxvdyA9IDA7CiAgICAgICAgZm9yKDs7KQogICAgICAgIHsKICAgICAgICAgICAgYmZzKHMpOwogICAgICAgICAgICBpZihsZXZlbFt0XTwwKSBicmVhazsKICAgICAgICAgICAgZmlsbChpdGVyLmJlZ2luKCksaXRlci5lbmQoKSwwKTsKICAgICAgICAgICAgaW50IGY7CiAgICAgICAgICAgIHdoaWxlKCAoZj1kZnMocyx0LERJTklDX0lORikpPjApCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGZsb3cgKz0gZjsKICAgICAgICAgICAgfQogICAgICAgIH0KIAogICAgICAgIHJldHVybiBmbG93OwogICAgfQogCiAgICAvLyAgw6PCg8KOw6PCg8K8w6PCg8KJc8OjwoHCi8OjwoLCicOowr7Cv8OjwoLCjMOjwoLCi8Onwq/ChMOlwpvCssOjwoLCksOmwrHCgsOjwoLCgcOjwoLCi8OvwrzCiMOjwoHCk8OjwoLCjMOkwrvCpcOkwrjCisOmwrXCgcOjwoHCm8OjwoHCqsOjwoHChMOjwoHCqMOjwoHCk8OjwoLCjWNhcD0ww6PCgcKvw6PCgMKBw6PCg8Kqw6PCg8Kzw6PCgsKvw6PCgcKMw6PCgcKqw6PCgcKPw6PCgcKqw6PCgsKLw6/CvMKJCiAgICAvLyDDr8K8wojDpsK1woHDo8KBwpfDp8K1woLDo8KCwo/Do8KBwqPDo8KBwp/Do8KBwoLDo8KBwqhzb3VyY2XDo8KBwovDo8KCwonDo8KBwp/Do8KBwqnDo8KCwozDo8KCwovDp8KvwoTDpcKbwrLDo8KBwozDo8KAwoHDpsKcwoDDpcKwwo/Do8KCwqvDo8KDwoPDo8KDwojDpsKZwoLDo8KBwq5zw6XCgcK0w6PCgMKCw6PCgcKfw6PCgcKpw6PCgsKMw6PCgcKqw6PCgcKEw6bCs8KVw6PCgcKMdMOlwoHCtMOjwoDCgsOjwoHCncOjwoHCrsOlwqLCg8OnwpXCjMOjwoHCjMOjwoLCq8OjwoPCg8OjwoPCiMOjwoHCmcOjwoLCi8OjwoHCqMOjwoHCk8OjwoLCjcOjwoDCgsOvwrzCiQogICAgdmVjdG9yIDxib29sPiBnZXRfbm9kZXNfaW5fZ3JvdXAoaW50IHMpCiAgICB7CiAgICAgICAgdmVjdG9yIDxib29sPiByZXQobWF4dik7CiAKICAgICAgICBxdWV1ZTxpbnQ+IHF1ZTsKICAgICAgICBxdWUucHVzaChzKTsKICAgICAgICB3aGlsZSghcXVlLmVtcHR5KCkpCiAgICAgICAgewogICAgICAgICAgICBpbnQgdiA9IHF1ZS5mcm9udCgpOwogICAgICAgICAgICBxdWUucG9wKCk7CiAgICAgICAgICAgIHJldFt2XT10cnVlOwogCiAgICAgICAgICAgIGZvcihpbnQgaT0wO2k8U1ooR1t2XSk7aSsrKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBlZGdlICZlID0gR1t2XVtpXTsKICAgICAgICAgICAgICAgIGlmKGUuY2FwPjAgJiYgIXJldFtlLnRvXSkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBxdWUucHVzaChlLnRvKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gcmV0OwogICAgfQogCiAgICB2b2lkIGRpc3AoKQogICAgewogICAgICAgIGZvciAoaW50IHYgPSAwOyB2IDwgbWF4djsgdisrKQogICAgICAgIHsKICAgICAgICAgICAgcHJpbnRmKCIlZDoiLHYpOwogICAgICAgICAgICBmb3IoaW50IGk9MDtpPFNaKEdbdl0pO2krKykKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgaWYoR1t2XVtpXS5pbml0X2NhcD4wKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIHByaW50ZigiLT4lZCglZCksIixHW3ZdW2ldLnRvLEdbdl1baV0uaW5pdF9jYXApOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgICAgIHByaW50ZigiXG4iKTsKICAgICAgICB9CiAgICB9CiAKcHJpdmF0ZToKICAgIC8vIHPDo8KBwovDo8KCwonDo8KBwq7DpsKcwoDDp8Kfwq3DqMK3wp3DqcKbwqLDo8KCwpJCRlPDo8KBwqfDqMKowojDp8KuwpfDo8KBwpnDo8KCwosKICAgIHZvaWQgYmZzKGludCBzKQogICAgewogICAgICAgIGZpbGwobGV2ZWwuYmVnaW4oKSxsZXZlbC5lbmQoKSxORyk7CiAgICAgICAgcXVldWU8aW50PiBxdWU7CiAgICAgICAgbGV2ZWxbc109MDsKICAgICAgICBxdWUucHVzaChzKTsKICAgICAgICB3aGlsZSghcXVlLmVtcHR5KCkpCiAgICAgICAgewogICAgICAgICAgICBpbnQgdiA9IHF1ZS5mcm9udCgpOwogICAgICAgICAgICBxdWUucG9wKCk7CiAgICAgICAgICAgIGZvcihpbnQgaT0wO2k8U1ooR1t2XSk7aSsrKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBlZGdlICZlID0gR1t2XVtpXTsKICAgICAgICAgICAgICAgIGlmKGUuY2FwPjAgJiYgbGV2ZWxbZS50b108MCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBsZXZlbFtlLnRvXSA9IGxldmVsW3ZdICsgMTsKICAgICAgICAgICAgICAgICAgICBxdWUucHVzaChlLnRvKTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KIAogICAgLy8gw6XCosKXw6XCisKgw6PCg8KRw6PCgsK5w6PCgsKSREZTw6PCgcKnw6bCjsKiw6PCgcKZCiAgICBpbnQgZGZzKGludCB2LCBpbnQgdCwgaW50IGYpCiAgICB7CiAgICAgICAgaWYodj09dCkgcmV0dXJuIGY7CiAgICAgICAgZm9yIChpbnQgJmk9aXRlclt2XTtpPFNaKEdbdl0pO2krKykKICAgICAgICB7CiAgICAgICAgICAgIGVkZ2UmIGUgPSBHW3ZdW2ldOwogICAgICAgICAgICBpZihlLmNhcD4wICYmIGxldmVsW3ZdPGxldmVsW2UudG9dKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBpbnQgZCA9IGRmcyhlLnRvLCB0LCBtaW4oZiwgZS5jYXApKTsKICAgICAgICAgICAgICAgIGlmKGQ+MCkKICAgICAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgICAgICBlLmNhcCAtPSBkOwogICAgICAgICAgICAgICAgICAgIEdbZS50b11bZS5yZXZdLmNhcCArPSBkOwogICAgICAgICAgICAgICAgICAgIHJldHVybiBkOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiAwOwogICAgfQogCiAgICBzdGF0aWMgY29uc3QgaW50IERJTklDX0lORiA9IElOVF9NQVg7IC8vIMOlwq7CucOpwofCj8OjwoLCkmxsw6PCgcKrw6PCgcKXw6PCgcKfw6PCgcKEw6PCgcKow6PCgcKNw6PCgcKvw6PCgMKBw6PCgcKTw6PCgcKTw6PCgsKCw6XCpMKJw6PCgcKIw6PCgsKLCiAKICAgIHN0cnVjdCBlZGdlIAogICAgewogICAgICAgIGVkZ2UoaW50IGlucHV0X3RvLCBpbnQgaW5wdXRfY2FwLCBpbnQgaW5wdXRfcmV2KSA6IHRvKGlucHV0X3RvKSwgY2FwKGlucHV0X2NhcCksIHJldihpbnB1dF9yZXYpLCBpbml0X2NhcChpbnB1dF9jYXApIHt9CiAgICAgICAgaW50IHRvOyAgICAgLy8gw6jCocKMw6XChcKICiAgICAgICAgaW50IGNhcDsgICAgLy8gw6XCrsK5w6nCh8KPCiAgICAgICAgaW50IHJldjsgICAgLy8gw6nCgMKGw6jCvsK6CiAgICAgICAgaW50IGluaXRfY2FwOyAvLyDDpcKIwp3DpsKcwp/DpcKuwrnDqcKHwo/Dr8K8wojDo8KDwofDo8KDwpDDo8KDwoPDo8KCwrDDp8KUwqjDr8K8wokKICAgIH07CiAKICAgIGludCBtYXh2OwogICAgdmVjdG9yIDwgdmVjdG9yIDxlZGdlPiA+IEc7IC8vIMOjwoLCsMOjwoPCqcOjwoPClcOjwoHCrsOpwprCo8Omwo7CpcOjwoPCqsOjwoLCucOjwoPCiAogICAgdmVjdG9yIDwgaW50ID4gbGV2ZWw7ICAgICAvLyBzw6PCgcKLw6PCgsKJw6PCgcKuw6jCt8Kdw6nCm8KiCiAgICB2ZWN0b3IgPCBpbnQgPiBpdGVyOyAgICAgIC8vIMOjwoHCqcOjwoHCk8OjwoHCvsOjwoHCp8OowqrCv8OjwoHCucOnwrXCgsOjwoLCj8OjwoHCo8OjwoHCn8OjwoHCiwogCn07CiAKaW50IG1haW4oKQp7CglpbnQgVDsKCWNpbiA+PiBUOwoKCWZvciAoaW50IHRlc3RjYXNlID0gMDsgdGVzdGNhc2UgPCBUOyB0ZXN0Y2FzZSsrKQoJewoJCWludCBNLE47CgkJY2luID4+IE0gPj4gTjsKCgkJY29uc3QgaW50IFMgPSBNKk47CgkJY29uc3QgaW50IFQgPSBTKzE7CgkJY29uc3QgaW50IFYgPSBUKzE7CgkJdmVjdG9yIDxzdHJpbmc+IHZzOwoJCWZvciAoaW50IHkgPSAwOyB5IDwgTTsgeSsrKQoJCXsKCQkJc3RyaW5nIHM7CgkJCWNpbiA+PiBzOwoJCQl2cy5wdXNoX2JhY2socyk7CgkJfQoKCgkJY29uc3Qgc3RhdGljIGludCBkeVtdID0gey0xLCAwLCAxLCAwfTsgLy8gVSxSLEQsTAoJCWNvbnN0IHN0YXRpYyBpbnQgZHhbXSA9IHsgMCwgMSwgMCwtMX07CgoJCURpbmljKiBkaW5pYyA9IG5ldyBEaW5pYyhWKTsKCgkJaW50IGRlZmF1bHRfc2NvcmUgPSAwOwoKCgkJZm9yIChpbnQgeSA9IDA7IHkgPCBNOyB5KyspCgkJewoJCQlmb3IgKGludCB4ID0gMDsgeCA8IE47IHgrKykKCQkJewoJCQkJY29uc3QgaW50IG5vdyA9IHkqTit4OwoJCQkJaWYoKHgreSklMj09MCkKCQkJCXsKCQkJCQlpZih2c1t5XVt4XT09Jz8nKQoJCQkJCXsKCQkJCQkJZGVmYXVsdF9zY29yZSArPSA0OwoJCQkJCQkvLwkJCQkJCWRpbmljLT5hZGRfZWRnZShTLG5vdywwKTsKCQkJCQkJZGluaWMtPmFkZF9lZGdlKG5vdyxULDQpOwoKCQkJCQkJZm9yKGludCBkID0gMDsgZCA8IDQ7IGQrKykKCQkJCQkJewoJCQkJCQkJY29uc3QgaW50IG55ID0geStkeVtkXTsgCgkJCQkJCQljb25zdCBpbnQgbnggPSB4K2R4W2RdOwoJCQkJCQkJY29uc3QgaW50IG5leHQgPSBueSpOK254OwoJCQkJCQkJaWYoSU5SQU5HRShueSwwLE0tMSkmJklOUkFOR0UobngsMCxOLTEpKQoJCQkJCQkJewoJCQkJCQkJCWlmKHZzW255XVtueF09PScjJyB8fCB2c1tueV1bbnhdPT0nPycpCgkJCQkJCQkJewoJCQkJCQkJCQlkaW5pYy0+YWRkX2VkZ2UobmV4dCxub3csMik7CgkJCQkJCQkJfQoJCQkJCQkJfQoJCQkJCQl9CgkJCQkJfQoJCQkJCWVsc2UgaWYgKHZzW3ldW3hdPT0nIycpCgkJCQkJewoJCQkJCQlkZWZhdWx0X3Njb3JlICs9IDQ7CgkJCQkJCWRpbmljLT5hZGRfZWRnZShub3csVCxCSUcpOwoKCQkJCQkJZm9yKGludCBkID0gMDsgZCA8IDQ7IGQrKykKCQkJCQkJewoJCQkJCQkJY29uc3QgaW50IG55ID0geStkeVtkXTsgCgkJCQkJCQljb25zdCBpbnQgbnggPSB4K2R4W2RdOwoJCQkJCQkJaWYoSU5SQU5HRShueSwwLE0tMSkmJklOUkFOR0UobngsMCxOLTEpKQoJCQkJCQkJewoJCQkJCQkJCWlmKHZzW255XVtueF09PScjJykKCQkJCQkJCQl7CgkJCQkJCQkJCWRlZmF1bHRfc2NvcmUgLT0gMjsKCQkJCQkJCQl9CgkJCQkJCQl9CgkJCQkJCX0KCQkJCQl9CgkJCQl9CgkJCQllbHNlCgkJCQl7CgkJCQkJaWYodnNbeV1beF09PSc/JykKCQkJCQl7CgkJCQkJCWRlZmF1bHRfc2NvcmUgKz0gNDsKCgkJCQkJCWRpbmljLT5hZGRfZWRnZShTLG5vdyw0KTsKCQkJCQkJLy8JCQkJCQlkaW5pYy0+YWRkX2VkZ2Uobm93LFQsMCk7CgoJCQkJCQlmb3IoaW50IGQgPSAwOyBkIDwgNDsgZCsrKQoJCQkJCQl7CgkJCQkJCQljb25zdCBpbnQgbnkgPSB5K2R5W2RdOyAKCQkJCQkJCWNvbnN0IGludCBueCA9IHgrZHhbZF07CgkJCQkJCQljb25zdCBpbnQgbmV4dCA9IG55Kk4rbng7CgkJCQkJCQlpZihJTlJBTkdFKG55LDAsTS0xKSYmSU5SQU5HRShueCwwLE4tMSkpCgkJCQkJCQl7CgkJCQkJCQkJaWYodnNbbnldW254XT09JyMnKQoJCQkJCQkJCXsKCQkJCQkJCQkJZGluaWMtPmFkZF9lZGdlKG5vdyxuZXh0LDIpOwoJCQkJCQkJCX0KCQkJCQkJCX0KCQkJCQkJfQoJCQkJCX0KCQkJCQllbHNlIGlmICh2c1t5XVt4XT09JyMnKQoJCQkJCXsKCQkJCQkJZGVmYXVsdF9zY29yZSArPSA0OwoJCQkJCQlkaW5pYy0+YWRkX2VkZ2UoUyxub3csQklHKTsKCQkJCQl9CgkJCQl9CgkJCX0KCQl9CgoKCQlwcmludGYoIkNhc2UgIyVkOiAlZFxuIix0ZXN0Y2FzZSsxLGRlZmF1bHRfc2NvcmUgLSBkaW5pYy0+bWF4X2Zsb3coUyxUKSk7CgoJCWRlbGV0ZSBkaW5pYzsKCX0KCgoJcmV0dXJuIDA7Cn0K