I need help to debug my code for the following challenge - https://www.hackerrank.com/challenges/maximizing-mission-points/problem
I've followed the lines of code from - https://www.geeksforgeeks.org/segment-tree-set-1-sum-of-given-range/.
My code is as below :
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
class SegmentTreeRMQ {
int st[][];
int minVal(int x, int y) {
return (x < y) ? x : y;
}
int getMid(int s, int e) {
return s + (e - s) / 2;
}
int RMQUtil(int sx1, int sy1, int sx2, int sy2, int x1, int y1, int x2, int y2, int index1, int index2)
{
// If segment of this node is a part of given range, then
// return the min of the segment
if (x1 <= sx1 && y1 <= sy1 && x2 >= sx2 && y2 >= sy2)
return st[index1][index2];
// If segment of this node is outside the given range
if ((sx1 < x1 && sy1 < y1) || (sx2 > x2 && sy2 > y2))
return Integer.MIN_VALUE;
// If a part of this segment overlaps with the given range
int midx = getMid(sx1, sx2);
int midy = getMid(sy1, sy2);
return minVal(RMQUtil(sx1, sy1, midx, midy, x1, y1, x2, y2, 2 * index1 + 1, 2 * index2 + 1),
RMQUtil(midx + 1, midy + 1, sx2, sy2, x1, y1, x2, y2, 2 * index1 + 2, 2 * index2 + 2));
}
int RMQ(int n, int m, int x1, int y1, int x2, int y2)
{
// Check for erroneous input values
/*if (x1< 0 || x2 > n - 1 || x1 > x2) {
System.out.println("Invalid Input "+x1+" "+x2);
return -1;
}
if (y1< 0 || y2 > m - 1 || y1 > y2) {
System.out.println("Invalid Input");
return -1;
}*/
return RMQUtil(0, 0, n - 1, m - 1, x1, y1, x2, y2, 0, 0);
}
int constructSTUtil(int arr[][], int x1, int y1, int x2, int y2, int si, int sj)
{
// If there is one element in array, store it in current
// node of segment tree and return
if (x1 == x2 && y1 == y2) {
st[si][sj] = arr[x1][y1];
return arr[x1][y1];
}
// If there are more than one elements, then recur for left and
// right subtrees and store the minimum of two values in this node
int midx = getMid(x1, x2);
int midy = getMid(y1, y2);
st[si][sj] = minVal(constructSTUtil(arr, x1, y1, midx, midy, si * 2 + 1, sj * 2 + 1),
constructSTUtil(arr, midx + 1, midy + 1, x2, y2, si * 2 + 2, sj * 2 + 2));
return st[si][sj];
}
void constructST(int arr[][], int n, int m)
{
// Allocate memory for segment tree
//Height of segment tree
int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));
int y = (int) (Math.ceil(Math.log(m) / Math.log(2)));
//Maximum size of segment tree
int max_size_x = 2 * (int) Math.pow(2, x) - 1;
int max_size_y = 2 * (int) Math.pow(2, y) - 1;
st = new int[max_size_x][max_size_y]; // allocate memory
// Fill the allocated memory st
constructSTUtil(arr, 0, 0, n - 1, m - 1, 0, 0);
}
}
class City implements Comparator<City> {
int latitude;
int longitude;
int height;
int points;
public City() {
}
public int compare(City c1, City c2){
return c1.height - c2.height;
}
}
public class Solution {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int d_lat = in.nextInt();
int d_long = in.nextInt();
ArrayList<City> cities = new ArrayList<City>();
for(int a0 = 0; a0 < n; a0++){
int latitude = in.nextInt();
int longitude = in.nextInt();
int height = in.nextInt();
int points = in.nextInt();
// Write Your Code Here
City city = new City();
city.latitude = latitude;
city.longitude = longitude;
city.height = height;
city.points = points;
cities.add(city);
}
Collections.sort(cities, new City());
int max_lat = Integer.MIN_VALUE;
int min_lat = Integer.MAX_VALUE;
int max_long = Integer.MIN_VALUE;
int min_long = Integer.MAX_VALUE;
for(City city : cities){
if(city.latitude > max_lat){
max_lat = city.latitude;
}
if(city.latitude < min_lat){
min_lat = city.latitude;
}
if(city.longitude > max_long){
max_long = city.longitude;
}
if(city.longitude < min_long){
min_long = city.longitude;
}
}
int lat_diff = max_lat-min_lat;
int long_diff = max_long-min_long;
int[][] arr = new int[lat_diff+1][long_diff+1];
for(City city : cities){
arr[city.latitude - min_lat ][city.longitude - min_long]=city.points;
}
SegmentTreeRMQ tree = new SegmentTreeRMQ();
tree.constructST(arr, lat_diff, long_diff);
int max_till_now = Integer.MIN_VALUE;
int max_till_city = 0;
for(City city : cities){
int x = city.latitude;
int y = city.longitude;
max_till_city = tree.RMQ(lat_diff+1,long_diff+1,x-d_lat,y-d_long,x+d_lat,y+d_long);
if(max_till_now < max_till_city){
max_till_now = max_till_city;
}
}
System.out.println(max_till_now);
in.close();
}
}
What I need to know is that do i require an update query as well? If yes please send me some pointers.
Thanks,
Apoorv Srivastava
Related
I have tried the code to find "whether a point lies inside a triangle or not " ,using area.I think by this way ,I can find the answer to "whether a point lies inside a polygon or not" because any polygon is made up of one or more triangles.But when polygon have more sides ,this method will be complex.I want to know Is there another simplier way to implement this in java.
This is my code to find "whether a point lies inside a triangle or not ".
class PointInTriangle {
static double AreaofTriangle(int x1,int y1,int x2,int y2,int x3,int y3){
return 0.5*(double)Math.abs(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2));
}
static boolean isInTriangle(int x1,int y1,int x2,int y2,int x3,int y3,int px,int py){
double bigArea,area1,area2,area3;
bigArea = AreaofTriangle(x1, y1, x2, y2, x3, y3);
area1 = AreaofTriangle(px, py, x2, y2, x3, y3);
area2 = AreaofTriangle(x1, y1, px, py, x3, y3);
area3 = AreaofTriangle(x1, y1, x2, y2, px, py);
if(bigArea == (area1+area2+area3)) {
return true;
}
return false;
}
public static void main(String[]args){
Scanner in = new Scanner(System.in);
System.out.println("Enter three points of triangle:");// (x1,y1) , (x2,y2) , (x3,y3)
int x1,y1,x2,y2,x3,y3,px,py;
x1 = in.nextInt();
y1 = in.nextInt();
x2 = in.nextInt();
y2 = in.nextInt();
x3 = in.nextInt();
y3 = in.nextInt();
System.out.println("\nEnter searching point:");// (px,py)
px = in.nextInt();
py = in.nextInt();
if(isInTriangle(x1, y1, x2, y2, x3, y3, px, py)){
System.out.println("\nExtra point is in the triangle");
}
else{
System.out.println("\nExtra point is not in the triangle");
}
}
}
Wikipedia has a direct approach to this problem at Even–odd rule. Here's an example of an implementation in Java:
class Point {
int x;
int y;
Point(int x, int y){
this.x = x;
this.y = y;
}
}
public class Testing {
Point[] polygon;
Testing(Point[] polygon) {
this.polygon = polygon;
}
public static void main(final String[] args) {
Point[] polygon = {new Point(5,11), new Point(4,4), new Point(11,2), new Point(2,2)};
Testing test = new Testing(polygon);
Point pOutside = new Point(6,6);
Point pInside = new Point(3,3);
System.out.println(test.isInsideByEvenOddRule(pOutside)); // false
System.out.println(test.isInsideByEvenOddRule(pInside)); // true
}
// java implementation of https://en.wikipedia.org/wiki/Even–odd_rule
boolean isInsideByEvenOddRule(Point point){
boolean result = false;
int j = polygon.length - 1;
for (int i = 0; i < polygon.length; i++) {
if ((polygon[i].y > point.y) != (polygon[j].y > point.y) &&
(point.x < polygon[i].x + (polygon[j].x - polygon[i].x) *
(point.y - polygon[i].y) / (polygon[j].y - polygon[i].y))) {
result = !result;
}
j = i;
}
return result;
}
}
Using this formula, you could implement areaOfPolygon method using an array of Point objects:
class Point {
public double x, y;
public Point(double x, double y){
this.x = x;
this.y = y;
}
public static double areaOfPolygon(Point[] points){
double sum = 0;
for (int i = 0; i < points.length-1; i++){
sum += (points[i].x * points[i+1].y -
points[i].y * points[i+1].x);
}
sum += (points[points.length-1].x * points[0].y -
points[points.length-1].y * points[0].x);
return Math.abs(0.5 * sum);
}
}
Now you can build isInPolygon method using the areaOfPolygon method.
I'm trying to implement mandelbrot however it my main classes it draws a single color because all of the iteration counts are staying at zero. I've looked for the cause of this for a while and couldn't determine what is causing it to do this. I looked for other sources however their approach was completely different. All of the drawing is done in the main class and the magnitude add and multiply methods were created in a third class.
package edu.ycp.cs201.mandelbrot;
public class MandelbrotTask implements Runnable {
private double x1, y1, x2, y2;
private int startCol, endCol, startRow, endRow;
private int[][] iterCounts;
public MandelbrotTask(double x1, double y1, double x2, double y2,
int startCol, int endCol, int startRow, int endRow,
int[][] iterCounts) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.startCol = startCol;
this.endCol = endCol;
this.startRow = startRow;
this.endRow = endRow;
this.iterCounts = iterCounts;
}
public void run() {
for (int i = startRow; i < endRow; i++) {
for (int j = startCol; j < endCol; j++) {
Complex c = getComplex(i, j);
int iterCount = computeIterCount(c);
iterCounts[i][j] = iterCount;
}
}
}
// TODO: implement getComplex and computeIterCount methods
public Complex getComplex(int x, int y) {
//return new Complex (x, y);
double col = (double) endCol - (double) startCol;
double row = (double) endRow - (double) startRow;
double dx = x2 - x1;
double dy = y2 - y1;
return new Complex(x1 + dx / col * x, y1 + dy / row * y);
}
public int computeIterCount(Complex complex) {
//Zo is initially 0+0i
Complex z = new Complex(0,0);
//# of iterations
int count = 0;
//while z has magnitude of less than 2 and iteration counts have not
exceeded MAX
for (int k = 0; k < 100; k++) {
//iterate complex number
z = z.multiply(z).add(complex);
//if magnitude of complex number is >2 stop
if (z.getMagnitude() > 2) {
break;
}
//increment count
count++;
}
return count;
}
}
Down in the second class named paintthis, in the constructor i declare that array = array.clone, and it says that there is nothing in the array? I declare the array in LineGraph and then put the array into the peramiters, which there is a constructor of the second class names painthis with the arguments int[] array.
package javatestframming;
import java.awt.geom.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
public class LineGraph extends JFrame{
public LineGraph(){
super("Line Graph");
int[] array = {1, 2, 3, 4, 5, 7, 8, 9};
setSize(400, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
paintthis gpane = new paintthis(array);
add(gpane);
setVisible(true);
}
public static void main(String[] args){
LineGraph lg = new LineGraph();
}
}
class paintthis extends JPanel{
int[] xpoints;
paintthis(int[] array){
xpoints = array.clone;
}
int max = arrayGetMaxInt(xpoints);
int min = arrayGetMinInt(xpoints);
int divisable = findDivisableWholeNumber(max, min);
Font f = new Font("Arial", Font.BOLD, 14);
FontMetrics fm = getFontMetrics(f);
public void paintComponent(Graphics g){
Graphics2D g2d = (Graphics2D) g;
super.paintComponents(g);
int graphHeight = 200;
int graphWidth = 200;
int graphX = 10;
int graphY = 10;
float borderThickness = 5.0f;
//set graph background and border
g2d.setColor(Color.white);
g2d.fillRect(graphX, graphY, graphWidth, graphHeight);
g2d.setColor(Color.GRAY);
BasicStroke bs = new BasicStroke(borderThickness, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
g2d.setStroke(bs);
g2d.drawLine(graphX - (int)borderThickness, graphY, graphX + graphWidth, graphY);
g2d.drawLine(graphX - (int)borderThickness, graphY + graphHeight, graphX + graphWidth, graphY + graphHeight);
g2d.drawLine(graphX - (int)borderThickness, graphY, graphX - (int)borderThickness, graphY + graphHeight);
g2d.drawLine(graphX + graphWidth, graphY, graphX + graphWidth, graphY + graphHeight);
int trueGraphWidth = graphWidth - drawYAxis(g2d, graphWidth, graphHeight, max, min, divisable, graphY, graphX);
int trueGraphHeight = graphHeight - drawXAxis(g2d, graphY + graphHeight - fm.getHeight(), graphX, graphWidth, (int)borderThickness);
System.out.println(trueGraphWidth + " " + graphWidth);
drawPoints(g2d, trueGraphWidth, trueGraphHeight, (graphWidth - trueGraphWidth) + (int)borderThickness + graphX, (graphHeight - trueGraphHeight) + (int)borderThickness + graphY);
}
public int drawYAxis(Graphics2D g, int graphWidth, int graphHeight, int max, int min, int counts, int beginingpoint, int overx){
graphHeight -= fm.getHeight();
int averageSpaceInBetween = ((graphHeight-fm.getHeight())/((max - min)/counts)); //- ((fm.getHeight()/(graphHeight/fm.getHeight())));
int space = 0;
Stack<Integer> stackAxisNumbers = new Stack<Integer>();
g.setFont(f);
for (int x = 0; x <= (max - min); x+=counts){
stackAxisNumbers.add(x + min);
}
for (int x = 0; x <= (max - min); x+= counts){
g.drawString("$" + Integer.toString(stackAxisNumbers.pop()), overx, space + beginingpoint + fm.getHeight());
space += averageSpaceInBetween;
}
space = 0;
return fm.stringWidth("$" + Integer.toString(max));
}
public int drawXAxis(Graphics2D g, int beginingpoint, int overx, int graphWidth, int borderThickness){
g.drawLine(overx - borderThickness, beginingpoint, overx + graphWidth, beginingpoint);
return beginingpoint - fm.getHeight();
}
public void drawPoints(Graphics2D g, int graphWidth,int graphHeight, int startX, int startY){
g.setColor(Color.blue);
int xSpace = (int) graphWidth/xpoints.length;
g.drawLine(startX, startY, xSpace + startX, xpoints[0]);
}
public int arrayGetMaxInt(int[] array){
int max = 0;
for (int x: array){
if (x > max){
max = x;
}
}
return max;
}
public int arrayGetMinInt(int[] array){
int min = max;
for (int x: array){
if (x < min){
min = x;
}
}
return min;
}
public int power(int base, int exp){
int num = base;
for (int x = 1; x < exp; x++){
num = num * base;
}
if (exp == 0){
num = 1;
}
return num;
}
public int findDivisableWholeNumber(int max, int min){
boolean passed = false;
int range = max - min;
int divis = 1;
int multiplier = 1;
out:
for (int x = 5; x > 0; x--){
if (range >= power(10, x)){
multiplier = x;
break;
}
}
out:
for (int x = 10 * multiplier; x <= 10 * multiplier && x > 0; x--){
if(range%((int)(range/x)) == 0){
divis = x;
passed = true;
break;
}
}
if (passed == false){
out:
for (int x = 11 * multiplier; x <= (int)(range / 2); x++){
if(range%((int)(range/x)) == 0){
divis = x;
passed = true;
break;
}
}
}
if (passed == false){
System.out.println("ERROR -- NoWholeDiviableNumbersException");
System.exit(0);
}
return divis;
}
}
Exception is:
Exception in thread "main" java.lang.NullPointerException
at javatestframming.paintthis.arrayGetMaxInt(LineGraph.java:97)
at javatestframming.paintthis.<init>(LineGraph.java:31)
at javatestframming.LineGraph.<init>(LineGraph.java:15)
at javatestframming.LineGraph.main(LineGraph.java:22)
C:\Users\Morgan Higginbotham\AppData\Local\NetBeans\Cache\8.1\executor- snippets\run.xml:53: Java returned: 1
BUILD FAILED (total time: 1 second)
When you create an object using paintthis gpane = new paintthis(array); It will initialize class level variables first
int max = arrayGetMaxInt(xpoints);
then body of constructor is called. In this case xpoints is still not initialized, so you are getting NullPointerException
You can try some thing like this
class paintthis extends JPanel{
int[] xpoints;
int max;
int min;
int divisable;
public paintthis(int[] array){
xpoints = array.clone();
max = arrayGetMaxInt(xpoints);
min = arrayGetMinInt(xpoints);
divisable = findDivisableWholeNumber(max, min);
}
I have a convex quadrilateral. I know the four points, and I have its four lines in the format mx + b (from the top going clockwise). Quadrilateral is a class shown below:
import java.awt.Point;
import java.awt.Polygon;
public final class Quadrilateral extends Polygon {
private static final long serialVersionUID = 794866732073166739L;
public final Point p1, p2, p3, p4;
public final Line l12, l23, l34, l41;
public Quadrilateral(Point p1, Point p2, Point p3, Point p4) {
super(new int[] { p1.x, p2.x, p3.x, p4.x }, new int[] { p1.y, p2.y,
p3.y, p4.y }, 4);
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.p4 = p4;
this.l12 = Quadrilateral.getLine(p1, p2);
this.l23 = Quadrilateral.getLine(p2, p3);
this.l34 = Quadrilateral.getLine(p3, p4);
this.l41 = Quadrilateral.getLine(p4, p1);
}
public static final Line getLine(Point p1, Point p2) {
if (p1.x > p2.x) {
return Quadrilateral.getLine(p2, p1);
} else {
int x1 = p1.x;
int x2 = p2.x;
int y1 = p1.y;
int y2 = p2.y;
int xdiff = x2 - x1;
int ydiff = y1 - y2;
double m = (double) ydiff / (double) xdiff;
double b = y1 - m * x1;
return new Line(m, b);
}
}
public Quadrilateral[][] grid(int x, int y) {...?...}
}
What I want to do is to divide an instance of Quadrilateral into an x by y grid of Quadrilaterals, sorted in a Quadrilateral[][]. How would I do this efficiently?
You have to interpolate to create the points in between. Do this for each component like so:
p1.x * (1-t) + p2.x * t
Where t goes from 0 to 1.
Create a grid of x+1 by y+1 points this way. Interpolate between two pairs of points of the outline that are neighbours (not connected via diagonals). Then interpolate again between the two points you receive as a result. Set t on each interpolation according to the values of x and y and what iteration step you are currently calculating.
From this grid of points you can build the grid of quadriliterals by iterating over the the points in steps of size 2.
I've finally found out the answer! It's quite lengthy. I've included the whole Quadrilateral.java file below:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
public final class Quadrilateral extends Polygon {
private static final long serialVersionUID = 794866732073166739L;
public final Point p1, p2, p3, p4;
public final Line l12, l23, l34, l41;
public Quadrilateral(Point p1, Point p2, Point p3, Point p4) {
super(new int[] { p1.x, p2.x, p3.x, p4.x }, new int[] { p1.y, p2.y,
p3.y, p4.y }, 4);
this.p1 = p1;
this.p2 = p2;
this.p3 = p3;
this.p4 = p4;
this.l12 = Quadrilateral.getLine(p1, p2);
this.l23 = Quadrilateral.getLine(p2, p3);
this.l34 = Quadrilateral.getLine(p3, p4);
this.l41 = Quadrilateral.getLine(p4, p1);
}
public static Quadrilateral formatted(Quadrilateral quadrilateral, int w,
int h) {
return new Quadrilateral(Format.format(quadrilateral.p1, w, h),
Format.format(quadrilateral.p2, w, h), Format.format(
quadrilateral.p3, w, h), Format.format(
quadrilateral.p4, w, h));
}
public Quadrilateral[][] grid(int x, int y) {
Point[][] points = new Point[x + 1][y + 1];
for (int ix = 0; ix <= x; ix++) {
for (int iy = 0; iy <= y; iy++) {
points[ix][iy] = this.getPointAt(x, y, ix, iy);
}
}
Quadrilateral[][] qs = new Quadrilateral[x][y];
for (int ix = 0; ix < x; ix++) {
for (int iy = 0; iy < y; iy++) {
qs[ix][iy] = new Quadrilateral(points[ix][iy],
points[ix + 1][iy], points[ix + 1][iy + 1],
points[ix][iy + 1]);
}
}
return qs;
}
public ArrayList<ArrayList<Quadrilateral>> gridList(int x, int y) {
Point[][] points = new Point[x + 1][y + 1];
for (int ix = 0; ix <= x; ix++) {
for (int iy = 0; iy <= y; iy++) {
points[ix][iy] = this.getPointAt(x, y, ix, iy);
}
}
ArrayList<ArrayList<Quadrilateral>> qs = new ArrayList<>(0);
for (int ix = 0; ix < x; ix++) {
qs.add(new ArrayList<>(y));
for (int iy = 0; iy < y; iy++) {
qs.get(ix).add(
new Quadrilateral(points[ix][iy], points[ix + 1][iy],
points[ix + 1][iy + 1], points[ix][iy + 1]));
}
}
return qs;
}
public Point getPointAt(int xdiv, int ydiv, int xiter, int yiter) {
Point n1 = this.getTopPointAt(xdiv, xiter);
Point n2 = this.getRightPointAt(ydiv, yiter);
Point n3 = this.getBottomPointAt(xdiv, xiter);
Point n4 = this.getLeftPointAt(ydiv, yiter);
Line h = Quadrilateral.getLine(n4, n2);
Line v = Quadrilateral.getLine(n1, n3);
return h.intersect(v, n2.x, n1.x);
}
public Point getTopPointAt(int div, int iter) {
Point start = this.p1;
Point end = this.p2;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public Point getBottomPointAt(int div, int iter) {
Point start = this.p4;
Point end = this.p3;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public Point getLeftPointAt(int div, int iter) {
Point start = this.p4;
Point end = this.p1;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public Point getRightPointAt(int div, int iter) {
Point start = this.p3;
Point end = this.p2;
int xdiff = end.x - start.x;
int ydiff = end.y - start.y;
int xadd = (int) ((double) xdiff / (double) div) * iter;
int yadd = (int) ((double) ydiff / (double) div) * iter;
int x = start.x + xadd;
int y = start.y + yadd;
return new Point(x, y);
}
public static final Line getLine(Point p1, Point p2) {
if (p1.x < p2.x) {
return Quadrilateral.getLine(p2, p1);
} else {
int x1 = p1.x;
int x2 = p2.x;
int y1 = p1.y;
int y2 = p2.y;
int xdiff = x2 - x1;
int ydiff = y2 - y1;
double m = (double) ydiff / (double) xdiff;
double b = y1 - m * x1;
return new Line(m, b);
}
}
public void paint(Graphics g, BufferedImage image) {
int w = image.getWidth();
int h = image.getHeight();
Quadrilateral[][] grid = this.grid(w, h);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
g.setColor(new Color(image.getRGB(x, y), true));
g.fillPolygon(grid[x][y]);
}
}
}
}
I have a list of point objects that need to be sorted by both X and Y coordinates, but when I pass them to a comparator object only one coordinate gets sorted (the first one called). Any ideas to why this might be happening?
static public List<Point> convertToThreeByThreeGrid(String points) {
String[] ptsArray;
List<Point> ptsList = new ArrayList<>();
String stripString = points.replace("[", "").replace("]", "").replace("(", "").replace(")", "").replace(" ", ",").trim();
ptsArray = stripString.split(",");
for(int i = 0; i < ptsArray.length; i += 2) {
int x = Integer.parseInt(ptsArray[i]);
int y = Integer.parseInt(ptsArray[i + 1]);
System.out.println("X: " + x);
System.out.println("Y: " + y);
ptsList.add(new Point(x, y));
}
Collections.sort(ptsList, new Comparator<Point>() {
public int compare(Point a, Point b) {
int result = Integer.compare((int) a.getX(), (int) b.getX());
if (result == 0 ) {
result = Integer.compare((int) a.getY(), (int) b.getY());
}
return result;
}
});
// subtract each coordinate by smallest x and y coordinate values
List<Point> convertedPtList = new ArrayList<>();
int smallestX = (int) ptsList.get(0).getX();
int smallestY = (int) ptsList.get(0).getY();
for (int i = 1; i < ptsList.size(); i++) {
int x = ((int) ptsList.get(i).getX() - smallestX);
int y = ((int) ptsList.get(i).getY() - smallestY);
convertedPtList.add(new Point(x, y));
}
return convertedPtList;
}
}
Output:
[java.awt.Point[x=10,y=26], java.awt.Point[x=10,y=26], java.awt.Point[x=10,y=28], java.awt.Point[x=12,y=26]]
[java.awt.Point[x=13,y=26], java.awt.Point[x=13,y=28], java.awt.Point[x=13,y=28], java.awt.Point[x=14,y=27], java.awt.Point[x=14,y=27], java.awt.Point[x=15,y=26], java.awt.Point[x=15,y=28], java.awt.Point[x=15,y=28]]
[java.awt.Point[x=16,y=26], java.awt.Point[x=16,y=28], java.awt.Point[x=16,y=28], java.awt.Point[x=18,y=26], java.awt.Point[x=18,y=26], java.awt.Point[x=18,y=28]]
for(int i = 0; i < ptsArray.length; i += 2) {
int x = Integer.parseInt(ptsArray[i]);
int y = Integer.parseInt(ptsArray[i+1]);
ptsList.add(new Point(x, y));
}
Collections.sort( ptsList, new Comparator<Point>() {
public int compare(Point x1, Point x2) {
int result = Double.compare(x1.getX(), x2.getX());
if ( result == 0 ) {
// both X are equal -> compare Y too
result = Double.compare(x1.getY(), x2.getY());
}
return result;
}
});
// ptsList is now sorted by both X and Y!
Edit:
To just find the lowest X and the lowest Y you can also go the 'classic' way without any (double-)sorting:
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
for ( Point p : ptsList ) {
final int x = (int)p.getX();
final int y = (int)p.getY();
if ( x < minX ) {
minX = x;
}
if ( y < minY ) {
minY = y;
}
}