您的位置:首页 > 编程语言 > Go语言

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

2018-03-10 13:40 429 查看

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
;

// 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
; // points to which we calculate slope
Point[] pointsToCheck = new Point
; // 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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 Coursera 共线