// biatris.code




string getNameA(var n){
	if(n<0)return "0";
	p='z'-'a'+1;
	name="";
	do{
		t=n%p;
		if(n<p&&name.length())--t;
		name=((string)('a'+t))+name;
		n=((int)(n/p));
		}while(n);
	return name;
}



var rowtest(var p_table){
	typesrow={};
	n=(*p_table)[1].size();
	i=0;
	for(;i<n;++i){
		t=(*p_table)[1][i];
		typesrow.push(typeof(t));
		}
	S=((set)typesrow);
	if(S.size()==1)return typesrow[0];
	A=B=((set)0);
	i=0;
	for(;i<n;++i){
		t=typesrow[i];
		ok=(*p_table)[0][i];
		if(ok)A.insert(t);else B.insert(t);
		}
	if(S-A==B){
		a=A.size();
		b=B.size();
		if(b<a)a=b;
		return a;
		}
	return #;
}



var rowRazbor(var p_table){
	n=(*p_table)[0].size();
	S=((set)0);
	i=0;
	for(;i<n;++i)S.insert((*p_table)[1][i]);
	A=B=((set)0);
	i=0;
	for(;i<n;++i){
		t=(*p_table)[1][i];
		ok=(*p_table)[0][i];
		if(ok)A.insert(t);else B.insert(t);
		}
	if(S-A==B){
		ok=1;
		if(A.size()>B.size()){
			A=B;
			ok=0;
			}
		A=((vector)A);
		R={"S":A,"ok":ok};
		return R;
		}
	return #;
}



var PrevAnalize(var p_table){
	t=rowtest(&(*p_table)["body"]);
	if(typeof(t)=="string"){
		if(t=="vector"){
			table={"body":{},"head":p_table->head};
			table.body.push((p_table->body)[0]);
			table.body.push(#);
			n=(p_table->body)[1].size();
			none=(p_table->body)[1][0].size();
			R={};
			ok=0;
			i=0;
			for(;i<none;++i){
				(table.body)[1]={};
				j=0;
				for(;j<n;++j)(table.body)[1].push((p_table->body)[1][j][i]);
				x=PrevAnalize(&table);
				R.push(x);
				if(x)ok=1;
				}
			if(ok)return R;
			return 0;
			}
		return 0;
		}
	if(!isset(t)){
		t=rowRazbor(&p_table->body);
		if(!isset(t))return 0;
		return t.S.size();
		}
	return t;
}



var getAdress(var p_row,var adres,var p_ok){
	if(!isset(adres)){
		n=p_row->size();
		S=((set)0);
		i=0;
		for(;i<n;++i)S.insert(typeof((*p_row)[i]));
		if(S.size()==1){
			type=S[0];
			if(type=="vector"){
				S=((set)0);
				i=0;
				for(;i<n;++i)S.insert((*p_row)[i].size());
				if(S.size()>1){
					P=PROGRAM("#.size()=="+S[0]);
					return {"size",P};
					}
				size=S[0];
				up={};
				i=0;
				for(;i<size;++i)up.push(1);
				do{
					size2=0;
					i=0;
					for(;i<size;++i)if(up[i])++size2;
					if(!size2)return 0;
					posi=rand()%size2;
					pos=0;
					i=0;
					for(;i<size;++i)if(!up[i]);else {
						if(pos==posi)break;
						++pos;
						};
					pos=i;
					up[pos]=0;
					row={};
					i=0;
					for(;i<n;++i)row.push((*p_row)[i][pos]);
					X=getAdress(&row);
					}while(X==0);
				P=PROGRAM("#["+pos+"]");
				return {"pos",P}+X;
				}
			}
		type="#";
		if(S.in("vector"))type="vector";
		if(S.in("set"))type="set";
		if(S.in("map"))type="map";
		if(type!="#"){
			P=PROGRAM("typeof(#)==\""+type+"\"");
			return {"type",P};
			}
		S=((set)0);
		i=0;
		for(;i<n;++i)S.insert((*p_row)[i]);
		if(S.size()==1)return 0;
		pos=rand()%S.size();
		W=S[pos];
		if(typeof(W)=="string")W=W.export();
		P=PROGRAM("#=="+W);
		return {"==",P};
		}
	if(!adres.size()){
		table={(*p_ok),(*p_row)};
		R=rowRazbor(&table);
		if(R.S.size()==1){
			z=R.ok?"==":"!=";
			W=(R.S)[0];
			if(typeof(W)=="string")W=W.export();
			P=PROGRAM("#"+z+W);
			return {"==",P};
			}
		s="";
		if(!R.ok)s="!";
		s=s+R.S.export()+".in(#)";
		P=PROGRAM(s);
		return {"==",P};
		}
	pos=adres[0];
	adres.pop_begin();
	row={};
	n=p_row->size();
	i=0;
	for(;i<n;++i)row.push((*p_row)[i][pos]);
	X=getAdress(&row,adres,p_ok);
	return {"pos",PROGRAM("#["+pos+"]")}+X;
}



var assembleDetails(var X){
	access={};
	P=PROGRAM("#");
	i=0;
	for(;i<X.size();++i){
		type=X[i];
		A=X[++i];
		N={0};
		if(type=="size")N={0,0,0};
		A.setSub(N,P);
		P=A;
		access=N+access;
		}
	return {access,P};
}



var findWayToMinArg(var mask,var n){
	if(!isset(n)){
		min=0;
		i=0;
		for(;i<mask.size();++i){
			x=mask[i];
			if(typeof(x)=="vector")x=findWayToMinArg(x);
			if(!x);else {if(!min||x<min)min=x;}
			}
		return min;
		}
	i=0;
	for(;i<mask.size();++i){
		x=mask[i];
		if(typeof(x)=="int"){if(x==n)return {i};}else {
			x=findWayToMinArg(x,n);
			if(typeof(x)=="vector")return {i}+x;
			}
		}
	return #;
}



var Biatris(var p_table){
	if(!(p_table->body)[0].size())return #;
	mask=PrevAnalize(p_table);
	if(mask==0){
		S=((set)(p_table->body)[0]);
		if(S.size()==1){
			P=PROGRAM((p_table->head)[0]+"=(bool)"+(S[0]?1:0));
			return P;
			}
		X=getAdress(&(p_table->body)[1]);
		if(X==0){
			s=(p_table->body)[0][0]?1:0;
			s="(bool)"+s;
			s=(p_table->head)[0]+"="+s;
			return PROGRAM(s);
			}
		X=assembleDetails(X);
		n=(p_table->body)[1].size();
		P=PROGRAM("p_table->body[1][i]");
		P2=X[1];
		P2.setSub(X[0],P);
		P=P2;
		A=B={"body":{{},{}},"head":p_table->head};
		i=0;
		for(;i<n;++i){
			ok=eval(P);
			((ok?A:B).body)[0].push((p_table->body)[0][i]);
			((ok?A:B).body)[1].push((p_table->body)[1][i]);
			}
		P=PROGRAM((p_table->head)[1]);
		P2=X[1];
		P2.setSub(X[0],P);
		A=Biatris(&A);
		B=Biatris(&B);
		if(isset(A)&&isset(B))P=PROGRAM("if(#)#;else #;");
		if(isset(A)&&!isset(B))P=PROGRAM("if(#)#;");
		if(!isset(A)&&isset(B))P=PROGRAM("if(#);else #;");
		P.setSub({0},P2);
		if(isset(A))P.setSub({1},A);
		if(isset(B))P.setSub({2},B);
		return P;
		}
	n=findWayToMinArg(mask);
	adres=findWayToMinArg(mask,n);
	X=getAdress(&(p_table->body)[1],adres,&(p_table->body)[0]);
	X=assembleDetails(X);
	P=PROGRAM((p_table->head)[1]);
	X[1].setSub(X[0],P);
	P=X[1];
	P2=PROGRAM((p_table->head)[0]+"=#");
	P2.setSub({1},P);
	return P2;
}


// biatris.code	:-|