// Javascript zur Lösung linearer Gleichungssysteme
// (c) Arndt Brünner, Gelnhausen, 27.8.2001
//                       Version: 18.4.2003

var m=new Array(),L=new Array(),B=new Array(); 
var vvv=new Array("a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z");
var lambda='µ';
var t1lmerker=0;
var v=new Array();
var n,maxgrad=5,mingrad=2;

function Analyse()
{
	t=new String;
	t=document.f.t1.value;
	ErklTyp=(document.f.erkltyp[0].checked)?0:1;
	if(document.f.immererkl.checked)Erkl=true;
	ganzzahlig=document.f.ganzzahlig.checked;
	document.f.gauss.value="";
	if(t.indexOf("=")==-1){Analyse2(t);return;}
	if (t.indexOf("(")>-1){alert("unzulässiges Zeichen: ("); return;}
	if (t.indexOf(")")>-1){alert("unzulässiges Zeichen: )"); return;}
	if (t.indexOf("^")>-1){alert("unzulässiges Zeichen: ^"); return;}
	if (t.indexOf("²")>-1){alert("unzulässiges Zeichen: ²"); return;}
	if (t.indexOf("³")>-1){alert("unzulässiges Zeichen: ³"); return;}
	if ((t.search(/\/\D/)>-1)||(t.search(/\D\//)>-1)){alert("Eine Variable als Zähler oder Nenner ist unzulässig");return;}
	t=t.replace(/\*/g,"").replace(/·/g,"").toLowerCase().replace(/\,/g,".").replace(/ +/g,"");
	t=t.replace(/—/g,"-").replace(/–/g,"-").replace(/\t/g,"").replace(/ /g,"").replace(/=\+/g,"=");
	while(t.indexOf("+-")>-1)t=t.replace(/\+-/g,"-");
	while(t.indexOf("--")>-1)t=t.replace(/--/g,"+");
	while(t.indexOf("++")>-1)t=t.replace(/\++/g,"+");
	homogen=1;
	n=0;li=-1;
	for(i=0 ; i<26;i++) if (t.indexOf(vvv[i])>-1){v[n]=vvv[i];n++;}
	g=t.split("\n");
	var Z=new Array(),N=new Array();
	for(i=0;i<ng;i++){if (g[i].indexOf("=")==-1){ng=i;break;}}
	for(i=0;i<(n+1)*n;i++){ m[i]=0;N[i]=1;Z[i]=0;}
	for(i=0;i<g.length;i++)g[i]=g[i].replace(/\n/g,"").replace(/\r/g,"");
	var ig=0;var ng=0;
	for(var iig=0;iig<g.length;iig++) //Schleife für Gleichungen
	{
		if((g[iig].indexOf("=")==-1)||(g[iig].length<3))continue;
		var GG=g[iig].split("=");
		if(GG[1].substr(0,1)!="-")GG[1]="+"+GG[1];
		if(GG[0].substr(0,1)!="-")GG[0]="+"+GG[0];
		var G=GG[0]+GG[1].replace(/-/g,"#").replace(/\+/g,"-").replace(/#/g,"+");
		G=G.replace(/-/g,"#-").replace(/\+/g,"#+");
		var T=G.split("#");
		for(i=0;i<T.length;i++)
		{
			status="analysiere Eingabe und erzeuge Matrix";
			var t=T[i],tt=t.charAt(t.length-1).toLowerCase();
			var iDD=t.search(/\D\D/)
			if((iDD>-1)&&(t.length>2)&&(iDD<t.length-1))
				{alert("Variablennamen aus zwei Buchstaben \noder Produkte aus Variablen sind unzulässig:\n"+t.replace(/-/,"").replace(/\+/,""));return;}
			for(j=0;j<n;j++)if(tt==v[j])break;
			var Bruch=t.substr(0,t.length-((j==n)?0:1)).split("/");
			if(Bruch.length==1)Bruch[1]=1;
			var I=(j==n)?(ig+1)*(n+1)-1:ig*(n+1)+j;
			if(I>=Z.length)for(var ii=Z.length;ii<=I;ii++){Z[ii]=0;N[ii]=1;m[ii]=0;}
			var vz=(j==n)?-1:1;
			if(Bruch[0]=="-")Bruch[0]=-1;
			if(Bruch[0]=="+")Bruch[0]=1;
			Z[I]=Z[I]*Number(Bruch[1])+vz*Number(Bruch[0])*N[I];
			N[I]*=Number(Bruch[1]);
			if((vz==-1)&&(Z[I]!=0))homogen=0;
			if((isNaN(Z[I]))||(isNaN(N[I]))){alert("Fehler in der Eingabe bei "+t+"\n"+g[iig]);return;}
		}
		g[iig]=g[iig].replace(/=/," = ").replace(/\+/g," + ").replace(/-/g," - ").replace(/=  - /,"= -");
		if(g[iig].substr(0,3)==" - ")g[iig]="-"+g[iig].substring(3,g[iig].length);
		g[iig]=g[iig].replace(/\./g,",").replace(/ ,/g," 0,").replace(/-,/g,"-0,");
		if(g[iig].charAt(0)==",")g[iig]="0"+g[iig];
		ig++;ng++;
	} // ig-Schleife
	t="";
	for(i=0;i<n*(n+1);i++)m[i]=Z[i]+"/"+N[i];
	document.f.t1.value=g.join("\n").replace(/\n+/g,"\n");
	if(document.f.t1.value.charAt(document.f.t1.value.length-1)!="\n")document.f.t1.value+="\n";
	v[n]=" ";

	if ((homogen==0))
	{
		if (n>ng){ alert("Mehr Variablen als Gleichungen"); return;}
		else if (n<ng){ alert("Mehr Gleichungen als Variablen"); return;}
		//GLSL(n,n+1); 
		
		GLSL_(m,n);
		if(Erkl)document.f.gauss.value=ET;
		Erkl=false;
		for(i=0;i<n;i++)
		{
			s=0;
			for(j=0;j<n;j++){if(m[(n+1)*i+j]!=0)s=1;}
			//alert(s + "\n"+ m[(n+1)*(i+1)-1] +"\n"+((s==0)&&(m[(n+1)*(i+1)-1]!=0)));
			if((s==0)&&(m[(n+1)*(i+1)-1]!=0)){t=" \n   Gleichungssystem\n   hat keine Lösung";break;}
			if(m[(n+1)*i+i]==0){t=" \n   keine eindeutige\n   Lösung gefunden";break;}
			t+=" "+ v[i]+" = "+String(Runden(m[(n+1)*(i+1)-1],10)).replace(/\./g,",")+"\n";
		}
		t=t.replace(/ ,/g," 0,").replace(/-,/g,"-0,");
		document.f.t2.value=t;
	}
	else 
	{
		j=0;
		for(i=0;i<n*(n+1);i++)m[i]=Z[i]/N[i];
		for(i=0;i<n*ng;i++){B[i]=m[i+j];if ((i+1)%n==0)j++;}
		//while(ng<n){for(i=0;i<n;i++)B[n*ng+i]=B[i];ng++;}
		homogenGLSL(ng,n,0);
		for(i=0;i<n;i++)
		t+=" "+ v[i]+" = "+String(Runden(L[i],10)).replace(/\./,",")+"·"+lambda+"\n";
		t=t.replace(/ \-1·/g," -").replace(/ 1·/g," ").replace(/ 0·µ/g," 0").replace(/·/g,"");
		t+="\n     µ aus R";
		for (i=0;i<n;i++)if(L[i]==0){t="";for(i=0;i<n;i++)t+=" "+v[i]+" = 0\n";t+="\n (sonst keine Lösung\n mit einem Parameter)";break;}
		t=t.replace(/ ,/g," 0,").replace(/-,/g,"-0,");
		document.f.t2.value=t;
		document.f.gauss.value=" \n Erklärungen zu homogenen Gleichungssystemen sind noch nicht verfügbar.";
	}
	status="";
}

function Analyse2(t)
{
if(t.length<3){if(Erkl)document.f.gauss.value=" \n Geben Sie oben zunächst ein Gleichungssystem ein\n\n oder lassen Sie ein Zufallsbeispiel erzeugen!";return;}
document.f.erkltyp[0].checked=true;
t=t.replace(/\n/g," ").replace(/\r/g," ").replace(/\t/g," ").replace(/,/g,".");
t=t.replace(/ +/g," ");
while(t.indexOf(" ")==0){t=t.substr(1,t.length);};
while(t.lastIndexOf(" ")==t.length-1){t=t.substr(0,t.length-1);};
m=t.split(" ");
mm=m.length;
//for(i=0;i<mm;i++)m[i]=Number(m[i]);
nn=(Math.sqrt(4*mm+1)-1)/2;
if(nn!=Math.floor(nn)){alert("Matrix hat nicht die Form n x (n+1)");return;}
//GLSL(nn,nn+1);
GLSL_(m,nn);
if(Erkl)document.f.gauss.value=ET;
Erkl=false;
t="";
for(i=0;i<mm;i++){t+=Runden(m[i],10)+"  ";if(i%(nn+1)==nn)t+="\n";}
t=t.replace(/\./g,",").replace(/ ,/g," 0,").replace(/-,/g,"-0,");
document.f.t2.value=t;
}

function Runden(t,i)
{
	var T=String(t);
	if(T.indexOf("/")>0)if(document.f.alsBruch.selectedIndex==0)return t;else t=eval(t);
	var d=Math.pow(10,i);
	return Math.round(t*d)/d;
}


function GLSL(nz, ns)
{
    var i, j, k ;
	var q;
	for (j = 0;j<ns-1;j++)
	{
        // Diagonalenfeld normalisieren
        q = m[j * ns + j];
        if (q == 0){
            //Gewährleisten, daß keine 0 in der Diagonale steht
            for (i = j+1 ;i< nz;i++)
			{
                // Suche Reihe mit Feld <> 0 und addiere dazu
                if (m[i * ns + j] != 0)
				{
                    for (k = 0 ; k<ns; k++)
					{
						m[j * ns + k] += m[i * ns + k];
                    }
                    q = m[j * ns + j];
                    break;
                }
            }
        }
        if (q != 0)
		{
            // Diagonalen auf 1 bringen
            for (k = 0;k< ns;k++)
			{
                m[j * ns + k] = m[j * ns + k] / q;
            }
        }
        
        // Spalten außerhalb der Diagonalen auf 0 bringen
        for (i = 0 ; i< nz ; i++)
		{
            if (i != j )
			{
                q = m[i * ns + j];
                for (k = 0; k< ns;k++)
				{
                    m[i * ns + k] -=  q * m[j * ns + k];
                }
			}
        }
    }
}


function homogenGLSL(nz, ns)
{
    var i=0, j=0, k=0 ;
	var q=0.0;
	for (j = 0;j<nz;j++)
	{
        // Diagonalenfeld normalisieren
        q = B[j * ns + j];
        if (q == 0.0){
            //Gewährleisten, daß keine 0 in der Diagonale steht
            for (i = j+1;i< nz;i++)
			{
                // Suche Reihe mit Feld <> 0 und addiere dazu
                if (B[i * ns + j] !=0.0 )
				{
                    for (k = 0 ; k<ns; k++)
					{
						B[j * ns + k] += B[i * ns + k];
                    }
                    q = B[j * ns + j];
                    break;
                }
            }
        }
			
		if (Math.abs(q)<0.000001){B[j*ns+j]=0;q=0;}
        if (q != 0.0)
		{
            // Diagonalen auf 1 bringen
            for (k = 0;k< ns;k++)
			{
                B[j * ns + k] = B[j * ns + k] / q;
            }
        }
        
        // Spalten außerhalb der Diagonalen auf 0 bringen
        for (i = 0 ; i< nz ; i++)
		{
			if (i!=j)
			{
				q = B[i * ns + j];
				for (k = 0; k< ns;k++)
				{
					B[i * ns + k] -=  q * B[j * ns + k];
				}
			}
        }
    }
	// freie Parameter bestimmen
	j=ns-1;
	for(i=0;i<ns;i++) L[i]=0.0;
	for (i=nz-1;i>=0;i--)
	{

		if (Math.abs(B[i*ns+j])<0.0000001)
		{
			L[i]=1.0;
			for (k=i-1;k>=0;k--)
				L[k]-=B[k*ns+j]; // Abhängigkeit vom freien Parameter im Lösungsvektor eintragen
			j--;
		}
		else 
			j--;
	}
	min=10000000000;
	GGT=1;
	q=1.0;
	for(i=0;i<ns;i++){if(L[i]==0)return; q*=L[i];}
	Nenner=Runden(GetNenner(q,0.00001,1000),8);
	for(i=0;i<ns;i++) L[i]=Runden(L[i]*Nenner,8);
	GGT=L[ns-1];
	for(i=0;i<ns-1;i++)
      {
	    if((min>Math.abs(L[i]))&&(L[i]!=0))min=Math.abs(L[i]);
	    GGT=ggT(L[i],GGT);
	}
	if (Math.abs(GGT)>=1)
	    for(i=0;i<ns;i++) L[i]=L[i]/GGT;
	else
	    for(i=0;i<ns;i++) L[i]=L[i]/min;
}
function ggT(a,b)
{
	var r=-1;
	while(r!=0)
	{r=a%b;a=b;b=r;}
	return a;
}

function GetNenner(x,d,max)
{
	var y;
	for(var i=1;i<=max;i++)
	{
		y=x*i;
		if(Math.abs(y-Math.floor(y+0.5))<=d) return i;
	}
	return 1;
}

function erkl()
{
	Erkl=true;Analyse();
}

function bsp()
{
	var x=new Array(),vv=new Array(),i,j,g,gl="",gr,t="@\n",k=new Array(),s,ik,jj,f,z0,z1;
	mingrad=Number(document.f.mingrad.value);
	if(mingrad<2)mingrad=2;if(isNaN(mingrad))mingrad=2;
	maxgrad=Number(document.f.maxgrad.value);
	if(maxgrad>9)maxgrad=9;
	if((maxgrad<2)||isNaN(maxgrad))maxgrad=mingrad;
	if(mingrad>maxgrad)mingrad=maxgrad;
	document.f.mingrad.value=mingrad;
	document.f.maxgrad.value=maxgrad;
	n=Math.floor(Math.random()*(maxgrad-mingrad)+mingrad);
	if(isNaN(n))n=2;
	switch(Math.floor(Math.random()*4))
	{
		case 0: vv[0]="a";vv[1]="b";vv[2]="c";vv[3]="d";vv[4]="e";break;
		case 1: vv[0]="x";vv[1]="y";vv[2]="z";vv[3]="w";vv[4]="u";break;
		case 2: vv[0]="m";vv[1]="n";vv[2]="p";vv[3]="q";vv[4]="r";break;
		default:vv[0]=vvv[j=Math.floor(Math.random()*vvv.length)];
		for(i=1;i<n;i++)
		{
			j=(j+Math.floor(Math.random()*5)+1)%vvv.length;
			if(vvv[j]=="o")j++;if(vvv[j]=="l")j++;
			vv[i]=vvv[j];
		}
	}
	j=Math.floor(Math.random()*vvv.length);
	for(i=vv.length;i<n;i++)
	{
		do{
			j=(j+Math.floor(Math.random()*5)+1)%vvv.length;
			if(vvv[j]=="o")j++;if(vvv[j]=="l")j++;
			for(jj=0;jj<i;jj++)if(vv[jj]==vvv[j])break;
		}while(jj<i);
		vv[i]=vvv[j];
	}
	vv[n]="";
	for(i=0;i<n*(n+1);i++)m[i]=0;
	for(i=0;i<n;i++)
	{
		x[i]=Math.round(Math.random()*40-20);if(Math.random()>.8)x[i]+=.5;
		//if(Math.random()>.9)x[i]-=.25;if(Math.random()>.9)x[i]-=Math.floor(Math.random()*10)/10;
		do{f=Math.floor(Math.random()*10-5);}while(f==0);
		m[(i+1)*(n+1)-1]=-x[i]*f;m[i*(n+1)+i]=f;
	}
	for(i=0;i<n*n;i++)
	{
		var fmin=10000000000,ff,fi=-0.5;
		z0=Math.floor(Math.random()*n);
		do{z1=Math.floor(Math.random()*n)}while(z1==z0);
		for(f=-10;f<10;f++)
		{
			ff=0;
			for(jj=0;jj<=n;jj++)ff+=Math.abs(m[z0*(n+1)+jj]+f*m[z1*(n+1)+jj]);
			if((ff<fmin)&&(ff>4*n)){fmin=ff;fi=f;}
		}
		for(jj=0;jj<n;jj++)if(m[z0*(n+1)+jj]+Math.floor(fi+.1)*m[z1*(n+1)+jj]!=0)break;
		if(jj==n)fi=1;
		for(jj=0;jj<n+1;jj++)m[z0*(n+1)+jj]+=Math.floor(fi+.1)*m[z1*(n+1)+jj];
	}	
	for(i=0;i<n;i++)
	{
		z0=Math.floor(Math.random()*n);
		do{z1=Math.floor(Math.random()*n)}while(z1==z0);
		for(j=0;j<n+1;j++){jj=m[z0*(n+1)+j];m[z0*(n+1)+j]=m[z1*(n+1)+j];m[z1*(n+1)+j]=jj;}
	}

	for(i=0;i<n*(n+1);i++)
	{
		if((m[i]==1)&&((i%(n+1))<n))m[i]="+"+vv[i%(n+1)];
		else if((m[i]==-1)&&((i%(n+1))<n))m[i]="-"+vv[i%(n+1)];
		else if(m[i]!=0) m[i]=((m[i]>0)?"+":"")+m[i]+vv[i%(n+1)];
		else m[i]="";
	}
	//alert(m);
	for(i=0;i<n;i++)
	{
		gl="";gr="";
		for(j=0;j<n+1;j++)
		{
			if(m[i*(n+1)+j]!="")
			{
				jj=Math.floor(Math.random()*4)
				switch(jj)
				{
					case 0: gl+=m[i*(n+1)+j];break;
					case 1: gr+="-"+m[i*(n+1)+j];break;
					case 2: gl=m[i*(n+1)+j]+gl;break;
					default: gr="-"+m[i*(n+1)+j]+gr;break;
				}
			}
		}
		if(gl=="")gl="0";if(gr=="")gr="0";
		//if(gl.length<gr.length){var gg=gl;gl=gr;gr=gg;}
		t+=gl+"="+gr+"\n";
	}
	t=t.replace(/\./g,",").replace(/-,/g,"-0,").replace(/\+,/g,"+0,");
	t=t.replace(/--/g,"+").replace(/-\+/g,"-").replace(/\+-/g,"-").replace(/\n\+/g,"\n");
	t=t.replace(/=\+/g,"=").replace(/-/g," - ").replace(/\+/g," + ");
	t=t.replace(/= - /g,"=-").replace(/\n - /g,"\n-").replace(/@\n/,"");
	t=t.replace(/=/g," = ");
	document.f.t1.value=t;
	document.f.t2.value="";
}

function bsp_()
{
	bsp();Analyse();
}
function bsp__()
{
	Erkl=true;
	bsp();
	//var t=(ErklTyp==0)?" Umformen und sortieren (Variablen alphabetisch links, Konstanten rechts):\n\n"+getGS()+"\n\n":"";
	Analyse();
	//document.f.gauss.value=" \n Gleichungssystem:\n\n   "+document.f.t1.value.replace(/\n/g,"\n\n   ")+"\n"+t+document.f.gauss.value;
}
function getGS(vz)
{
	var i,j,jj,t="@\n  ";
	if(vz==null)vz="";
	for(i=0;i<n;i++)
	{
		for(j=0;j<n;j++)
			if(m[i*(n+1)+j]!="")
			{
				if(vz=="")
					t+=m[i*(n+1)+j];
				else
				{
					var mm=String(m[i*(n+1)+j]).replace(/,/,".");
					if(mm=="")mm="0";var emm=eval(mm);
					if(emm==1)t+="+"+v[j];
					else if(emm==-1)t+="-"+v[j];
					else if(emm!=0)t+="+"+emm+v[j];
				}
			}
	
			if(vz=="")
				t+="=-"+vz+m[i*(n+1)+n]+"\n\n  ";
			else
			{
				var mm=String(m[i*(n+1)+n]).replace(/,/,".");
				if(mm=="")mm="0";var emm=eval(mm);
				t+="="+emm+"\n\n  ";
			}
	}
	t=t.replace(/\./g,",").replace(/-,/g,"-0,").replace(/\+,/g,"+0,");
	t=t.replace(/--/g,"+").replace(/\+-/g,"-").replace(/\++/g,"+").replace(/\n +\+/g,"\n   ").replace(/-\+/g,"-");
	t=t.replace(/=-\n/g,"=0\n").replace(/=\+/g,"=").replace(/-/g," - ").replace(/\+/g," + ");
	t=t.replace(/= - /g,"=-").replace(/\n +- /g,"\n  -").replace(/@\n/,"");
	t=t.replace(/=/g," = ");
	return t;
}

function uebungen()
{
	var t="<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=iso-8859-1\">\n";
	t+="<meta name=\"author\" content=\"Arndt Brünner\">\n";
	t+="<title>Übungen</title>\n<link rel=stylesheet type=\"text/css\" href=\"standard1.css\">\n";
	t+="</head>\n<body bgcolor=\"#FFFAEE\" link=\"#000066\" alink=\"#000066\" vlink=\"#000066\">\n";
	t+='<h3>Übungsaufgaben</h3>\n<p><small>erzeugt auf: <a href="http://www.arndt-bruenner.de/mathe/scripts/gleichungssysteme.htm">http://home.t-online.de/home/arndt.bruenner/mathe/scripts/gleichungssysteme.htm</a></small></p>\n';
	var l="<p>&nbsp;</p>\n<hr><p>&nbsp;</p>\n<h5>Lösungen</h5>\n<p>&nbsp;<br><small>";
	var i;
	t+="<p>&nbsp;</p>\n<h5>Lineare Gleichungssysteme lösen</h5>\n";
	t+='<table cellpadding=10>\n';
	for(i=0;i<10;i++)
	{
		bsp_();
		if((i%2)==0)t+=((i>0)?'</tr>':'')+'<tr>\n';
		else t+='<td>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>\n';
		t+='<td style="text-align:right">('+(i+1)+')</td><td>\n';
		t+='<table style="margin-left:50px"><tr>\n';
		t+='<td rowspan=2><img src="vstr.gif" width="2" height="'+(20*n)+'">&nbsp;</td>\n';
		t+='<td align=center >\n';
		t+=document.f.t1.value.replace(/\n/g,"<br>\n");
		t+='</td>\n';
		t+='<td rowspan=2>&nbsp;<img src="vstr.gif" width="2" height="'+(20*n)+'"></td>\n';
		t+='</tr><tr><td align=center>\n';
		t+='</td></tr></table>\n</td>\n';
		l+='('+(i+1)+') &nbsp;&nbsp;&nbsp;'+document.f.t2.value.replace(/\n/g,"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;")+'<br>\n';
	}
	t+='</tr></table>\n';
	t+=l+"<p>&nbsp;</p><hr><p><small>&copy; Arndt Brünner&nbsp;&nbsp;<br>eMail: arndt.bruenner@t-online.de\n";
	t+='<br>Homepage: <a href="http://www.arndt-bruenner.de/mathe/mathekurse.htm">http://www.arndt-bruenner.de/mathe</a></small>\n</p>\n';
	t+='<p><small><a href="javascript:history.back()">zur&uuml;ck</a></small></p>\n</body>\n</html>\n';
	document.open();
	document.write(t);
	document.close();
}
