/* *********************************************************
	factorpolynomial.js
	(c) 2008-2010 by Allen W. Murphy
	Code for factoring a second degree trinomial.
	GPLv2 
   ********************************************************* */

/* ********************************************************* */
function gcf(A, B, C) {

	/* Returns the GCF of three integers */

	var i = getMinCoefficient(A, B, C);

	while (i > 1) {
		if (Math.abs(A) % i == 0) {
			if (Math.abs(B) % i == 0) {
				if (Math.abs(C) % i == 0) {
					return i
				}
			}
		}
		i--;
	}
	return 1;
}

/* ********************************************************* */
function getMinCoefficient(A, B, C) {

	/* Returns the lowest of three integers */
	
	if (Math.abs(A) <= Math.abs(B) && Math.abs(A) <= Math.abs(C)) {
		return A;
	}
	else if (Math.abs(B) <= Math.abs(A) && Math.abs(B) <= Math.abs(C)) {
		return B;
	}
	else {
		return C;
	}
}

/* ********************************************************* */
function getFactorPairs(n) {
	
	/* returns an array f factor pairs of an integer */
	
	var i = 0;
	var pairs = new Array();
	
	/* Positive factors */
	for (var f = 1; f <= Math.abs(n); f++) {
		if (Math.abs(n) % f == 0) {
			pairs[i] = {x: f, y: n/f};
			//alert(pairs[i].x + ", " + pairs[i].y);
			i++;
		}
	}

	/* Negative factors */
	for (var f = -1*Math.abs(n); f <= -1; f++) {
		if (Math.abs(n) % f == 0) {
			pairs[i] = {x: f, y: n/f};
			//alert(pairs[i].x + ", " + pairs[i].y);
			i++;
		}
	}
	
	return pairs;
}

/* ********************************************************* */
function getOperator(n) {
	
	/* Returns either a plus or minus sign for the factors */
	
	if (n < 0) {
		return "-";
	}
	else {
		return "+";
	}
}

/* ********************************************************* */
function getCoefficient(n) {
	
	/* 
	 * If the coefficient on the variable is 1 or -1 
	 * it is not necessary. 
	 */
	
 	if (n != 1) {
		return n;
	}
	else if (n == -1) {
		return "-";
	}
	else return "";
}

/* ********************************************************* */
function factorPolynomial(output, A, B, C) {

	/* factor a second degree polynomial Ax^2 + Bx + C */


	var firstoperator = "+";
	var secondoperator = "+";

	// Factor out constants
	var h = gcf(A, B, C);

	//alert(h);
	
	if (h != 1 && h != 0) {
		A = A/h;
		B = B/h;
		C = C/h;

		output += "Factor out " + h + " leaving <b>" + h + "(" + A + 
			"x<sup>2</sup> + " + B + "x + " + C +") </b><br /><br />";
	}

	var aPairs = getFactorPairs(A);
	var cPairs = getFactorPairs(C);
	var found = 0;

	output += "Check factors of (" + A + ")(" + C + ") = <b>" + A*C +
		"</b> so they sum to <b>" + B + "</b>.<br />"; 

	for (var i=0; i < aPairs.length; i++) {
		for (var j=0; j < cPairs.length; j++) {

			if (aPairs[i].x * cPairs[j].y + aPairs[i].y * cPairs[j].x == B) {

				/* yes we found the factors! 
				 * display h(aPairs.x x + cPairs.x)(aPairs.y x + cPairs.y)
				 */
				
				output += '<span class="boldblue">' +
					aPairs[i].x * cPairs[j].y + " + " + (aPairs[i].y * 
					cPairs[j].x) + " = " + (aPairs[i].x * cPairs[j].y + 
					aPairs[i].y * cPairs[j].x) + " YES! </span><br />";

				/* Split the middle 'x' term. */
				output += '<br />So the middle splits like this: <b>' + 
					getCoefficient(A) + 'x<sup>2</sup> ' + getOperator(aPairs[i].y * 
					cPairs[j].x) + ' ' + getCoefficient(Math.abs(aPairs[i].y * cPairs[j].x)) +
					'x ' + getOperator(aPairs[i].x * cPairs[j].y) + ' ' +
					getCoefficient(Math.abs(aPairs[i].x * cPairs[j].y)) +
					'x ' +  getOperator(C) + ' ' + getCoefficient(Math.abs(C)) +
					'</b><br />';

				/* Grouping */
				output += '<br />Grouping gives us: <b>' + getCoefficient(aPairs[i].y) +
					'x(' + getCoefficient(aPairs[i].x) + 'x ' + 
					getOperator(cPairs[j].x) + ' ' + Math.abs(cPairs[j].x) + ') ' + 
					getOperator(cPairs[j].y) + ' ' + Math.abs(cPairs[j].y) + 
					'(' + getCoefficient(aPairs[i].x) + 'x ' + getOperator(cPairs[j].x) + 
					' ' + Math.abs(cPairs[j].x) + ') ' + '</b><br />';

				/* Binomial Factors */
				output += 'with <b>' + '(' + getCoefficient(aPairs[i].x) + 'x ' + 
					getOperator(cPairs[j].x) + ' ' + Math.abs(cPairs[j].x) + 
					') ' + '</b> as the common binomial factor and <b>(' + 
					getCoefficient(aPairs[i].y) + 'x ' + getOperator(cPairs[j].y) + ' ' + 
					Math.abs(cPairs[j].y) + ')</b> as the leftover binomial factor.<br />' +
					'<br />So the factored form is: <br /><br />';

				/* Coefficients of 1 are not necessary */
				var D = getCoefficient(aPairs[i].x);
				var E = getCoefficient(aPairs[i].y);
				
				/* Set the operators to + or - */
				firstoperator = getOperator(cPairs[j].x);
				secondoperator = getOperator(cPairs[j].y);
				
				/* Add factored form to output. */
				output += '<span class="boldred">';
				if (h == 1) {
					output += "(" + D + "x "+ firstoperator + " " + 
						Math.abs(cPairs[j].x) + ")(" + E + "x " +
						secondoperator + " " + Math.abs(cPairs[j].y) +")";
				}
				else {
					output += h + "(" + D + "x "+ firstoperator + " " + 
						Math.abs(cPairs[j].x) + ")(" + E + "x " + 
						secondoperator + " " + Math.abs(cPairs[j].y) +")";
				}
				output += '</span><br />';
				found = 1;
				break; 
			}
			/* Not a match */
			output += aPairs[i].x * cPairs[j].y + " + " + 
				aPairs[i].y * cPairs[j].x + " = " + (aPairs[i].x * cPairs[j].y +
				aPairs[i].y * cPairs[j].x) + " NO <br />";
				
		}
		if (found == 1) {
			break;
		}
	}
	if (found == 0) {
		output += "<br />No further factoring can be done.";
	}
	return output;
}

/* ********************************************************* */
function validateCoefficients(A, B, C) {

	/* Check to make sure the user has entered numbers in the form. */
	
	if (isNaN(A) || isNaN(B) || isNaN(C)) {
		alert("One or more of your coefficients is not a number.");
		return false;
	}
	else if ((A % 1 != 0) || (B % 1 != 0) || (C % 1 != 0)) {
		alert("One or more of your coefficients is not an integer.");
		return false;
	}
	else {
		return true;
	}	
}

/* ********************************************************* */
function solveClicked() {

	/* Called when the user clicks the "Solve" button.
	   This is the main funciton of the script.*/
	
	var A = document.polynomialform.A.value;
	var B = document.polynomialform.B.value;
	var C = document.polynomialform.C.value;
	var output = "";
	
	if (validateCoefficients(A, B, C)) {	
		output = factorPolynomial(output, A, B, C);
		document.getElementById("steps").innerHTML = output;
	}
}

/*
 This script is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This script is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 To contact the FSF, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/



syntax highlighted by Code2HTML, v. 0.9.1