// 

function balanceformat()
{
	document.write("<a name='baleq'></a><h1>Chemical Equation Balancer</h1>");
	document.write("<b>Written by Don Kiel</b><br><br>");
	document.write("Enter the unbalanced chemical equation ");
	document.write("in the format FeS2+O2=Fe2O3+SO2");
	document.write("</P><FORM><INPUT TYPE=TEXT  NAME='input' SIZE=50><P>");
	document.write("<INPUT TYPE=BUTTON VALUE='Balance!' onclick='Coeff(this.form)'>");
	document.write("<P><INPUT TYPE=TEXT NAME ='result' SIZE=50></FORM><FORM>");
	document.write("<INPUT TYPE=BUTTON VALUE='Help' onclick='openHelp()'></FORM>");
}

function dimension (name_str, n0, n1, n2, n3)   {
      var numDimens = dimension.arguments.length - 1;
      var code = name_str + " = new Array();";   
      eval (code);
      for (var i = 0; i <  n0; i++) // first index is 0    
     {
         var newName = name_str + "[" + i + "]";      
         if (numDimens > 1)         {
            code = "dimension ('" + newName + "'";
            for (var j = 2; j <= numDimens; j++)
               code += ", " + dimension.arguments[j];         
               code += ");";
            eval (code);       
  }     
 }     
}  



   function gcd( a ,  b) {               //Greatest Common Divisor of a and b
      if (a > b) {
           temp = a; a = b; b = temp       }
     if((a==0)||(b==0))return 1
     if((b%a)==0) return a
        else
       return gcd(a, b%a)  
   }
   
   function lowCommMult(a, b) {    //Lowest Common Multiple of a and b
      if(a == b) return a
      else return (a*b)/gcd(a, b)
   }

function isDigit(n) {                      //Check if n is a digit
   var test = "" + n
    if(test=="0"||test=="1"||test=="2"||test=="3"||test=="4"||
        test=="5"||test=="6"||test=="7"||test=="8"||test=="9")
     {return true}
else
     {return false}
}

function Coeff(form) {
    
   Uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   Lowercase="abcdefghijklmnopqrstuvwxyz"
   str=form.input.value +" "
   s=str
   size=0
   var col = 0
   var k=0
   row=0
   col=0
   right=false
   found=false
   dimension("a", 9, 10)  //declare arrays
   dimension("symbol", 10, 2)
   dimension("rightSide", 10)
   dimension("term",10)

   str=form.input.value +" "
   s=str
   
   for(var g=0; g<9; g++)   //initialize arrays
     for(var h=0; h<10; h++)
          a[g][h] = 0
  
  for(var m=0; m<10; m++){
         symbol[m][0] = ' '
         symbol[m][1] = ' '
  }
     
  for(var j=0; j<10; j++)
         rightSide[j]=false
        
  while(k<str.length-1) {
        chr = s.charAt(k)
        if(chr == '+'){
          col++
          k++
        }
        if(chr == '=') {
          right = true
          col++
          k++
        }
        if(right) rightSide[col]= true
           if(Uppercase.indexOf(chr)!= -1){  //if character is upper case
                found = false
           if (k < s.length-1){ 
              chr3 = s.charAt(k+1)                  //look at next character 
              if(Lowercase.indexOf(chr3)!= -1 )   //if it is lower case 
                   k++ 
              else chr3 = ' '
          }
          for(check=0; check<size; check++) {  //see if chemical symbol is in symbol table
            if((chr == symbol[check][0]) && 
               (chr3 == symbol[check][1])){
                  row = check
                  found = true
                  k++
                }                
         }
                     
         if(!found) {                                        //if not, add it to symbol table
            symbol[size][0] = chr
            symbol[size][1] = chr3
            row = size
            size++
            k++
         }
          if(k<s.length){     
            chr2=s.charAt(k)                             //look at next character
            if(isDigit(chr2)){                              //if it is a digit 
               a[row][col]=parseInt(chr2)            //put it in matrix
               k++
              if(k<s.length){
                chr2=s.charAt(k)                         //look at next character
                if (isDigit(chr2)){                         // if also a digit
                     a[row][col] = parseInt(chr2)+ a[row][col]*10  //compute two digit number
                     k++
               }        
             }
          }
          else a[row][col] = 1                          //if there was no digit, matrix entry is 1
          }   
        }
      }    

//Now start to solve the matrix by Gaussian elimination
   n=col
   for(var i=0; i<n; i++) {
      if(a[i][i] == 0) {                                   //not a pivot element
        for(var j=0; j<n; j++) {
          if(a[j][i] != 0) {                               //found one, interchange rows
            for(var k=0; k<n+1; k++) { 
            temp = a[i][k]
             a[i][k] = a[j][k]
             a[j][k] = temp
            }
          }
         }
       }
       if(a[i][i] < 0)                                  //if pivot element is negative, multiply row by -1
         for(var c=0; c<n+1; c++)
           a[i][c] = -a[i][c]
       
     for(var p=0; p<n; p++) {
         if(p != i) 
       {
        if(a[p][i] != 0) 
       {                                                    //eliminate it     
             mult = a[p][i]
              piv = a[i][i]
              for(r=0; r<n+1; r++)             
                   a[p][r] = a[p][r]*piv
                             - a[i][r]*mult
         }
       } 
      }
    }

  for(var  u=0; u<n; u++) 
     if(a[u][u] < 0) a[u][n]=-a[u][n]         //if any pivot element is negative, make it positive
  
  lcm = a[0][0]; 
  for(var v=1;v<n;v++) {                     //find lcm of pivot elemnts
     if(a[v][v] != lcm) lcm = lowCommMult(lcm,a[v][v])
  }

  term[n] = lcm
    for(var w=0;w<n; w++){               
      if (a[w][w] !=0) 
          term[w] = a[w][n]*lcm/a[w][w]
      if(rightSide[w])
          term[w]=-term[w]
   }
                 
    divisor = term[0]                           //find gcd of coefficients 
    for (var v=1; v<n+1; v++) 
         divisor = gcd(divisor, term[v])
    
    for(var v=0; v<n+1; v++)             //divide by gcd
         term[v] = term[v]/divisor
 
    for(var w=0; w<n; w++) 
       k=0 
       count = 0
       var buff=""
       buff= buff+term[count]            //insert coefficients into original string
       while(k < str.length) {
          chr = s.charAt(k)
          buff=buff + chr
          if ((chr == ('+'))||(chr ==('='))) {
             count++
              buff = buff + term[count].toString()
      }
       k++
    }
    s = buff
 
      if(term[n] == 0) {
        buff = "Impossible, try again."
        if(confirm("Did you input the equation properly?"))
         {alert("Try changing the order of the elements in the first compound.")}
      }   
  form.result.value=buff

}

function openHelp() {
  	helpWin=open("", "", "status=no,height=450, width=450")
	helpWin.document.open();

	helpWin.document.write("<html><head>");
	helpWin.document.write("<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=iso-8859-1'>");
	helpWin.document.write("<META NAME='GENERATOR' CONTENT='Mozilla/4.04 [en] (Win95; I) [Netscape]'>");
	helpWin.document.write("<title>help</title>");
	helpWin.document.write("</head><body>");
	helpWin.document.write("<CENTER><B>Help File</B></CENTER>&nbsp;");
	helpWin.document.write("<BR>There are still some quirks in this program:");
	helpWin.document.write("<P>&nbsp;&nbsp;&nbsp; 1.&nbsp; There should be no spaces in the entry of ");
	helpWin.document.write("the original equation.");
	helpWin.document.write("<BR>&nbsp;&nbsp;&nbsp; 2.&nbsp; The uses of elements is conventional, i.e.-the ");
	helpWin.document.write("first letter of each element must be upper case and the second(if there ");
	helpWin.document.write("is one) must be lower case.");
	helpWin.document.write("<BR>&nbsp;&nbsp;&nbsp; 3.&nbsp; Parentheses are not allowed.&nbsp; To balance ");
	helpWin.document.write("<BR>Fe(OH)3=Fe2O3+H2O, enter it as FeO3H3=Fe2O3+H2O to compute the correct ");
	helpWin.document.write("coefficients and then convert back to the original form.  I ");
	helpWin.document.write("am trying to expand the program ");
	helpWin.document.write("so that this will not be necessary.");
	helpWin.document.write("<BR>&nbsp;&nbsp;&nbsp; 4.&nbsp; Some equations are of such a form that they ");
	helpWin.document.write("will produce an error.&nbsp;&nbsp; For example, KClO3=KCl+O2 will give ");
	helpWin.document.write("an error, but will also give an alert box to suggest you change the order ");
	helpWin.document.write("of the elements in one of the first compounds.&nbsp; In this case, the equation ");
	helpWin.document.write("KO3Cl=KCl+O2 will work.");
	helpWin.document.write("<BR>If you encounter any other types of errors, please let me know at <A ");
	helpWin.document.write("HREF='mailto:dkiel@abac.com'>dkiel@abac.com</A>");
	helpWin.document.write("</body></html>");

	helpWin.document.close();
}
