Point.java
import edu.princeton.cs.algs4.StdDraw;
import java.util.Comparator;
public class Point implements Comparable {
private int x, y;
public Point(int x, int y) {
this.x = x;
this.y = y;
}
public void draw() {
StdDraw.point(this.x, this.y);
} // draws this point
public void drawTo(Point that) {
StdDraw.line(this.x, this.y, that.x, that.y);
}
public String toString() {
return "(" + x + ", " + y + ")";
}
@Override
public int compareTo(Point that) {
if ((this.x == that.x) && (this.y == that.y)) {
return 0;
} else if ((that.y > this.y) ||
((that.y == this.y) && (that.x > this.x))) {
return -1;
} else {
return 1;
}
}
public double slopeTo(Point point) {
int dx = point.x - this.x;
int dy = point.y - this.y;
if (dx == 0 && dy == 0) return Double.NEGATIVE_INFINITY;
if (dx == 0) return Double.POSITIVE_INFINITY;
if (dy == 0) return +0;
else return (double) dy / (double) dx;
}
public Comparator slopeOrder() {
return new SlopeOrder(this);
}
private class SlopeOrder implements Comparator {
private Point p0;
public SlopeOrder(Point invokePoint) {
p0 = invokePoint;
}
public int compare(Point p1, Point p2) {
double d01 = p0.slopeTo(p1);
double d02 = p0.slopeTo(p2);
if (d01 < d02) {
return -1;
} else if (d01 > d02) {
return 1;
} else {
return 0;
}
}
}
}
LineSegment .java
public class LineSegment {
private Point p, q;
public LineSegment(Point p, Point q) {
} // constructs the line segment between points p and q
public void draw() {
} // draws this line segment
public String toString() {
return p + " -> " + q;
}
}
BruteCollinearPoints .java
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import java.util.Arrays;
public class BruteCollinearPoints {
private int lineNumber;
private Node last;
public BruteCollinearPoints(Point[] points) // finds all line segments containing 4 points
{
if (points == null) {
throw new NullPointerException();
}
lineNumber = 0;
int num = points.length;
Point[] clone = new Point[num];
for (int i = 0; i < num; i++) {
if (points[i] == null) {
throw new NullPointerException();
}
for (int j = i + 1; j < num; j++) {
if (points[i].compareTo(points[j]) == 0) {
throw new IllegalArgumentException();
}
}
clone[i] = points[i];
}
Arrays.sort(clone);
for (int i = 0; i < num; i++) {
for (int j = i + 1; j < num; j++) {
for (int m = j + 1; m < num; m++) {
for (int n = m + 1; n < num; n++) {
double d01 = clone[i].slopeTo(clone[j]);
double d02 = clone[j].slopeTo(clone[m]);
double d03 = clone[m].slopeTo(clone[n]);
if (d01 == d02 && d01 == d03) {
if (last != null) {
Node newNode = new Node();
newNode.prev = last;
newNode.value = new LineSegment(clone[i],
clone[n]);
last = newNode;
} else {
last = new Node();
last.value = new LineSegment(clone[i],
clone[n]);
}
lineNumber++;
}
}
}
}
}
}
public int numberOfSegments() // the number of line segments
{
return lineNumber;
}
public LineSegment[] segments() // the line segments
{
LineSegment[] lines = new LineSegment[lineNumber];
Node current = last;
for (int i = 0; i < lineNumber; i++) {
lines[i] = current.value;
current = current.prev;
}
return lines;
}
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++) {
int x = in.readInt();
int y = in.readInt();
points[i] = new Point(x, y);
}
// 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
BruteCollinearPoints collinear = new BruteCollinearPoints(points);
for (LineSegment segment : collinear.segments()) {
StdOut.println(segment);
segment.draw();
}
StdDraw.show();
}
private class Node {
private LineSegment value;
private Node prev;
}
}
FastCollinearPoints .java
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdDraw;
import edu.princeton.cs.algs4.StdOut;
import java.util.Arrays;
public class FastCollinearPoints {
private int lineNumber;
private Node last;
public FastCollinearPoints(Point[] points) // finds all line segments containing 4 or more points
{
if (points == null) {
throw new NullPointerException();
}
lineNumber = 0;
int num = points.length;
Point[] clone = new Point[num];
for (int i = 0; i < num; i++) {
if (points[i] == null) {
throw new NullPointerException();
}
for (int j = i + 1; j < num; j++) {
if (points[i].compareTo(points[j]) == 0) {
throw new IllegalArgumentException();
}
}
clone[i] = points[i];
}
Arrays.sort(clone);
if (num < 4) {
return;
}
for (int i = 0; i < num - 1; i++) {
int tempPointsNum = 0;
Point[] tempPoints = new Point[num - 1];
for (int j = 0; j < num; j++) {
if (i != j) tempPoints[tempPointsNum++] = clone[j];
}
Arrays.sort(tempPoints, clone[i].slopeOrder());
int count = 0;
Point min = null;
Point max = null;
for (int j = 0; j < (tempPointsNum - 1); j++) {
if (clone[i].slopeTo(tempPoints[j]) == clone[i].slopeTo(
tempPoints[j + 1])) {
if (min == null) {
if (clone[i].compareTo(tempPoints[j]) > 0) {
max = clone[i];
min = tempPoints[j];
} else {
max = tempPoints[j];
min = clone[i];
}
}
if (min.compareTo(tempPoints[j + 1]) > 0) {
min = tempPoints[j + 1];
}
if (max.compareTo(tempPoints[j + 1]) < 0) {
max = tempPoints[j + 1];
}
count++;
if (j == (tempPointsNum - 2)) {
if (count >= 2 && clone[i].compareTo(min) == 0) {
addLine(min, max);
}
count = 0;
min = null;
max = null;
}
} else {
if (count >= 2 && clone[i].compareTo(min) == 0) {
addLine(min, max);
}
count = 0;
min = null;
max = null;
}
}
}
}
private void addLine(Point a, Point b) {
if (last != null) {
Node newNode = new Node();
newNode.prev = last;
newNode.value = new LineSegment(a, b);
last = newNode;
} else {
last = new Node();
last.value = new LineSegment(a, b);
}
lineNumber++;
}
public int numberOfSegments() // the number of line segments
{
return lineNumber;
}
public LineSegment[] segments() // the line segments
{
LineSegment[] lines = new LineSegment[lineNumber];
Node current = last;
for (int i = 0; i < lineNumber; i++) {
lines[i] = current.value;
current = current.prev;
}
return lines;
}
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++) {
int x = in.readInt();
int y = in.readInt();
points[i] = new Point(x, y);
}
// 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
FastCollinearPoints collinear = new FastCollinearPoints(points);
for (LineSegment segment : collinear.segments()) {
StdOut.println(segment);
segment.draw();
}
StdDraw.show();
}
private class Node {
private LineSegment value;
private Node prev;
}
}