Coursera-Algorithms,Part I-Robert Sedgewick-Programming Assignment 3

Programming Assignment 3: Collinear Points

问题描述

Point.java

/******************************************************************************
 *  Compilation:  javac Point.java
 *  Execution:    java Point
 *  Dependencies: none
 *  
 *  An immutable data type for points in the plane.
 *  For use on Coursera, Algorithms Part I programming assignment.
 *
 ******************************************************************************/

import java.util.Arrays;
import java.util.Comparator;
import edu.princeton.cs.algs4.StdDraw;

public class Point implements Comparable<Point> {

    private final int x;     // x-coordinate of this point
    private final int y;     // y-coordinate of this point

    /**
     * Initializes a new point.
     *
     * @param  x the <em>x</em>-coordinate of the point
     * @param  y the <em>y</em>-coordinate of the point
     */
    public Point(int x, int y) {
        /* DO NOT MODIFY */
        this.x = x;
        this.y = y;
    }

    /**
     * Draws this point to standard draw.
     */
    public void draw() {
        /* DO NOT MODIFY */
        StdDraw.point(x, y);
    }

    /**
     * Draws the line segment between this point and the specified point
     * to standard draw.
     *
     * @param that the other point
     */
    public void drawTo(Point that) {
        /* DO NOT MODIFY */
        StdDraw.line(this.x, this.y, that.x, that.y);
    }

    /**
     * Returns the slope between this point and the specified point.
     * Formally, if the two points are (x0, y0) and (x1, y1), then the slope
     * is (y1 - y0) / (x1 - x0). For completeness, the slope is defined to be
     * +0.0 if the line segment connecting the two points is horizontal;
     * Double.POSITIVE_INFINITY if the line segment is vertical;
     * and Double.NEGATIVE_INFINITY if (x0, y0) and (x1, y1) are equal.
     *
     * @param  that the other point
     * @return the slope between this point and the specified point
     */
    public double slopeTo(Point that) {
        /* YOUR CODE HERE */
        if (this.compareTo(that) == 0) return Double.NEGATIVE_INFINITY;
        if (this.x == that.x) return Double.POSITIVE_INFINITY;
        if (this.y == that.y) return +0.0;
        return (this.y - that.y) * 1.0 / (this.x - that.x);
    }

    /**
     * Compares two points by y-coordinate, breaking ties by x-coordinate.
     * Formally, the invoking point (x0, y0) is less than the argument point
     * (x1, y1) if and only if either y0 < y1 or if y0 = y1 and x0 < x1.
     *
     * @param  that the other point
     * @return the value <tt>0</tt> if this point is equal to the argument
     *         point (x0 = x1 and y0 = y1);
     *         a negative integer if this point is less than the argument
     *         point; and a positive integer if this point is greater than the
     *         argument point
     */
    public int compareTo(Point that) {
        /* YOUR CODE HERE */
        if (this.x == that.x && this.y == that.y) return 0;
        if (this.y < that.y || (this.y == that.y && this.x < that.x)) return -1;
        else return 1;
    }

    /**
     * Compares two points by the slope they make with this point.
     * The slope is defined as in the slopeTo() method.
     *
     * @return the Comparator that defines this ordering on points
     */
    public Comparator<Point> slopeOrder() {
        /* YOUR CODE HERE */
        return new BySlopeToThis();
    }

    private class BySlopeToThis implements Comparator<Point>
    {
        public int compare(Point a, Point b)
        {
            Double slopeOfA = a.slopeTo(Point.this);
            Double slopeOfB = b.slopeTo(Point.this);
            return slopeOfA.compareTo(slopeOfB);
        }
    }

    /**
     * Returns a string representation of this point.
     * This method is provide for debugging;
     * your program should not rely on the format of the string representation.
     *
     * @return a string representation of this point
     */
    public String toString() {
        /* DO NOT MODIFY */
        return "(" + x + ", " + y + ")";
    }

    /**
     * Unit tests the Point data type.
     */
    public static void main(String[] args) {
        /* YOUR CODE HERE */
        Point p1 = new Point(0,0);
        Point p2 = new Point(1,2);
        Point p3 = new Point(2,4);
        Point p4 = new Point(3,6);
        Point p5 = new Point(4,8);
        Point p6 = new Point(5,5);  
        Point p7 = new Point(6,6);
        Point p8 = new Point(7,7);
        Point p9 = new Point(8,8);
        Point p10 = new Point(9,0);
        Point p11 = new Point(11,0);
        Point p12 = new Point(12,0);

        Point[] points = { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12};

        FastCollinearPoints fcp = new FastCollinearPoints(points);
        BruteCollinearPoints bcp = new BruteCollinearPoints(points);

        for (LineSegment s: bcp.segments())
        System.out.print(s.toString());

        System.out.println();

        for (LineSegment s: fcp.segments())
        System.out.print(s.toString());

    }
}

BruteCollinearPoints,java

import java.util.Arrays;

public class BruteCollinearPoints {

    private int numberOfSegments;
    private LineSegment[] segments;
    public BruteCollinearPoints(Point[] points)    // finds all line segments containing 4 points
    {
        // Exception 1
        if (points == null ) throw new java.lang.IllegalArgumentException();

        int N = points.length;      
        Point[] copy = new Point[N];

        // Exception 2
        for (int i = 0; i < N; i++)
        {
            if (points[i] == null) 
                throw new java.lang.IllegalArgumentException();
            copy[i] = points[i];
        }

        // Exception 3
        Arrays.sort(copy);
        Point previousPoint = copy[0];
        for (int i = 1; i < N; i++)
        {
            if (copy[i].compareTo(previousPoint) == 0) 
                throw new java.lang.IllegalArgumentException();
            previousPoint = copy[i];
        }

        segments = new LineSegment[N*N];
        numberOfSegments = 0;

        for (int i = 0; i < N; i++)
        {
            for (int j = i + 1 ; j < N; j++)
            {
                for (int k = j + 1; k < N; k++)
                {
                    for (int l = k + 1; l < N; l++) // ensure uniqueness: (i,j,k,l) comply with certain order
                                                    // therefore a segment has one and only one representation
                    {
                        if (isCollinear(copy[i], copy[j], copy[k], copy[l]))
                            store(copy[i], copy[j], copy[k], copy[l]);
                    }
                }
            }
        }
    }
    private boolean isCollinear(Point a, Point b, Point c, Point d)
    {   
        return (a.slopeTo(b) == a.slopeTo(c)) && (a.slopeTo(b) == a.slopeTo(d));
    }

    private void store(Point a, Point b, Point c, Point d)
    {
        Point[] p = {a, b, c, d};
        Arrays.sort(p); // guarantee the order and thus get the beginning and end
        LineSegment ls = new LineSegment(p[0],p[3]);
        segments[numberOfSegments++] = ls;
    }

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

    public LineSegment[] segments()                // the line segments
    {   
        LineSegment[] result = new LineSegment[numberOfSegments];
        for (int i = 0; i < numberOfSegments; i++) result[i] = segments[i];     
        return result;  
    }
}

FastCollinearPoints.java

import java.util.Arrays;

public class FastCollinearPoints {
    private int numberOfSegments;
    private LineSegment[] segments;

    public FastCollinearPoints(Point[] points)     // finds all line segments containing 4 or more points
    {
        // Exception 1
        if (points == null ) throw new java.lang.IllegalArgumentException();

        int N = points.length;      
        Point[] originPoints  = new Point[N]; // points to which we calculate slope 
        Point[] pointsToCheck = new Point[N]; // points we're to check if collinear with the origin

        // Exception 2
        for (int i = 0; i < N; i++)
        {
            if (points[i] == null) 
                throw new java.lang.IllegalArgumentException();
            originPoints[i]  = points[i];
            pointsToCheck[i] = points[i];
        }

        // Exception 3
        Arrays.sort(originPoints);
        for (int i = 1; i < N; i++)
        {
            if (originPoints[i].compareTo(originPoints[i-1]) == 0) 
                throw new java.lang.IllegalArgumentException();
        }

        numberOfSegments = 0;
        segments = new LineSegment[N*N];

        for (int i = 0; i < N; i++)
        {
            Point origin = originPoints[i];
            //  System.out.println("\nOrigin:"+ origin.toString());  // Debugging Info: print origin

            Arrays.sort(pointsToCheck); // necessary: make points in ascending natural order when their slopes are equal        
            Arrays.sort(pointsToCheck, origin.slopeOrder());

            Point start = null; // the first encountered point collinear with the origin, also the 'smallest' one
            Point stop  = null; // the last  encountered point collinear with the origin, also the 'largest'  one
            int   count =    0; // number of check points that are collinear with the origin

            start = pointsToCheck[0];
            count = 1;
            for (int j = 1 ; j < N; j++)
            {   
                //  System.out.print(pointsToCheck[j].toString()+" ");   // Debugging Info: print point being checked 
                if (origin.slopeTo(pointsToCheck[j]) != origin.slopeTo(pointsToCheck[j-1]))
                {   
                    // Situation 1: slope changes, check if we've got 4 or more
                    if (count >= 3) 
                    {
                        stop = pointsToCheck[j-1];
                        checkAndStore(start, stop, origin); // check if unique, if so, store
                    }
                    start = pointsToCheck[j];
                    count = 1;
                }
                else 
                {
                    count++;
                    // Situation 2: slope stay same, but pointToCheck[] ends, check if we've got 4 or more
                    if (j == N-1 && count >=3)
                    {
                        stop = pointsToCheck[j];
                        checkAndStore(start, stop, origin);                 
                    }
                }       
            }
        }
    }

    // A segment can be found N times with each of its N points assigned as 'origin', select 
    // ONE situation only to ensure uniqueness. Here the choice is only when the origin is
    // the 'smallest' point in the segment, that is origin is even 'smaller' than start.
    //   [Illustration]
    // 
    //             (origin)----(start)--()-()-()-()----(stop)
    //
    // When alias segment is found, just return and do not store it.

    private void checkAndStore(Point start, Point stop, Point origin)
    {   
        if (origin.compareTo(start) >= 0 ) return;
        else 
        {
            LineSegment ls = new LineSegment(origin, stop);
            segments[numberOfSegments++] = ls;
            //  System.out.print("[" + ls.toString() + "]" ); // Debugging Info: findings
        }
    }

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

    public LineSegment[] segments()                // the line segments
    {   
        LineSegment[] result = new LineSegment[numberOfSegments];
        for (int i = 0; i < numberOfSegments; i++) result[i] = segments[i];     
        return result;  
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值