3
\$\begingroup\$

First number indicates the number of points, followed by N points (x,y). Then the next number indicates Q num_queries, followed by Q queries:

  1. Reflect all points between point i and j both including along the X axis. This query is represented as "X i j"
  2. Reflect all points between point i and j both including along the Y axis. This query is represented as "Y i j"
  3. Count how many points between point i and j both including lie in each of the 4 quadrants. This query is represented as "C i j"

Sample Input

4         
1 1         
-1 1         
-1 -1
1 -1
5
C 1 4
X 2 4
C 3 4
Y 1 2
C 1 3

Sample Output

1 1 1 1
1 1 0 0
0 2 0 1

How can i improve this code for better metrics?

import java.util.ArrayList;
import java.util.Scanner;

/**
 *
 * @author cypronmaya
 */
class Point {

    int x;
    int y;

    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

public class Quad_query {

    private ArrayList<Point> arrayList;

    public Quad_query(int capacity) {
        this.arrayList = new ArrayList<Point>(capacity);
    }

    public static void main(String args[]) {

        Scanner scanner = new Scanner(System.in);
        int num_of_points = scanner.nextInt();
        Quad_query quad_query = new Quad_query(num_of_points);
        for (int i = num_of_points; --i >= 0;) {
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            quad_query.add(x, y);
        }
        int num_of_queries = scanner.nextInt();
        for (int i = num_of_queries; --i >= 0;) {
            char c = scanner.next().charAt(0);
            quad_query.query(c, scanner.nextInt() - 1, scanner.nextInt() - 1);
        }
    }

    public void add(int x, int y) {
        Point point = new Point(x, y);
        arrayList.add(point);
    }

    public void query(char c, int i, int j) {

        switch (c) {
            case 'C':
                queryC(i, j);
                break;
            default:
                queryXY(c, i, j);
                break;
        }
    }

    public void queryC(int i, int j) {

        int quad_1 = 0, quad_2 = 0, quad_3 = 0, quad_4 = 0;
        for (int k = i; k <= j; k++) {
            Point pnt = arrayList.get(k);
            int pnt_x = pnt.x;
            int pnt_y = pnt.y;
            if (pnt_x > 0 && pnt_y > 0) {
                quad_1++;
            } else if (pnt_x < 0 && pnt_y > 0) {
                quad_2++;
            } else if (pnt_x < 0 && pnt_y < 0) {
                quad_3++;
            } else if (pnt_x > 0 && pnt_y < 0) {
                quad_4++;
            }
        }
        System.out.println(quad_1 + " " + quad_2 + " " + quad_3 + " " + quad_4);
    }

    private void queryXY(char c, int i, int j) {

        for (int k = i; k <= j; k++) {
            Point pnt = arrayList.get(k);
            int pnt_x = pnt.x;
            int pnt_y = pnt.y;
            if (c == 'X') {
                pnt = new Point(pnt_x, -pnt_y);
            } else if (c == 'Y') {
                pnt = new Point(-pnt_x, pnt_y);
            }
            arrayList.set(k, pnt);
        }
    }
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Can you add the expected output for the input you gave ? As a first quick and useless comment, I would say that variable "num_of_points" is not really useful. \$\endgroup\$
    – SylvainD
    Commented Jan 2, 2012 at 22:33

2 Answers 2

3
\$\begingroup\$

Instead of initializing your arrayList when you create the instance of the class, do it when you have the num_of_points value from the scanner.

arrayList = new ArrayList<Point>(num_of_points);

This will mean the array list doesn't need to resize itself (potentially slow operation). In the example you have given with only 4 points it won't make any difference, but if there were a larger number of points you may save some time!

Where you get the value from the scanner char c you trim the value, which you shouldn't need to do as the Scanner should stop when it sees a delimiter (in this case, a space).

In the queryC method, you have a for loop...

for (int b = 0; b < len; b++) {
    pnt = arrayList.get(b);
}

...that does nothing, so you can remove it.

A few notes on code style...

  • In the main method your for loops go from X down to 0, but in the query methods you go from 0 up to X. Just wondering why?
  • You also use (0 - pnt.x) where you could use -pnt.x.

Hope this helps.

\$\endgroup\$
12
  • \$\begingroup\$ sorry,i forgot to remove that useless loop before only,regarding (o-pnt.x) -- written simply, loops go down in main method from X->0 because i wouldn't use the loop variable in it,the way i've written loops in main method, would optimized one's \$\endgroup\$
    – cypronmaya
    Commented Jan 3, 2012 at 3:59
  • \$\begingroup\$ those trim, that i've done just for safety purposes,i know scanner would take exactly what to take, but simply, please look at modified version \$\endgroup\$
    – cypronmaya
    Commented Jan 3, 2012 at 4:00
  • \$\begingroup\$ @cypronmaya The only other thing I can see is that you have used variables int pnt_x = pnt.x I wouldn't bother with this variable as the compiler should inline it anyway. It is coded in a pretty readable manner which as @MikeNakis said, is the main thing to worry about. \$\endgroup\$ Commented Jan 3, 2012 at 14:49
  • \$\begingroup\$ Also you say that you write the for loops in the main method that way because you're not using the loop variable inside the loop - why not turn it into a much more readable while loop? \$\endgroup\$ Commented Jan 3, 2012 at 14:51
  • \$\begingroup\$ Ya, u've given lot of usefull inpur, but still i'm not able to achieve the req thing, execution time failed \$\endgroup\$
    – cypronmaya
    Commented Jan 3, 2012 at 14:53
2
\$\begingroup\$

for (int i = num_of_queries; --i >=0;) is cute, but it makes one pause for a moment and think whether it is correct or not before moving on. It is better rewritten as for (int i = num_of_queries; i > 0; i--).

Your arraylist is allocated once and never changed, (its contents are ganged, but not the object itself,) so it should be declared as final. Right before you start using it, since you know how many items are going to go into it, do arrayList.ensureCapacity(num_of_points); so as to help it to avoid resizing itself as it is discovering its capacity by itself.

Use better names; quad_qu should be quad_queue or perhaps just queue.

In QueryC:

Get rid of the pnt_x and pnt_y variables and simply use pnt.x and pnt.y instead.

Declare pnt inside the loop, not outside it: Point pnt = arrayList.get(k);

Rename pnt to point, or pt, or just p.

In QueryXY:

Again, declare pnt inside the loop, not outside it.

Declare new_pnt inside the loop, too, and do not initialize it to null. It is bad practice to initialize things when there is no need. It prevents the compiler from giving you useful warnings. When you do this, the compiler will give you a warning that you may be trying to use new_pnt before you have assigned a value to it. That's because your if statement checks for 'X', and then for 'Y', but there is no else clause to handle any other possibility. So, add an else clause and throw an exception: throw new Exception("wtf?")

Get rid of these: int pnt_x = 0, pnt_y = 0; they are not used. Actually, the fact that you have these in your code, and you have not seen a compiler warning about them not being used, tells me that you are not compiling with all warnings enabled. Do yourself a favor and enable all warnings so as to have the compiler help you. That's his job.

Replace this:

arrayList.remove(k);
arrayList.add(k, new_pnt);

With simply this: arrayList.set(k, new_pnt);

\$\endgroup\$
11
  • \$\begingroup\$ Speaking of -> for (int i = num_of_queries; --i >=0;) is lot better, it removes useless checks and optimized. -> ensureCapacity it's better only if i'm having lots of records, atleast more than 10(initial capacity).As i'm having very few records, i don't it doesn't really matter ....:P \$\endgroup\$
    – cypronmaya
    Commented Jan 3, 2012 at 9:20
  • \$\begingroup\$ Regarding names,un-necessary variables,declarations thanks. BTW i've initialized it to null as compiler thrown me a warning. About replacing this "arrayList.remove(k); arrayList.add(k, new_pnt);" ----> Here first i'm removing the element at pos-k and then inserting newly modified element at the same position. As u suggested arrayList.set(k, new_pnt); , what it does is , it doesn't replace the existing element, it only checks if an element exists, if so their index will be increased and new_element is inserted at tht position. \$\endgroup\$
    – cypronmaya
    Commented Jan 3, 2012 at 9:26
  • 1
    \$\begingroup\$ arrayList.set( k, new_pnt ) will do exactly what I intended it to do; don't theorize about it when you can just look it up: docs.oracle.com/javase/6/docs/api/java/util/…, E) \$\endgroup\$
    – Mike Nakis
    Commented Jan 3, 2012 at 9:46
  • 1
    \$\begingroup\$ In any case, my advise to you would be to stop worrying about performance so much. The rule in the industry is to code things in the simplest, most readable and most maintainable way possible, then establish performance requirements, then measure the software against these requirements, and if and only if the software fails to meet these requirements, go optimize that 1% of the code which will make the software meet the requirements. And usually, these optimizations turn out to be algorithmic, not hacky. \$\endgroup\$
    – Mike Nakis
    Commented Jan 3, 2012 at 9:55
  • 1
    \$\begingroup\$ As to the approach you followed, no, I have nothing to say about that, it seems just fine to me. \$\endgroup\$
    – Mike Nakis
    Commented Jan 3, 2012 at 9:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.