import java.util.ArrayList;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.text.DecimalFormat;
/**
Polynomial represents a polynomial from algebra with integer
coefficients. e.g. 4x3 + 3x2 - 5x + 2
Polynomial extends ArrayList, and contains the coefficients
of the polynomial, such that for Polynomial p, p.get(i) returns
the coefficient of the xi term. p.get(0) returns
the constant term.
For a Polynomial object p that represents a polynomial of degree
d, (i.e. where xd is the highest order term with a
non-zero coefficient), invoking p.get(k) where k>d should
result in an IndexOutOfBoundsException; that is, the ArrayList
should be of size exactly d+1.
@author P. Conrad
@author TODO: FILL IN YOUR NAME(S) HERE
@version UCSB, CS56, W14
*/
public class Polynomial extends ArrayList {
/** Assign Polynomial.debug to true or false to turn debugging
* output on or off.
*/
public static boolean debug = false;
/**
no-arg constructor returns a polynomial of degree 1, with value 0
*/
public Polynomial() {
// invoke superclass constructor, i.e. the
// constructor of ArrayList with
super(1); // we want capacity at least 1
// parameter 1 (capacity, not size)
this.add(0,0); // uses autoboxing (index, value)
}
/**
get the degree of the polynomial. Always >= 1
@return degree of the polynomial
*/
public int getDegree() { return this.size() - 1; }
/**
Construct polynomial from int array of coefficients.
The coefficients are listed in order from highest to lowest degree.
The degree is the size of the array - 1.
Example: 7x^3 - 2x^2 + 3 would be represented as {7,-2,0,3}
Example: x^4 - 4 would be represented as {1,0,0,0,-4}
NOTE that the order of coefficients is not necessarily the way
they will be stored in the array. That is, the order of coefficients
in the array passed in is from highest degree down to lowest
degree, so for a cubic:
-
coeffs[0]
is the x3 coefficient
-
coeffs[1]
is the x2 coefficient
-
coeffs[2]
is the x coefficient
-
coeffs[3]
is the constant term
It is done this way so that when initializing a polynomial
from an array literal, the order of coefficients mirrors the
way polynomials are typically written, from highest order
term to lowest order term:
Example: to represent 4x3 - 7x2 + 5,
use: Polynomial p = new Polynomial (new int [] {4,-7,0,5});
NOT: Polynomial p = new Polynomial (new int [] {5,0,-7,4});
@param coeffsHighToLow array of coefficients in order from largest degree down to smallest. If array has length zero, return a polynomial of degree zero with constant value zero.
*/
public Polynomial(int [] coeffsHighToLow) {
if (coeffsHighToLow.length==0) {
coeffsHighToLow = new int [] {0};
}
int [] coeffsLowToHigh = Polynomial.lowToHigh(coeffsHighToLow);
for (int i=0;i
0
1
-4
2x - 3
x^2 - 5x + 6
x^2 - x - 1
x^2 - x
-x^7 - 2x^5 + 3x^3 - 4x
@return string representation of Polynomial
*/
public String toString() {
String result = "stub"; // @@@ TODO: FIX ME!
return result;
}
/**
Construct polynomial from string representation
that matches the output format of the Polynomial toString method.
That is, you should be able to do:
Polynomial p = new Polynomial("0");
Polynomial p = new Polynomial("1");
Polynomial p = new Polynomial("-4");
Polynomial p = new Polynomial("2x - 3");
Polynomial p = new Polynomial("x^2 - 5x + 6");
Polynomial p = new Polynomial("x^2 - x - 1");
Polynomial p = new Polynomial("x^2 - x");
Polynomial p = new Polynomial("-x^7 - 2x^5 + 3x^3 - 4x");
And for any Polymomial object p, the following test should pass:
assertEquals(new Polynomial(p.toString()), p);
@param s string representation of Polynomial
*/
public Polynomial(String s) {
// invoke superclass constructor, i.e. the
// constructor of ArrayList with
super(1); // we want capacity at least 1
if (debug) {System.out.println("In Polynomial(String s), s=" + s);}
// For information on regular expressions in Java,
// see http://docs.oracle.com/javase/tutorial/essential/regex
// First check for special case of only digits,
// with possibly a - in front
// i.e. a degree 0 polynomial that is just an integer constant
Pattern integerConstantPattern =
Pattern.compile("^-?\\d+$");
Matcher integerConstantMatcher = integerConstantPattern.matcher(s);
// if that pattern matches, then the whole string is just
// an integer constant. So we can safely call Integer.parseInt(s)
// to convert to int, and add in this parameter.
if (integerConstantMatcher.matches()) {
this.add(0,Integer.parseInt(s));
return; // we are done!
}
// now, try for polynomials of degree 1
Pattern degreeOnePattern =
Pattern.compile("^(-?)(\\d*)x( ([+-]) (\\d+))?$");
// Explanation:
// start/end ^ $
// sign for x term (-?) group(1)
// coeff for x term (\\d*) group(2)
// x in x term x
// optional constant part ( )? group(3)
// sign for constant ([+-]) group(4)
// coeff for constant (\\d+) group(5)
Matcher degreeOneMatcher = degreeOnePattern.matcher(s);
if (degreeOneMatcher.matches()) {
int xCoeff = 1;
int constantTerm = 0;
String xCoeffSign = degreeOneMatcher.group(1);
String xCoeffString = degreeOneMatcher.group(2);
String constantTermSign = degreeOneMatcher.group(4);
String constantTermString = degreeOneMatcher.group(5);
if (xCoeffString != null && !xCoeffString.equals("")) {
xCoeff = Integer.parseInt(xCoeffString);
}
if (xCoeffSign != null && xCoeffSign.equals("-")) {
xCoeff *= -1;
}
if (constantTermString != null && !constantTermString.equals("")) {
constantTerm = Integer.parseInt(constantTermString);
}
if (constantTermSign != null && constantTermSign.equals("-")) {
constantTerm *= -1;
}
this.add(0,constantTerm);
this.add(1,xCoeff);
return;
}
// then try for higher degree
String twoOrMoreRe =
"^" // start of the string
+ "([-]?)(\\d*)x\\^(\\d+)" // first x^d term, groups 1,2,3
+ "(( [+-] \\d*x\\^\\d+)*)" // zero or more x^k terms group 4 (and 5)
+ "( [+-] \\d*x)?" // optional x term (group 6)
+ "( [+-] \\d+)?" // optional constant term (group 7)
+ "$"; // the end of the string
Pattern degreeTwoOrMorePattern = Pattern.compile(twoOrMoreRe);
Matcher degreeTwoOrMoreMatcher = degreeTwoOrMorePattern.matcher(s);
// if we have a match...
if (degreeTwoOrMoreMatcher.matches()) {
int firstCoeff = 1;
String startSign = degreeTwoOrMoreMatcher.group(1);
String coeffString = degreeTwoOrMoreMatcher.group(2);
String degreeString = degreeTwoOrMoreMatcher.group(3);
String middleXtoTheTerms = degreeTwoOrMoreMatcher.group(4);
String optionalXTermPart = degreeTwoOrMoreMatcher.group(6);
String optionalConstantTermPart = degreeTwoOrMoreMatcher.group(7);
if (coeffString != null && !coeffString.equals("")) {
firstCoeff = Integer.parseInt(coeffString);
}
if (startSign != null && startSign.equals("-")) {
firstCoeff *= -1;
}
int degree = Integer.parseInt(degreeString);
this.ensureCapacity(degree+1); // method of ArrayList
for(int i=0; i<=degree; i++) // initialize all to zero
this.add(0,0);
this.set(degree,firstCoeff);
if (middleXtoTheTerms!=null && !middleXtoTheTerms.equals("")) {
Pattern addlXtoThePowerTermPattern =
Pattern.compile(" ([+-]) (\\d+)(x\\^)(\\d+)");
Matcher addlXtoThePowerTermMatcher
= addlXtoThePowerTermPattern.matcher(middleXtoTheTerms);
while (addlXtoThePowerTermMatcher.find()) {
int coeff = 1;
String sign = addlXtoThePowerTermMatcher.group(1);
String nextCoeffString = addlXtoThePowerTermMatcher.group(2);
String nextDegreeString = addlXtoThePowerTermMatcher.group(4);
if (nextCoeffString != null && !nextCoeffString.equals("")) {
coeff = Integer.parseInt(nextCoeffString);
}
if (sign != null && sign.equals("-")) {
coeff *= -1;
}
this.set(Integer.parseInt(nextDegreeString),coeff);
}
} // if middleXToTheTerms has something
// Now all that is left is, possibly, an x term and a constant
// term. We need to select them out if they are there.
if (optionalXTermPart != null && !optionalXTermPart.equals("")) {
if (debug) {System.out.println("optionalXTermPart=" +
optionalXTermPart);}
Pattern optXTermPattern =
Pattern.compile("^ ([+-]) (\\d*)x$");
Matcher optXTermMatcher = optXTermPattern.matcher(optionalXTermPart);
optXTermMatcher.find();
int xCoeff = 1;
int constantTerm = 0;
String xCoeffSign = optXTermMatcher.group(1);
String xCoeffString = optXTermMatcher.group(2);
if (xCoeffString != null && !xCoeffString.equals("")) {
xCoeff = Integer.parseInt(xCoeffString);
}
if (xCoeffSign != null && xCoeffSign.equals("-")) {
xCoeff *= -1;
}
this.set(1,xCoeff);
} // optionalXTerm part
if (optionalConstantTermPart != null
&& !optionalConstantTermPart.equals("")) {
Pattern constantTermPattern =
Pattern.compile("^ ([+-]) (\\d+)$");
Matcher constantTermMatcher
= constantTermPattern.matcher(optionalConstantTermPart);
constantTermMatcher.find();
int constant = 0;
String sign = constantTermMatcher.group(1);
String constantString = constantTermMatcher.group(2);
if (constantString != null && !constantString.equals("")) {
constant = Integer.parseInt(constantString);
}
if (sign!=null && sign.equals("-")) {
constant *= -1;
}
this.set(0,constant);
} // a constant term is present
return;
} // degreeTwoOrMore
if (debug) {System.out.println("at bottom");}
// in the end, if we don't find what we need,
// through an exception
throw new IllegalArgumentException("Bad Polynomial String: [" + s + "]");
}
/**
determine whether two polynomials are equal
(same degree, same coefficients)
@param o arbitrary object to test for equality
@return true if objects are equal, otherwise false
*/
public boolean equals(Object o) {
// This is boiler plate code for a equals method in Java
// Always do this first
if (o == null)
return false;
if (!(o instanceof Polynomial))
return false;
Polynomial p = (Polynomial) o;
// @@@ TODO: Check the size of each ArrayList.
// If they don't match, return false
// @@@ TODO: If the sizes match, check whether the
// values match. If not, return False. Otherwise, return true.
return false; // @@@ STUB
}
/** Given an int [] of coefficients from lowest to highest
degree (where the index in the array matches the power of the
x term), find the degree of the polynomial (ignoring trailing terms with a coefficient of zero)
If all terms are zero, return 0.
This is a utility method that may be useful in converting
between the low to high and high to low representations of
coefficients, both in user programs that use the Polynomial
class, as well as in internal routines used to implement
Polynomial methods.
@param coeffsLowToHigh coefficients of a polynomial in order from lowest degree to highest degree. May have trailing zeros.
@return the degree of the polynomial as an int, ignoring trailing terms with a coefficient of zero
*/
public static int degreeCoeffsLowToHigh(int [] coeffsLowToHigh) {
return -42; // @@@ STUB!
}
/** Given an int [] of coefficients from highest to lowest
degree (the formal used for input to the Polynomial constructor),
find the degree of the polynomial (ignoring leading terms with a coefficient of zero)
If all terms are zero, return 0.
This is a utility method that may be useful in converting
between the low to high and high to low representations of
coefficients, both in user programs that use the Polynomial
class, as well as in internal routines used to implement
Polynomial methods.
@param coeffsHighToLow coefficients of a polynomial in order from highest degree first to lowest degree last. May have leading zeros.
@return the degree of the polynomial as an int, ignoring leading terms with a coefficient of zero
*/
public static int degreeCoeffsHighToLow(int [] coeffsHighToLow) {
return -42; // @@@ STUB!
}
/** Convert a list of coefficients in order from
highest degree to lowest degree (the order used
for input to the Polynomial constructor) to one where
the order is lowest degree to highest degree (where index matches
power of the x term).
@param coeffsHighToLow coefficients of a polynomial in order from highest degree to lowest degree. May have leading zeros.
@return An int [] with coefficients in order from lowest degree to highest degree. No trailing zeros.
*/
public static int [] lowToHigh(int [] coeffsHighToLow) {
int [] stub = new int [] {-42, -42, -42};
return stub;
}
/** Convert a list of coefficients in order from
lowest degree to highest degree (where index matches
power of the x term) to one in order from
highest degree to lowest degree (the order used
for input to the Polynomial constructor).
@param coeffsLowToHigh coefficients of a polynomial in order from lowest degree to highest degree. May have trailing zeros.
@return An int [] with coefficients in order from highest degree to lowest degree. No leading zeros.
*/
public static int [] highToLow(int [] coeffsLowToHigh) {
int [] stub = new int [] {-42, -42, -42};
return stub;
}
/** return a new Polynomial which has as its value the
this polynomial plus the one passed in as a parameter.
@param p the Polynomial to add to this one
@return sum of this Polynomial and p
*/
public Polynomial plus (Polynomial p) {
Polynomial stub = new Polynomial (new int [] {-42});
return stub;
}
/** return a new Polynomial which has as its value the
this polynomial times the one passed in as a parameter.
@param p the Polynomial to multiply this one by
@return product of this Polynomial and p
*/
public Polynomial times (Polynomial p) {
Polynomial stub = new Polynomial (new int [] {-42});
return stub; // @@@ TODO: FIXME!
}
/** return a new Polynomial which has as its value the
this polynomial minus the one passed in as a parameter.
@param p the Polynomial to subtract from this one
@return the result of this Polynomial minus p
*/
public Polynomial minus (Polynomial p) {
Polynomial stub = new Polynomial (new int [] {-42});
return stub; // @@@ TODO: FIXME!
}
/** Print Usage message for Polynomial main
*/
public static void usage() {
System.err.println("Usage: java Polynomial 'string' ");
System.err.println(" java Polynomial 'string' ");
}
/**
Main for testing constructing Polynomials from strings,
and for testing plus, minus and times.
At Unix command line, use single quotes to make the entire
Polynomial be a single argument, and use
\* when operating is * (to avoid
having * expanded as a wildcard.) For example:
java -cp build Polynomial 'x^2 + 2x + 3' \* 'x - 4'
*/
public static void main (String [] args) {
if (args.length < 1) {
Polynomial.usage();
System.exit(1); // error code 1
}
Polynomial p = new Polynomial(args[0]);
if (args.length == 1) {
System.out.println("p=" + p);
System.exit(0); // successful completion
}
if (args.length != 3) {
System.out.println("There should be either 1 cmd line argument or 3 arguments, but there were: " + args.length + " arguments.");
Polynomial.usage();
System.exit(1);
}
Polynomial p2 = new Polynomial(args[2]);
if (args[1].equals("+")) {
Polynomial result = p.plus(p2);
System.out.println("(" + p.toString() + ") + (" +
p2.toString() + ") = " + result.toString());
} else if (args[1].equals("-")) {
Polynomial result = p.minus(p2);
System.out.println("(" + p.toString() + ") - (" +
p2.toString() + ") = " + result.toString());
} else if (args[1].equals("*")) {
Polynomial result = p.times(p2);
System.out.println("(" + p.toString() + ") * (" +
p2.toString() + ") = " + result.toString());
} else {
System.out.println("Error: illegal operand:" + args[1]);
Polynomial.usage();
System.exit(2); // error code 2
}
} // end main
} // end class Polynomial