Problem: You are given a set of n vectors on a plane. For each vector you are allowed to multiply any of its coordinates by -1. Thus, each vector vi = (xi, yi) can be transformed into one of the following four vectors:

  * vi1 = (xi, yi), 
  * vi2 = ( - xi, yi), 
  * vi3 = (xi, - yi), 
  * vi4 = ( - xi, - yi). 



You should find two vectors from the set and determine which of their coordinates should be multiplied by -1 so that the absolute value of the sum of the resulting vectors was minimally possible. More formally, you should choose two vectors vi, vj (1 ≤ i, j ≤ n, i ≠ j) and two numbers k1, k2 (1 ≤ k1, k2 ≤ 4), so that the value of the expression |vik1 + vjk2| were minimum.

Input

The first line contains a single integer n (2 ≤ n ≤ 105). Then n lines contain vectors as pairs of integers "xi yi" ( - 10000 ≤ xi, yi ≤ 10000), one pair per line.

Output

Print on the first line four space-separated numbers "i k1 j k2" — the answer to the problem. If there are several variants the absolute value of whose sums is minimum, you can print any of them. 

Examples

Input

5
-7 -3
9 0
-8 6
7 -8
4 -5


Output

3 2 4 2


Input

5
3 2
-4 7
-6 0
-8 4
5 1


Output

3 4 5 4

Note

A sum of two vectors v = (xv, yv) and u = (xu, yu) is vector s = v + u = (xv + xu, yv + yu).

An absolute value of vector v = (x, y) is number <image>. 

In the second sample there are several valid answers, such as:

(3 1 4 2), (3 1 4 4), (3 4 4 1), (3 4 4 3), (4 1 3 2), (4 1 3 4), (4 2 3 1).

Solution (in JAVA):

Solution:
import java.io.*;
import java.util.*;
public class J
{
    static
    PrintWriter writer;
    public static void main(String [] args) throws IOException
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("input.txt"))));
        writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(new File("output.txt"))));
        int n = Integer.parseInt(reader.readLine());
        Point [] points = new Point[n];
        StringTokenizer st;
        for(int i = 0; i < n; i++)
        {
            st = new StringTokenizer(reader.readLine());
            int x = Integer.parseInt(st.nextToken()), y = Integer.parseInt(st.nextToken());
            points[i] = new Point(Math.abs(x), Math.abs(y), i + 1, condition(x, y));
        }
        closestPair(points);
        writer.flush();
        writer.close();
    }

    private static int condition(int x, int y)
    {
        if (x > 0 && y > 0)
            return 1;
        if (x < 0 && y > 0)
            return 2;
        if (x > 0 && y < 0)
            return 3;
        return 4;
    }

    public static void closestPair(Point[] points) {
        Point[] closestPair = new Point[3];
//When we start the min distance is the infinity
        int crtMinDist = Integer.MAX_VALUE / 10;
//Get the points and sort them
        Point[] sorted = Arrays.copyOf(points, points.length);
        Arrays.sort(sorted, new Comparator<Point>()
        {
            @Override
            public int compare(Point a, Point b)
            {
                if (a.x < b.x) {
                    return -1;
                }
                if (a.x > b.x) {
                    return 1;
                }
                if (a.y < b.y) {
                    return -1;
                }
                if (a.y > b.y) {
                    return 1;
                }
                return 0;
            }
        });
//When we start the left most candidate is the first one
        int leftMostCandidateIndex = 0;
//Vertically sorted set of candidates
        SortedSet<Point> candidates = new TreeSet<Point>(new Comparator<Point>()
        {
            @Override
            public int compare(Point a, Point b)
            {
                if (a.y < b.y) {
                    return -1;
                }
                if (a.y > b.y) {
                    return 1;
                }
                if (a.x < b.x) {
                    return -1;
                }
                if (a.x > b.x) {
                    return 1;
                }
                return 0;
            }
        });
//For each point from left to right
        for (Point current : sorted) {
//Shrink the candidates
            while ( leftMostCandidateIndex < sorted.length && current.x - sorted
                    [leftMostCandidateIndex].x > crtMinDist) {
                candidates.remove(sorted[leftMostCandidateIndex]);
                leftMostCandidateIndex++;
            }
//Compute the y head and the y tail of the candidates set
            Point head = new Point(current.x, (current.y - crtMinDist), -1, -1);
            Point tail = new Point(current.x, (current.y + crtMinDist), -1, -1);
//We take only the interesting candidates in the y axis
            for (Point point : candidates.subSet(head, tail)) {
                int distance = dis(current, point);
//Simple min computation
                if (distance < crtMinDist) {
                    crtMinDist = distance;
                    closestPair[0] = current;
                    closestPair[1] = point;
                }
            }
//The current point is now a candidate
            candidates.add(current);
        }
        writer.println(closestPair[0].ind + " " + closestPair[0].con + " " + closestPair[1].ind + " " + apposite(closestPair[1].con));
    }

    private static int apposite(int con)
    {
        return 5 - con;
    }

    private static int dis(Point p1, Point p2)
    {
        return (p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y);
    }

    static class Point
    {
        int x, y, ind, con;
        public Point(int x, int y, int ind, int con)
        {
            this.x = x;
            this.y = y;
            this.ind = ind;
            this.con = con;
        }
    }
}