// basis.txt

var CreateOneMemoryCard(){
	X={
		know:(map)0,
		markerknow:(map)0,
		knowDont:(map)0,
		usedNames:(set)0,
		Conditions:{},
		EqualeVars:{},
		posLastAnalizeCondition:-1,
		conflict:0,
		pos:0,
		randomRow:{},
		povtorCommand:0,
		posPreviorInGraph:0
		};
	return X;
}


var toStringOneMemoryCard(p_memorycard){
	s2=s="";
	names=p_memorycard->know.getKeys();
	for(i=0;i<names.size();++i){
		if(i)s+=" && ";
		s+=names[i]+"=="+p_memorycard->know[names[i]];
		}
	names=p_memorycard->knowDont.getKeys();
	for(i=0;i<names.size();++i){
		if(i)s2+=" && ";
		s2+=names[i]+"!="+p_memorycard->knowDont[names[i]];
		}
	if(s.size()&&s2.size())s+=" && "+s2; else s+=s2;
	s2="";
	for(i=0;i<p_memorycard->Conditions.size();++i){
		if(i)s2+=" && ";
		P=p_memorycard->Conditions[i];
		if(typeof(P)=="vector"){
			ss="";
			for(j=0;j<P.size();++j){
				if(j)ss+=" || ";
				ss+=P[j];
				}
			s2+="("+ss+")";
			}else s2+=P;
		}
	if(s.size()&&s2.size())s+=" && "+s2; else s+=s2;
	s2="";
	for(i=0;i<p_memorycard->EqualeVars.size();++i){
		if(i)s2+=" && ";
		S=p_memorycard->EqualeVars[i];
		for(j=1;j<S.size();++j){
			if(j-1)s2+=" && ";
			s2+=(string)S[j-1]+"=="+S[j];
			}
		}
	if(s.size()&&s2.size())s+=" && "+s2; else s+=s2;
	if(p_memorycard->conflict)s+="\nConflict!";
	return s;
}


void setValueInMC(p_memorycard,name,value){
	if(typeof(name)=="program")name=(string)name;
	X=#;
	if(isDefinedInMC(p_memorycard,name,&X))if(X!=value){
		for(i=0;i<p_memorycard->EqualeVars.size();++i)
			if(p_memorycard->EqualeVars[i].find(name)>=0)p_memorycard->EqualeVars[i]-={name};
		//conditions need clear
		}
	p_memorycard->know[name]=value;
	p_memorycard->usedNames.insert(name);
}


var findAllRowOR(P){
	if(P.typeof()!="||")return {P};
	return findAllRowOR(P.getSub({0}))+findAllRowOR(P.getSub({1}));
}


bool isTyftoLogic(t,t2){// ==, >=
	if(t==t2)return 1;
	if(t+"="==t2)return 1;
	if(t2=="!=" && (t=="<" || t==">"))return 1;
	return 0;
}


var scanerRowOrInMC(p_memorycard,row){
	for(i=0;i<row.size();++i){
		ok=0;
		P=row[i];
		h={"==","!=","<",">","<=",">="}.find(P.typeof());
		if(h<0)continue;
		A=P.getSub({0});
		B=P.getSub({1});
		P2=pairFindConditionInMC(p_memorycard,A,#,B);
		if(typeof(P2)=="program"){
			if(isTyftoLogic(P2.typeof(),P.typeof()))return 1;
			m={"!=","==",">=","<=",">","<"};
			h2={"==","!=","<",">","<=",">="}.find(P2.typeof());
			ok=(isTyftoLogic(m[h2],P.typeof()) || isTyftoLogic(P2.typeof(),m[h]));
			}
		if(ok){
			row.erase(i);
			--i;
			}
		}
	if(row.size()==1)return row[0];
	if(row.size())p_memorycard->Conditions.push(row);else p_memorycard->conflict=1;
	return 0;
}


// a<b || a==b ===> a<=b
void glueRowOrInMC(p_memorycard,p_row){
	ok=1;
	while(ok){
		ok=0;
		for(i=0;i<p_row->size();++i){
			P=(*p_row)[i];
			A=P.getSub({0});
			B=P.getSub({1});
			t=P.typeof();
			for(j=i+1;j<p_row->size();++j){
				P2=(*p_row)[j];
				AA=P2.getSub({0});
				BB=P2.getSub({1});
				if(!(A==AA && B==BB || B==AA && A==BB))continue;
				t2=P2.typeof();
				if(B==AA){
					n={"==","!=","<",">","<=",">="}.find(t2);
					t2={"==","!=",">","<",">=","<="}[n];
					}
				t3=t; // t==t2
				if(t=="<"){
					n={">",">=","<=","==","!="}.find(t2);
					if(n>=0)t3={"!=",".","<=","<=","!="}[n];
					}
				if(t==">"){
					n={"<","<=",">=","==","!="}.find(t2);
					if(n>=0)t3={"!=",".",">=",">=","!="}[n];
					}
				if(t=="=="){
					n={"<","<=",">",">=","!="}.find(t2);
					if(n>=0)t3={"<=","<=",">=",">=","."}[n];
					}
				if(t==">="){
					n={"<","<=",">","==","!="}.find(t2);
					if(n>=0)t3={".",".",">=",">=","."}[n];
					}
				if(t=="<="){
					n={"<",">=",">","==","!="}.find(t2);
					if(n>=0)t3={"<=",".",".","<=","."}[n];
					}
				if(t=="!="){
					n={"<",">=",">","==","<="}.find(t2);
					if(n>=0)t3={"!=",".","!=",".","."}[n];
					}
				p_row->erase(j);
				if(t3!="."){
					P=PROGRAM("#"+t3+"#");
					P.setSub({0},A);
					P.setSub({1},B);
					(*p_row)[i]=P;
					}else p_row->erase(i);
				ok=1;
				break;
				}
			}
		}
}


void setConditionsInMC(p_memorycard,P){
	if(typeof(P)!="program")return;
	t=P.typeof();
	if(t=="||"){
		row=findAllRowOR(P);
		glueRowOrInMC(p_memorycard,&row);
		P=scanerRowOrInMC(p_memorycard,row);
		if(typeof(P)!="program")return;
		t=P.typeof();
		}
	if(t=="&&"){
		setConditionsInMC(p_memorycard,P.getSub({0}));
		setConditionsInMC(p_memorycard,P.getSub({1}));
		return;
		}
	if(t=="=="){
		A=P.getSub({0});
		B=P.getSub({1});
		if(A.typeof()=="var")A=(string)A;
		if(B.typeof()=="var")B=(string)B;
		//if(pairIsNotEqualeInMC(p_memorycard,A,B))p_memorycard->conflict=1;
		//find (>= or <=) for erase
		P2=pairFindConditionInMC(p_memorycard,A,#,B);
		if(typeof(P2)=="program"){
			if({"!=","<",">"}.find(P2.typeof())>=0)p_memorycard->conflict=1;
			if(P2.typeof()==">=" || P2.typeof()=="<=")
				p_memorycard->Conditions.erase(p_memorycard->posLastAnalizeCondition);
			}
		ok=0;
		ii=0;
		for(i=0;i<p_memorycard->EqualeVars.size();++i){
			p_row=&p_memorycard->EqualeVars[i];
			a=b=0;
			for(j=0;j<p_row->size();++j){
				if((*p_row)[j]==A)a=1;
				if((*p_row)[j]==B)b=1;
				}
			if(a&&b)return;
			if(a)p_row->push(B);
			if(b)p_row->push(A);
			if(a||b){
				if(ok){
					p_memorycard->EqualeVars[ii]+=(*p_row)-{A,B};
					p_memorycard->EqualeVars.erase(i);
					return;
					}
				ok=1;
				ii=i;
				}
			}
		if(!ok)p_memorycard->EqualeVars.push({A,B});
		return;
		}
	if(t==">" || t=="<"){
		A=P.getSub({0});
		B=P.getSub({1});
		if(A.typeof()=="var")A=(string)A;
		if(B.typeof()=="var")B=(string)B;
		if(pairIsEqualeInMC(p_memorycard,A,B))p_memorycard->conflict=1; else{
			if(pairIsNotEqualeInMC(p_memorycard,A,B)){
				X=p_memorycard->Conditions[p_memorycard->posLastAnalizeCondition];
				if(X.typeof()=="!=")p_memorycard->Conditions.erase(p_memorycard->posLastAnalizeCondition); else{
					fc=pairFindConditionInMC(p_memorycard,A,t,B);
					if(typeof(fc)=="program")if(fc==P)return;
					fc=pairFindConditionInMC(p_memorycard,A,(t==">"?"<":">"),B);
					if(typeof(fc)=="program")p_memorycard->conflict=1;
					}
				}
			//find (>= or <= or !=) for erase
			P2=pairFindConditionInMC(p_memorycard,A,#,B);
			if(typeof(P2)=="program"){
				if(t+"="==P2.typeof() || P2.typeof()=="!=")p_memorycard->Conditions.erase(p_memorycard->posLastAnalizeCondition);
				ok=0;
				if(t==">" && {"<","<="}.find(P2.typeof())>=0)ok=1;
				if(t=="<" && {">",">="}.find(P2.typeof())>=0)ok=1;
				if(ok)p_memorycard->conflict=1;
				}
			p_memorycard->posLastAnalizeCondition=-1;
			}
		}
	if(t==">=" || t=="<="){
		A=P.getSub({0});
		B=P.getSub({1});
		if(A.typeof()=="var")A=(string)A;
		if(B.typeof()=="var")B=(string)B;
		if(pairIsEqualeInMC(p_memorycard,A,B))return;
		P2=pairFindConditionInMC(p_memorycard,A,#,B);
		if(typeof(P2)=="program"){
			if(P2.typeof()[0]==t[0])return;
			p_memorycard->conflict=1;
			}
		p_memorycard->posLastAnalizeCondition=-1;
		}
	p_memorycard->Conditions.push(P);
}



bool pairIsEqualeInMC(p_memorycard,A,B){
	if(typeof(A)=="program")if(A.typeof()=="var")A=(string)A;
	if(typeof(B)=="program")if(B.typeof()=="var")B=(string)B;
	if(typeof(A)==typeof(B))if(A==B)return 1;
	for(i=0;i<p_memorycard->EqualeVars.size();++i){
		p_row=&p_memorycard->EqualeVars[i];
		ok=0;
		for(j=0;j<p_row->size();++j){
			if((*p_row)[j]==A)++ok;
			if((*p_row)[j]==B)++ok;
			}
		if(ok==2)return 1;
		}
	return 0;
}



bool pairIsNotEqualeInMC(p_memorycard,A,B,stop){
	if(typeof(A)=="string")A=PROGRAM(A);
	if(typeof(B)=="string")B=PROGRAM(B);
	if(A==B)return 0;
	for(i=0;i<p_memorycard->Conditions.size();++i){
		P=p_memorycard->Conditions[i];
		if(typeof(P)!="program")continue;
		if({"<",">","!="}.find(P.typeof())<0)continue;
		A2=P.getSub({0});
		B2=P.getSub({1});
		a=(A2==A && B2==B);
		b=(A2==B && B2==A);
		if(a || b){
			p_memorycard->posLastAnalizeCondition=i;
			return 1;
			}
		a=(A==A2 || A==B2);
		b=(B==A2 || B==B2);
		if(!a&&!b)continue;
		ok=2;
		if(a)ok=pairIsEqualeInMC(p_memorycard,B,A==A2?B2:A2);
		if(b)ok=pairIsEqualeInMC(p_memorycard,A,B==A2?B2:A2);
		if(ok<2){
			if(ok)p_memorycard->posLastAnalizeCondition=i;
			return ok;
			}
		}
	if(isset(stop))return 0;
	if(typeof(A)=="program")if(A.typeof()=="var")A=(string)A;
	for(i=0;i<p_memorycard->EqualeVars.size();++i){
		p_row=&p_memorycard->EqualeVars[i];
		pos=p_row->find(A);
		if(pos>=0){
			for(j=0;j<p_row->size();++j)if(j!=pos)
				if(pairIsNotEqualeInMC(p_memorycard,(*p_row)[j],B,1))return 1;
			return 0;
			}
		}
	return 0;
}




bool pairIsMoreOrLessInMC(p_memorycard,A,t,B){
	if({">","<","<=",">="}.find(t)<0)return 0;
	return pairIsNotEqualeInMC(p_memorycard,A,B);
}



bool isDefinedInMC(p_memorycard,P,p_x,stop){
	if(typeof(P)=="program")if(P.typeof()=="var")P=(string)P;
	if(p_memorycard->know.isset(P)){
		if(isset(p_x)){
			*p_x=p_memorycard->know[P];
			if((bool)isTerminateX)p_memorycard->know.erase(P);
			}
		return 1;
		}
	if(isset(stop))return 0;
	t=-1;
	for(i=0;i<p_memorycard->EqualeVars.size();++i){
		p_row=&p_memorycard->EqualeVars[i];
		t=p_row->find(P);
		if(t>=0)break;
		}
	if(t>=0)for(i=0;i<p_row->size();++i)if(i!=t)if(isDefinedInMC(p_memorycard,(*p_row)[i],p_x,1))return 1;
	return 0;
}



var pairFindConditionInMC(p_memorycard,A,t,B,stop){ // t= znak or #
	if(typeof(A)=="string")A=PROGRAM(A);
	if(typeof(B)=="string")B=PROGRAM(B);
	if(!isset(stop))if(pairIsEqualeInMC(p_memorycard,A,B)){
		P=PROGRAM("#==#");
		P.setSub({0},A);
		P.setSub({1},B);
		return P;
		}
	if(isset(t)){
		i={"<",">","!=","==","<=",">="}.find(t);
		antiZnak={">","<","!=","==",">=","<="}[i];
		}
	for(i=0;i<p_memorycard->Conditions.size();++i){
		P=p_memorycard->Conditions[i];
		if(typeof(P)!="program")continue;
		if(isset(t))if(P.typeof()!=t && P.typeof()!=antiZnak)continue;
		A2=P.getSub({0});
		B2=P.getSub({1});
		a=(A2==A && B2==B);
		b=(A2==B && B2==A);
		okeq=0;
		if(!a){
			if(A2==A)if(pairIsEqualeInMC(p_memorycard,B,B2))okeq=a=1;
			if(B2==B)if(pairIsEqualeInMC(p_memorycard,A,A2))okeq=a=1;
			}
		if(!b){
			if(A2==B)if(pairIsEqualeInMC(p_memorycard,A,B2))okeq=b=1;
			if(B2==A)if(pairIsEqualeInMC(p_memorycard,B,A2))okeq=b=1;
			}
		if(isset(t)){
			if(a)if(P.typeof()!=t)a=0;
			if(b)if(P.typeof()!=antiZnak)b=0;
			}
		if(a||b){
			p_memorycard->posLastAnalizeCondition=i;
			if(b){
				if(!isset(t)){
					i={"<",">","!=","==","<=",">="}.find(P.typeof());
					antiZnak={">","<","!=","==",">=","<="}[i];
					}
				P=PROGRAM("#"+antiZnak+"#");
				P.setSub({0},A);
				P.setSub({1},B);
				}
			if(a&&okeq){
				P.setSub({0},A);
				P.setSub({1},B);
				}
			return P;
			}
		}
	if(isset(stop))return 0;
	A2=A;
	if(A.typeof()=="var")A=(string)A;
	for(i=0;i<p_memorycard->EqualeVars.size();++i){
		p_row=&p_memorycard->EqualeVars[i];
		pos=p_row->find(A);
		if(pos>=0){
			for(j=0;j<p_row->size();++j)if(j!=pos){
				P=pairFindConditionInMC(p_memorycard,(*p_row)[j],t,B,1);
				if(typeof(P)=="program"){
					P.setSub({0},A2);
					return P;
					}
				}
			return 0;
			}
		}
	return 0;
}




string pairFindXConditionInMC(p_memorycard,A,B,p_stopList){
	if(!isset(p_stopList)){
		stopList={};
		p_stopList=&stopList;
		}
	if(typeof(A)=="program")if(A.typeof()=="var")A=(string)A;
	if(typeof(B)=="program")if(B.typeof()=="var")B=(string)B;
	P=pairFindConditionInMC(p_memorycard,A,#,B);
	if(typeof(P)=="program")return P.typeof();
	ok=0;
	for(i=0;i<p_memorycard->EqualeVars.size();++i){
		p_row=&p_memorycard->EqualeVars[i];
		for(j=0;j<p_row->size();++j)if((*p_row)[j]==A)ok=1;
		if(ok)break;
		}
	ListA={A};
	if(ok)ListA=p_memorycard->EqualeVars[i];
	for(ii=0;ii<ListA.size();++ii){
		A=ListA[ii];
		for(i=0;i<p_memorycard->Conditions.size();++i){
			P=p_memorycard->Conditions[i];
			if(typeof(P)!="program")continue;
			AA=(string)P.getSub({0});
			BB=(string)P.getSub({1});
			if(AA!=A && BB!=A)continue;
			t=P.typeof();
			if(AA==A){
				AA=BB;
				}else{
				n={"<",">","!=","==","<=",">="}.find(t);
				t={">","<","!=","==",">=","<="}[n];
				}
			if(p_stopList->find(AA)>=0)return "?";
			p_stopList->push(AA);
			Z=pairFindXConditionInMC(p_memorycard,AA,B,p_stopList);
			p_stopList->pop();
			if(Z=="?")continue;
			if(t=="!=" && Z==t)return "?";
			if(Z==t)return Z;
			if(Z=="!=" && (t=="<" || t==">"))return t;
			if(Z=="!=" && (t=="<=" || t==">="))return (t=="<=")?"<":">";
			if(t=="!=" && (Z=="<" || Z==">"))return Z;
			if(t=="!=" && (Z=="<=" || Z==">="))return (Z=="<=")?"<":">";
			if(Z=="==")return t;
			if(Z+"="==t)return Z;
			if(Z==t+"=")return t;
			}
		}
	return "?";
}





//--------------------------------------------------------------------------------------------------
void main(){
	X=CreateOneMemoryCard();
	setValueInMC(&X,"A",25);
	setConditionsInMC(&X,PROGRAM("A==B && C==B"));
	setConditionsInMC(&X,PROGRAM("n==t"));
	setConditionsInMC(&X,PROGRAM("q==p"));
	setConditionsInMC(&X,PROGRAM("q==t"));
	setConditionsInMC(&X,PROGRAM("k!=p"));
	setConditionsInMC(&X,PROGRAM("k==x"));
	//setConditionsInMC(&X,PROGRAM("n==x"));//
	setConditionsInMC(&X,PROGRAM("k<n"));
	setConditionsInMC(&X,PROGRAM("i2>ii"));
	setConditionsInMC(&X,PROGRAM("i==i2"));
	setConditionsInMC(&X,PROGRAM("y==e || i<ii"));

	setConditionsInMC(&X,PROGRAM("AA<BB && CC<=AA && CC==DD"));
	setConditionsInMC(&X,PROGRAM("aa==bb || bb>aa || cc==ee"));

	trace(toStringOneMemoryCard(&X));
	trace("?:n==k => "+pairIsEqualeInMC(&X,"n","k"));
	trace("?:p!=k => "+pairIsNotEqualeInMC(&X,"p","k"));
	trace("?:n!=k => "+pairIsNotEqualeInMC(&X,"n","k"));
	trace("?:n!=x => "+pairIsNotEqualeInMC(&X,"n","x"));
	trace("?:x>t => "+pairIsMoreOrLessInMC(&X,"x",">","t"));
	tmp=0;
	ok=isDefinedInMC(&X,"C",&tmp);
	trace("C: "+(ok?"":"not find.")+(ok?tmp:""));
	trace("?:(ii,i) => "+pairFindConditionInMC(&X,"ii",#,"i"));

	trace("?:(BB,DD) => "+pairFindXConditionInMC(&X,"BB","DD"));

	getstring();
}



// basis.txt	:-|