Java Classes - Point Line Polynomial
Practical exercises for week 3, building up a small geometry class hierarchy (Point → Line → Polynomial) to practice java-encapsulation and java-mutability (note that movePoint/flipPoint/scale-style methods return a new object rather than mutating this).
On the HTML site, fill in each blank with your answer (as a quoted string, e.g. "5.0"), then click Run Code to check it. In the PDF, the Working callout is shown as a static answer key instead (interactive checking needs a browser).
Question 1 — Points
Write a Point class representing an x,y-coordinate on a Cartesian plane, with:
Point(float x, float y)and a defaultPoint()(both 0).getX()/getY().Point movePoint(float deltaX, float deltaY)— returns a newPointat(getX() + deltaX, getY() + deltaY), without modifyingthis.static double distance(Point p, Point q)— Euclidean distance between two points.
If p1 = new Point() and p2 = p1.movePoint(4, 5), what does p2 print (assuming a toString of "(" + x + ", " + y + ")")?
public class Point {
private float x;
private float y;
public Point() {
this(0, 0);
}
public Point(float x, float y) {
this.x = x;
this.y = y;
}
public float getX() { return this.x; }
public float getY() { return this.y; }
public Point movePoint(float deltaX, float deltaY) {
return new Point(this.x + deltaX, this.y + deltaY);
}
public static double distance(Point p, Point q) {
double x = p.x - q.x;
double y = p.y - q.y;
return Math.sqrt(x * x + y * y);
}
@Override
public String toString() {
return "(" + x + ", " + y + ")";
}
}movePoint deliberately returns a new Point rather than mutating this — p1 is left unchanged at (0.0, 0.0).
Question 2 — Lines
Write a Line class storing a start Point, an end Point, and the (precomputed) double length between them, with:
Line(Point start, Point end)and a defaultLine()(both ends at the origin, length 0).getStart()/getEnd()/getLength().void moveStart(float deltaX, float deltaY)/void moveEnd(float deltaX, float deltaY)— mutate the line’s start/end in place and recompute the length.
For a Line from (0, 0) to (3, 4), what is getLength()?
public class Line {
private Point start;
private Point end;
private double length;
public Line() {
this.start = new Point();
this.end = new Point();
this.length = 0;
}
public Line(Point start, Point end) {
this.start = start;
this.end = end;
this.length = Point.distance(start, end);
}
public Point getStart() { return start; }
public Point getEnd() { return end; }
public double getLength() { return length; }
public void moveStart(float deltaX, float deltaY) {
start = start.movePoint(deltaX, deltaY);
length = Point.distance(start, end);
}
public void moveEnd(float deltaX, float deltaY) {
end = end.movePoint(deltaX, deltaY);
length = Point.distance(start, end);
}
@Override
public String toString() {
return start.toString() + " " + end.toString() + " " + this.getLength();
}
}(0,0) to (3,4) is a 3-4-5 right triangle, so the length is exactly 5.0 — unlike Point, moveStart/moveEnd mutate the Line in place (a deliberately different, mutable design from Point’s immutable movePoint).
Question 3 — Testing and toString
Unless overridden, printing an object prints its class name and memory location, e.g. Point@30f39991. Overriding toString() (as used above) replaces this with something readable — always worth adding when testing a class by eye.
Writing a quick main to sanity-check as you go (rather than writing a large class fully before ever running it) catches mistakes early:
Point p1 = new Point();
Point p2 = p1.movePoint(4, 5);
System.out.println(p1); // (0.0, 0.0)
System.out.println(p2); // (4.0, 5.0)Question 4 — Additional methods
Add to Point:
Line createLine(Point end)— aLinefromthistoend.Point flipPoint()— negates both coordinates, e.g.(-1, 2)becomes(1, -2).
Add to Line:
Point middle()— the midpoint of the start and end.Line flipLine()— aLinewith both endpoints flipped.
What does new Point(-1, 2).flipPoint() print?
public Line createLine(Point end) {
return new Line(this, end);
}
public Point flipPoint() {
return new Point(x * -1, y * -1);
}
public Point middle() {
return new Point((start.getX() + end.getX()) / 2, (start.getY() + end.getY()) / 2);
}
public Line flipLine() {
return new Line(start.flipPoint(), end.flipPoint());
}Question 5 — Polynomials (bonus)
A polynomial function of the restricted form \(f(x) = a + bx + cx^2\) can be represented by its coefficients. Write a Polynomial class with constructors Polynomial(), Polynomial(float a), Polynomial(float a, float b), Polynomial(float a, float b, float c), plus:
float valueAt(float x)— evaluates the polynomial atx.Polynomial add(Polynomial other)— adds two polynomials coefficient-wise, returning a newPolynomial.
For \(f(x) = 1 + 2x\), what is \(f(3)\)?
public class Polynomial {
private final float[] coefficients;
public Polynomial() { coefficients = new float[]{0}; }
public Polynomial(float a) { coefficients = new float[]{a}; }
public Polynomial(float a, float b) { coefficients = new float[]{a, b}; }
public Polynomial(float a, float b, float c) { coefficients = new float[]{a, b, c}; }
public Polynomial(float[] coefficients) { this.coefficients = coefficients; }
private static float index(float[] coefficients, int index) {
// Coefficients beyond the polynomial's degree are implicitly 0.
if (index >= coefficients.length) {
return 0;
}
return coefficients[index];
}
public Polynomial add(Polynomial other) {
int max = Math.max(coefficients.length, other.coefficients.length);
float[] newCoefficients = new float[max];
for (int i = 0; i < max; i++) {
newCoefficients[i] = index(coefficients, i) + index(other.coefficients, i);
}
return new Polynomial(newCoefficients);
}
public float valueAt(float x) {
float v = 0;
float xpower = 1;
for (int i = 0; i < coefficients.length; i++) {
v += coefficients[i] * xpower; // xpower == x^i
xpower *= x;
}
return v;
}
}\(f(3) = 1 + 2 \times 3 = 7\).
Challenge — representing the unrestricted polynomial \(f(x) = a_0 + a_1x + \dots + a_nx^n\) for any \(n \geq 0\) (rather than fixing the degree at 2) just needs the internal representation generalised to a float[] coefficients array of arbitrary length, as already used by add’s newCoefficients array and the extra Polynomial(float[]) constructor above — valueAt and add already work unchanged for any length.