普林斯顿算法第一部分的作业3中的不变数据类型错误

时间:2019-06-02 03:46:22

标签: java algorithm sorting

我正在做week 3 Assignment of Princeton Algorithm Part I。最后一部分是我对类BruteCollinearPoints的编码。我无法通过以下测试。该测试表明,在我新建对象BruteCollinearPoints之后,它对输入数组points进行了突变,并发现更改了我的对象BruteCollinearPoints的实例变量。

我当然知道避免这种失败的直接方法是将points的每个元素复制到另一个arrayNew。然后对arrayNew执行操作。但是我想知道使我的代码错误的具体示例。由于结果将直接指向不可变的Point对象,因此如何对Point[] points进行突变才能更改结果?我在IDE中尝试了许多方法,但无法重现此错误。我真的希望有人可以向我展示可靠的示例来使此错误发生,并使我对不可变数据类型有更深入的了解。谢谢。

它给我一种如下感觉:

Item[] array = new Item[]{item0, item1, item2, item3} // Item is some immutable type.
Item[] array2 = new Item[2];
array2[0] = array[2];
array2[1] = array[1];
.....// Then doing some operation on ``array``
.....// Then my array2[0] array2[1] will change.

怎么可能?我的代码中应该有一些漏洞,但我看不到。我真的很想了解这个漏洞,而不是直接使用另一个绝对权利绕过它。

===========

Test 10: check that data type is immutable by testing whether each method
     returns the same value, regardless of any intervening operations
* input8.txt
- failed after 11 operations involving BruteCollinearPoints
- first and last call to segments() returned different arrays

- sequence of operations was:
      BruteCollinearPoints collinear = new 

BruteCollinearPoints(points);
      collinear.segments()
      mutate array returned by last call to segments()
      mutate array returned by last call to segments()
      collinear.numberOfSegments() -> 2
      mutate array returned by last call to segments()
      collinear.numberOfSegments() -> 2
      collinear.numberOfSegments() -> 2
      mutate points[] array that was passed to constructor
      mutate array returned by last call to segments()
      collinear.segments()

- failed on trial 1 of 100

* equidistant.txt
- failed after 22 operations involving BruteCollinearPoints
- first and last call to segments() returned different arrays

- failed on trial 1 of 100

==> FAILED

=========================

import java.util.Arrays;

public class BruteCollinearPoints {    
    private final LineSegment[] lineResults;
    private final int numOfSeg;
    public BruteCollinearPoints(Point[] points) {
        if (points == null || points.length == 0) {
            throw new IllegalArgumentException();
        }

        for (Point p : points) {
            if (p == null) {
                throw new IllegalArgumentException();
            }
        }        
        for (int i = 0; i < points.length - 1; i++) {
            for(int j = i + 1; j < points.length; j++ ) {
                if (points[i].compareTo(points[j]) == 0) {
                    throw new IllegalArgumentException();
                }
            }                
        }
        Point[][] results = new Point[points.length][4];
        int tempNumOfSeg = 0;
        for (int i = 0; i < points.length; i++) {
            for (int j = i + 1; j < points.length; j++) {
               double slopeij = points[i].slopeTo(points[j]);
               for (int k = j + 1; k < points.length; k++) {
                   if (points[i].slopeTo(points[k]) == slopeij) {
                       for (int l = k + 1; l < points.length; l++) {
                           if (points[i].slopeTo(points[l]) == slopeij) {
                               results[tempNumOfSeg][0] = points[i];
                               results[tempNumOfSeg][1] = points[j];
                               results[tempNumOfSeg][2] = points[k];
                               results[tempNumOfSeg][3] = points[l];
                               Arrays.sort(results[tempNumOfSeg]);
                               tempNumOfSeg++;
                           }
                       }
                   }
               }
            }
        }
        LineSegment[] tempLineResults = new LineSegment[tempNumOfSeg];
        for (int i = 0; i < tempNumOfSeg; i++) {
            tempLineResults[i] = new LineSegment(results[i][0],results[i][3]);
        }
        lineResults = tempLineResults;
        numOfSeg = tempNumOfSeg;

    }    // finds all line segments containing 4 points
    public int numberOfSegments() {
        return numOfSeg;
    }        // the number of line segments
    public LineSegment[] segments() {
        return lineResults;
    }                // the line segments

    public static void main(String[] args) {
     // read the n points from a file

    }    
}

解决方案

将此代码用作参考

import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.MergeX;

public class BruteCollinearPoints {

    private final LineSegment[] segments;
    private int segmentsSize = 0;

    /** finds all line segments containing 4 points */
    public BruteCollinearPoints(Point[] points) {
        if (points == null) {
            throw new IllegalArgumentException("points can't be null");
        }
        for (Point p : points) {
            if (p == null) {
                throw new IllegalArgumentException("point can't be null");
            }
        }

        Point[] p = new Point[points.length];
        System.arraycopy(points, 0, p, 0, points.length);
        segments = analyzeSegments(p);
    }

    private LineSegment[] analyzeSegments(Point[] points) {
        LineSegment[] tmpSegments = new LineSegment[points.length * 4];
        MergeX.sort(points);
        for (int i = 0; i < points.length; i++) {
            for (int j = i + 1; j < points.length; j++) {
                for (int k = j + 1; k < points.length; k++) {
                    for (int m = k + 1; m < points.length; m++) {
                        Point p = points[i];
                        Point q = points[j];
                        Point r = points[k];
                        Point s = points[m];
                        if (Double.compare(p.slopeTo(q), p.slopeTo(r)) == 0 && Double.compare(p.slopeTo(q), p.slopeTo(s)) == 0) {
                            tmpSegments[segmentsSize++] = new LineSegment(p, s);
                        }
                    }
                }
            }
        }
        LineSegment[] resultSegments = new LineSegment[segmentsSize];
        for (int i = 0; i < segmentsSize; i++) {
            resultSegments[i] = tmpSegments[i];
        }
        return resultSegments;
    }

    /** the number of line segments */
    public int numberOfSegments() {
        return segmentsSize;
    }

    /** the line segments */
    public LineSegment[] segments() {
        LineSegment[] returnSegments = new LineSegment[segments.length];
        System.arraycopy(segments, 0, returnSegments, 0, segments.length);
        return returnSegments;
    }

    public static void main(String[] args) {
        // read the n points from a file
        In in = new In(args[0]);
        int n = in.readInt();
        Point[] points = new Point[n];
        for (int i = 0; i < n; i++) {
            String s = in.readString();
            if ("null".equals(s)) {
                points[i] = null;
            } else {
                int x = Integer.parseInt(s);
                int y = in.readInt();
                points[i] = new Point(x, y);
            }
        }

        BruteCollinearPoints collinear = new BruteCollinearPoints(points);

        // draw the points
        StdDraw.enableDoubleBuffering();
        StdDraw.setXscale(0, 32768);
        StdDraw.setYscale(0, 32768);
        for (Point p : points) {
            p.draw();
        }
        StdDraw.show();

        // print and draw the line segments
        for (LineSegment segment : collinear.segments()) {
            StdOut.println(segment);
            segment.draw();
        }
        StdDraw.show();
    }
}

顺便说一句,这是一门很棒的课程

0 个答案:

没有答案