EECS2030 Lab 3 Feedback

1.8 / 2  -passes all unit and style tests?

--------------------
TA Comments:

-in valueOf, you should not use != to compare strings; strings are
reference value types, and you always use equals to compare 
reference value types for equality

--------------------
Style checker output:

--------------------
Unit tester output:

YOUR SUMBISSION FAILED SOME UNIT TESTS
Here is the test output:

java -classpath .:/home/burton/work/teaching/2017F/2030/marking/lab3/_jar/* org.junit.runner.JUnitCore eecs2030.lab3.Lab3Suite
JUnit version 4.12
.............E.....
Time: 0.035
There was 1 failure:

1) test11_valueOf(eecs2030.lab3.ComplexTest)
java.lang.IllegalArgumentException: Not a complex number

FAILURES!!!
Tests run: 18,  Failures: 1

--------------------

Your submission:

Complex.java

package eecs2030.lab3;

import java.util.Arrays;
import java.util.List;

/**
 * A class that represents immutable complex numbers.
 * 
 * @author EECS2030 Fall 2017-18
 * 
 */
public final class Complex {

        public static final Complex ONE = new Complex(1, 0);

        public static final Complex I = new Complex(0, 1);

        private final double real;

        private final double imag;

        /**
         * Initializes this complex number to <code>0 + 0i</code>.
         * 
         */
        public Complex() {
                this(0.0, 0.0);
        }

        /**
         * Initializes this complex number so that it has the same real and
         * imaginary parts as another complex number.
         * 
         * @param other
         *            the complex number to copy.
         */
        public Complex(Complex other) {
                this(other.real, other.imag);
        }

        /**
         * Initializes this complex number so that it has the given real and
         * imaginary components.
         * 
         * @param re
         *            the real part of the complex number.
         * @param im
         *            the imaginary part of the complex number.
         */
        public Complex(double re, double im) {
                this.real = re;
                this.imag = im;
        }

        /**
         * A static factory method that returns a new complex number whose real part
         * is equal to re and whose imaginary part is equal to 0.0
         * 
         * @param re
         *            the desired real part of the complex number
         * @return a new complex number whose real part is equal to re and whose
         *         imaginary part is equal to 0.0
         */
        public static Complex real(double re) {
                double real = re;
                double imag = 0.0;
                return new Complex(real, imag);
        }

        /**
         * A static factory method that returns a new complex number whose real part
         * is equal to 0.0 and whose imaginary part is equal to im
         * 
         * @param im
         *            the desired imaginary part of the complex number
         * @return a new complex number whose real part is equal to 0.0 and whose
         *         imaginary part is equal to im
         */
        public static Complex imag(double im) {
                double real = 0.0;
                double imag = im;
                return new Complex(real, imag);
        }

        /**
         * Get the real part of the complex number.
         * 
         * @return the real part of the complex number.
         */
        public double re() {

                return this.real;
        }

        /**
         * Get the imaginary part of the complex number.
         * 
         * @return the imaginary part of the complex number.
         */
        public double im() {

                return this.imag;
        }

        /**
         * Add this complex number and another complex number to obtain a new
         * complex number. Neither this complex number nor c is changed by this
         * method.
         * 
         * @param c
         *            The complex number to add to this complex number.
         * @return a new Complex number equal to the sum of this complex number and
         *         c.
         */
        public Complex add(Complex c) {
                double a = this.real + c.real;
                double b = this.imag + c.imag;
                return new Complex(a, b);
        }

        /**
         * Multiply this complex number with another complex number to obtain a new
         * complex number. Neither this complex number nor c is changed by this
         * method.
         * 
         * <p>
         * This is not an industrial strength implementation of complex number
         * multiplication. In particular, issues related to the differences between
         * <code>-0.0</code> and <code>0.0</code> and infinite real or imaginary
         * parts are not taken into account.
         * 
         * @param c
         *            The complex number to multiply by.
         * @return a new Complex number equal to this complex number multiplied by
         *         c.
         */
        public Complex multiply(Complex c) {
                double a = (this.real * c.real) - (this.imag * c.imag);
                double b = (this.imag * c.real) + (this.real * c.imag);
                return new Complex(a, b);
        }

        /**
         * Compute the magnitude of this complex number.
         * 
         * @return the magnitude of this complex number.
         */
        public double mag() {
                return Math.hypot(this.real, this.imag);
        }

        /**
         * Return a hash code for this complex number.
         * 
         * <p>
         * This implementation uses a very crude algorithm to compute the hash code;
         * the hash code is computed as follows:
         * 
         * <ol>
         * <li>compute the value equal to <code>9999</code> times the real part of
         * this complex number
         * <li>compute the value equal to <code>99</code> times the imaginary part
         * of this complex number
         * <li>compute the sum of the values computed in Steps 1 and 2
         * <li>casts the value computed in Step 3 to an <code>int</code>
         * <li>returns the value computed in Step 4
         * </ol>
         * 
         * <p>
         * In production code, consider implementing hashCode() using
         * {@link java.util.Objects#hash}
         * 
         * @return a hash code value for this complex number.
         */
        @Override
        public int hashCode() {
                double valueReal = 9999 * this.real;
                double valueImag = 99 * this.imag;
                double sum = valueReal + valueImag;
                return (int) sum;
        }

        /**
         * Compares this complex number with the specified object. The result is
         * <code>true</code> if and only if the argument is a <code>Complex</code>
         * number with the same real and imaginary parts as this complex number.
         * 
         * @param obj
         *            the object to compare this Complex number against.
         * @return true if the given object is a Complex number equal to this
         *         complex number, false otherwise.
         */
        @Override
        public boolean equals(Object obj) {
                if (this == obj) {
                        return true;
                }
                if (obj == null) {
                        return false;
                }
                if (getClass() != obj.getClass()) {
                        return false;
                }
                Complex other = (Complex) obj;
                return (this.real == other.real) && (this.imag == other.imag);
        }

        /**
         * Returns a string representation of this complex number.
         * 
         * <p>
         * The returned string is the real part of the complex number, followed by a
         * space, followed by a <code>+</code> or <code>-</code> sign, followed by a
         * space, followed by the absolute value of the imaginary part of the
         * complex number, followed by an <code>i</code>. The sign is <code>+</code>
         * if the imaginary part of the complex number is positive, and
         * <code>-</code> if the imaginary part of the complex number is negative.
         * 
         * For example the complex number with real and imaginary parts equal to
         * zero has the string representation <code>0.0 + 0.0i</code>. The complex
         * number with real part equal to zero and imaginary part equal to
         * <code>-1</code> has the string representation <code>0.0 - 1.0i</code>.
         * 
         * @return a string representation of this complex number.
         * 
         */
        @Override
        public String toString() {
                String sign;
                if (this.imag >= 0) {
                        sign = "+";
                } else {
                        sign = "-";
                }

                return this.real + " " + sign + " " + Math.abs(this.imag) + "i";
        }

        /**
         * Returns a complex number holding the value represented by the given
         * string.
         * 
         * <p>
         * <code>valueOf</code> tries to create a complex number from a string
         * representation of the complex number. Strings that can interpreted as
         * complex numbers are those strings returned by
         * <code>Complex.toString</code>.
         * 
         * @param s
         *            a string representation of a complex number.
         * @return a Complex number equal to the complex number represented by the
         *         given string.
         * @throws IllegalArgumentException
         *             if the string cannot be interpreted as a complex
         *             number. @pre. s has a space before and after the + or - sign
         *             separating the real and imaginary parts of the complex number
         */
        public static Complex valueOf(String s) {
                Complex result = null;
                String t = s.trim();
                List<String> parts = Arrays.asList(t.split("\\s+"));

                // split splits the string s by looking for spaces in s.
                // If s is a string that might be interpreted as a complex number
                // then parts will be a list having 3 elements. The first
                // element will be a real number, the second element will be
                // a plus or minus sign, and the third element will be a real
                // number followed immediately by an i.
                //
                // To complete the implementation of this method you need
                // to do the following:
                //
                // -check if parts has 3 elements
                // -check if the second element of parts is "+" or "-"
                // -check if the third element of parts ends with an "i"
                // -if any of the 3 checks are false then s isn't a complex number
                // and you should throw an exception
                // -if all of the 3 checks are true then s might a complex number
                // -try to convert the first element of parts to a double value
                // (use Double.valueOf); this might fail in which case s isn't
                // a complex number
                // -remove the 'i' from the third element of parts and try
                // to convert the resulting string to a double value
                // (use Double.valueOf); this might fail in which case s isn't
                // a complex number
                // -you now have real and imaginary parts of the complex number
                // but you still have to account for the "+" or "-" which
                // is stored as the second element of parts
                // -once you account for the sign, you can return the correct
                // complex number

                if (parts.size() != 3) {
                        throw new IllegalArgumentException("Not a complex number");
                }
                if (parts.get(1) != "+" || parts.get(1) != "-") {
                        throw new IllegalArgumentException("Not a complex number");
                }
                if (parts.get(2).endsWith("i") == false) {
                        throw new IllegalArgumentException("Not a complex number");
                }

                double real = Double.valueOf(parts.get(0));
                double imagAbs = Double.valueOf(parts.get(2).replace("i", ""));

                double imag;
                if (parts.get(1) == "-") {
                        imag = imagAbs * -1;
                } else {
                        imag = imagAbs;
                }

                result = new Complex(real, imag);

                return result;
        }

}

MandelbrotUtil.java

package eecs2030.lab3;

public class MandelbrotUtil {

        private MandelbrotUtil() {

        }

        /**
         * Return the number of iterations needed to determine if z(n + 1) = z(n) *
         * z(n) + c remains bounded where z(0) = 0 + 0i. z(n + 1) is bounded if its
         * magnitude is less than or equal to 2. Returns 1 if the magnitude of c is
         * greater than 2. Returns max if the magnitude of z(n + 1) is less than or
         * equal to 2 after max iterations.
         * 
         * <p>
         * If z(n + 1) remains bounded after max iterations then c is assumed to be
         * in the Mandelbrot set.
         * 
         * @param c
         *            a complex number
         * @param max
         *            the maximum number of iterations to attempt
         * @return the number of iterations needed to determine if z(n + 1) = z(n) *
         *         z(n) + c remains bounded where z(0) = 0.0 + 0.0i. @pre. max is
         *         greater than 0
         */
        public static int mandelbrotIterations(Complex c, int max) {
                Complex z = new Complex(0.0, 0.0);
                Complex zn = new Complex(0.0, 1.0);

                // You need a loop here. Inside the loop, set z to z * z + c
                // (i.e. perform one iteration of the equation) and
                // check if the magnitude of z is greater than 2; if
                // the magnitude is greater than 2 then return the
                // number of times you computed z * z + c.
                // If you compute z * z + c max times and the magnitude
                // of z is still less than or equal to 2 you should
                // return max.

                if (c.mag() > 2) {
                        return 1;
                }

                for (int i = 0; i < max; i++) {
                        zn = z.multiply(z).add(c);
                        double zMag = z.mag();
                        if (zMag > 2) {
                                return i;
                        }
                        z = zn;
                }

                return max;
        }
}