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.util.*;
import java.io.*;

public class cf120j {
	static int n;
	public static void main(String[] args) throws Exception {
		FastScanner in = new FastScanner(new File("input.txt"));
		PrintWriter out = new PrintWriter("output.txt");
		n = 2;
		int N = in.nextInt();
		ArrayList<veca> vs = new ArrayList<veca>();
		ArrayList<veca> ts = new ArrayList<veca>();
		ArrayList<veca> rs = new ArrayList<veca>();
		
		for(int i=0; i<N; i++) {
			int x = in.nextInt();
			int y = in.nextInt();
			vs.add(new veca(new int[]{Math.abs(x),Math.abs(y)},i));
			ts.add(new veca(new int[]{Math.abs(x),Math.abs(y)},i));
			rs.add(new veca(new int[]{x,y},i));
		}
		KDTree kd = new KDTree(vs);
		int best = Integer.MAX_VALUE;
		veca a = null;
		veca b = null;
		for(veca v : ts) {
			veca tmp = kd.findBest(v);
			int rr = tmp.dist2(v);
			if(rr < best) {
				a = v;
				b = tmp;
				best = rr;
			}
		}
		int k1 = getKValue(ts.get(a.id), rs.get(a.id));
		int k2 = getKValue(ts.get(b.id).invert(), rs.get(b.id));

		out.printf("%d %d %d %d%n", a.id+1,k1,b.id+1,k2);
	//	System.out.printf("%d %d %d %d%n", a.id+1,k1,b.id+1,k2);
		out.close();
	}
	static int getKValue(veca a, veca b)
	{
		if ((a.v[0] == b.v[0])&&(a.v[1] == b.v[1]))
			return 1;
		if ((a.v[0] != b.v[0])&&(a.v[1] == b.v[1]))
			return 2;
		if ((a.v[0] == b.v[0])&&(a.v[1] != b.v[1]))
			return 3;
		return 4;
	}
	static class KDTree {
		Node root;
		static veca target;
		KDTree(ArrayList<veca> pts) {
			Collections.shuffle(pts);
			root = build(pts.toArray(new veca[0]),0,pts.size()-1,0);
		}
		Node build(veca[] pts, int left, int right, int depth) {
			if(left>right) return null;
			if(left==right) return new Node(pts[left],null,null);
			int lo = left+1, hi = right;
			while(lo < hi) {
				while(lo < hi && pts[lo].compareTo(pts[left],depth) < 0) lo++;
				while(lo < hi && pts[hi].compareTo(pts[left], depth) > 0) hi--;
				if(lo <= hi) {
					veca tmp = pts[lo];
					pts[lo] = pts[hi];
					pts[hi] = tmp;
					lo++;hi--;
				}
			}
			return new Node(pts[left], build(pts,left+1,hi,depth+1), build(pts,hi+1,right,depth+1));
		}
		veca findBest(veca v) {
			target = v;
			return find(root,0);
		}
		veca find(Node cur, int depth) {
			veca best = null;
			if(cur==null) return null;
			if(target.id != cur.loc.id) best = cur.loc; 
	//		if(cur.left == null && cur.right == null) return best;
			if(cur.right == null) return min(best,find(cur.left, depth+1),target);
			if(cur.left == null) return min(best,find(cur.right, depth+1),target);
			if(target.compareTo(cur.loc, depth) < 0) {
				best = min(best,find(cur.left, depth+1),target);			
				if(best == null || target.axisDist2(cur.loc, depth) < best.dist2(target)) 
					best = min(best,find(cur.right, depth+1),target);
			}
			else {
				best = min(best,find(cur.right, depth+1),target);
				if(best == null || target.axisDist2(cur.loc, depth) < best.dist2(target)) 
					best = min(best,find(cur.left, depth+1),target);
			}
			return best;
		}
		veca min(veca a, veca b, veca tar) {
			if(a==null) return b;
			if(b==null) return a;
			return a.dist2(tar) < b.dist2(tar) ? a : b;
		}
		static class Node {
			veca loc;
			Node left,right;
			Node(veca v, Node l, Node r) {
				loc = v; left=l; right=r;
			}
		}
	}
	static class veca {
		int[] v;
		int id;
		veca(int[] vv, int ii) {
			v = vv;
			id=ii;
		}
		int dist2(veca rhs) {
			int ret = 0;
			for(int i=0; i<n; i++) 
				ret += (rhs.v[i]-v[i])*(rhs.v[i]-v[i]);
			return ret;
		}
		int axisDist2(veca rhs, int depth) {
			int ret = rhs.v[depth%n] - v[depth%n];
			return ret*ret;
		}
		veca invert() {
			return new veca(new int[]{-v[0],-v[1]},id);
		}
		int compareTo(veca rhs, int dim) {
			for(int i=0; i<n; i++) 
				if(v[(i+dim)%n] != rhs.v[(i+dim)%n])
					return v[(i+dim)%n] - rhs.v[(i+dim)%n];
			return 0;
		}
	}
	static class FastScanner {
		FileInputStream in;
		FastScanner(File ff) throws Exception
		{
			in = new FileInputStream(ff);
		}
		int nextInt(){
			try{
				int c=in.read();
				if(c==-1) return c;
				while(c!='-'&&(c<'0'||'9'<c)){
					c=in.read();
					if(c==-1) return c;
				}
				if(c=='-') return -nextInt();
				int res=0;
				do{
					res*=10;
					res+=c-'0';
					c=in.read();
				}while('0'<=c&&c<='9');
				return res;
			}catch(Exception e){
				return -1;
			}
		}
	}
}