#include <bits/stdc++.h>

using namespace std;
const int nmax = 4e5 + 1;

int n;


int id[nmax] , f[nmax], lv[nmax],visited[nmax];

void Union(int x , int y)
{
    if( lv[x] > lv[y] )
        f[y] = x;
    else {
        f[x] = y;
        if(lv[x] == lv[y])
            lv[y]++;
    }
}


int Find(int x)
{
    while(f[x] != 0)
        x = f[x];
    return x;
}

vector<int> V[nmax];

struct trip{
    int u,v,w;

public :
    trip(int uu,int vv,int ww) : u(uu),v(vv),w(ww){}
};

vector<trip> solution;

int dfs(int nod,int fat)
{   visited[nod] = 1;
    int gc,sz;
    vector<int> lpp;
    lpp.clear();
    for(auto child: V[nod])
        if(child != fat)
            {

                gc = dfs(child,nod);

                 if(gc == 0)
                    lpp.push_back(child);

            }
    sz = lpp.size();

    for(int i = 0 ; i < sz -1 ; i+=2 ){
        solution.push_back( trip(lpp[i],nod,lpp[i+1]) );
    }
    //cout << nod << "\n";
    if(sz % 2 == 1 && fat != 0 )
        {  solution.push_back( trip( lpp[sz -1] ,nod,fat ) );
          return -1;}
    else return 0;

}


long long gcd(long long x , long long y)
{
    long long r;

    while(y)
    {
        r = x%y;
        x = y;
        y = r;
    }
    return x;
}
map<string,int> lini;
map<pair<int,int>,int> points;

string gtline(long long u , long long v , long long q , long long h)
{
    string result = "";
long long difnu,difde,gg;

difde = 1LL* v * h;
        if( 1LL *u * h > 1LL*v*q)
        {
            difnu = 1LL* u*h - 1LL* v*q;
            result.append(1,'+');
        }
        else {  result.append(1,'-');
                difnu = 1ll * v* q - 1ll*u*h ;}

        gg = gcd(difnu,difde);
        difnu /= gg;
        difde /= gg;
        gg = gcd(v,u);
        v /= gg;
        u /= gg;
        difnu *= v;
        difde *= u;

        gg = gcd(difnu,difde);
        difnu /= gg;
        difde /= gg;

        if(difnu == 0)
            difde = 0;

        result.append(  to_string(difnu) );
        result.append(1,',');
        result.append( to_string(difde) );


    return result;
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0);

    cin >> n ;

    int i,u,v,q,h,a1,a2,last = 0,j,w,nodes;

    for(i=1;i<=n;++i)
    {
        cin >> u >> v >> q >> h;

        auto linie = gtline(u+v,v,q,h);
        auto linie2 = gtline(u,v,q+h,h);

        if( lini.find(linie) == lini.end())
            lini[linie] = ++last;

        if(lini.find(linie2) == lini.end())
            lini[linie2] = ++last;

        u =lini[linie];
        v = lini[linie2];

        //cout << u << " " << v << "\n";

        a1 = Find(u);
        a2 = Find(v);

        if(  lv[a1] == 0)
        {
            id[u] = u;
        }
        if(lv[a2] == 0)
        {
            id[v] = v;
        }

        if( a1 == a2)
        {
            for(j=last;;++j)
                if(id[j] == 0 )
            {
                w = j;
                last = j + 1;
                break;
            }
            id[w] = v;
            Union(a1,w);
            V[u].push_back(w);
            V[w].push_back(u);
            points[make_pair(u,w)] = i;
            points[make_pair(w,u)] = i;
        }
        else {

            Union(a1,a2);
            V[u].push_back(v);
            V[v].push_back(u);
            points[ make_pair(u,v) ] = i;
            points[ make_pair(v,u) ] = i;
        }

    }

    nodes = last;

    //cout << nodes << "\n";


    for(i=1;i<=nodes;++i)
        if(visited[i] == 0)
            dfs(i,0);

   cout << solution.size() << "\n";
    int sz = solution.size();
   for(i=0; i< sz ;++i)
    cout << points[ make_pair(solution[i].u , solution[i].v) ] << " "<< points[make_pair(solution[i].v,solution[i].w)]  << "\n";


    return 0;
}
