//by tzupengwang™
#pragma GCC optimize ("O3")
#include<algorithm>
#include<map>
#include<cstdio>
#include<vector>
using namespace std;

typedef unsigned long long ll;
typedef long double ld;
typedef pair<int,int> ii;

int n ;
int s[ 405 ][ 5 ] ;

ll toint( int a , int b , int c , int d ) {
  ll ret = 1000000000000000LLU ;
  ret = min( ret , a * 1000000000LLU + b * 1000000LLU + c * 1000LLU + d ) ;
  ret = min( ret , b * 1000000000LLU + c * 1000000LLU + d * 1000LLU + a ) ;
  ret = min( ret , c * 1000000000LLU + d * 1000000LLU + a * 1000LLU + b ) ;
  ret = min( ret , d * 1000000000LLU + a * 1000000LLU + b * 1000LLU + c ) ;
  return ret ;
}

ll ctint( int a , int b , int c , int d ) {
  ll ret = 1000000000000000LLU ;
  ret = min( ret , a * 1000000000LLU + b * 1000000LLU + c * 1000LLU + d ) ;
  ret = min( ret , b * 1000000000LLU + c * 1000000LLU + d * 1000LLU + a ) ;
  ret = min( ret , c * 1000000000LLU + d * 1000000LLU + a * 1000LLU + b ) ;
  ret = min( ret , d * 1000000000LLU + a * 1000000LLU + b * 1000LLU + c ) ;
  ll rt2 = 0 ;
  rt2 += ( ret == a * 1000000000LLU + b * 1000000LLU + c * 1000LLU + d ) ;
  rt2 += ( ret == b * 1000000000LLU + c * 1000000LLU + d * 1000LLU + a ) ;
  rt2 += ( ret == c * 1000000000LLU + d * 1000000LLU + a * 1000LLU + b ) ;
  rt2 += ( ret == d * 1000000000LLU + a * 1000000LLU + b * 1000LLU + c ) ;
  return rt2 ;
}

ll ctint( ll x ) {
  ll a = x / 1000000000LLU ;
  ll b = x / 1000000LLU % 1000LLU ;
  ll c = x / 1000LLU % 1000LLU ;
  ll d = x % 1000LLU ;
  ll ret = 1000000000000000LLU ;
  ret = min( ret , a * 1000000000LLU + b * 1000000LLU + c * 1000LLU + d ) ;
  ret = min( ret , b * 1000000000LLU + c * 1000000LLU + d * 1000LLU + a ) ;
  ret = min( ret , c * 1000000000LLU + d * 1000000LLU + a * 1000LLU + b ) ;
  ret = min( ret , d * 1000000000LLU + a * 1000000LLU + b * 1000LLU + c ) ;
  ll rt2 = 0 ;
  rt2 += ( ret == a * 1000000000LLU + b * 1000000LLU + c * 1000LLU + d ) ;
  rt2 += ( ret == b * 1000000000LLU + c * 1000000LLU + d * 1000LLU + a ) ;
  rt2 += ( ret == c * 1000000000LLU + d * 1000000LLU + a * 1000LLU + b ) ;
  rt2 += ( ret == d * 1000000000LLU + a * 1000000LLU + b * 1000LLU + c ) ;
  return rt2 ;
}

map< ll , ll > mp ;

void init() {
  scanf( "%d" , &n ) ;
  for ( int i = 0 ; i < n ; i ++ ) {
    for ( int j = 0 ; j < 4 ; j ++ ) {
      scanf( "%d" , &s[ i ][ j ] ) ;
    }
    mp[ toint( s[ i ][ 0 ] , s[ i ][ 1 ] , s[ i ][ 2 ] , s[ i ][ 3 ] ) ] ++ ;
  }
}

ll ans = 0 ;

ll C( ll x , ll y ) {
  ll ret = 1 ;
  for ( ll i = 0 ; i < y ; i ++ ) {
    ret *= x - i ;
  }
  return ret ;
}

ll cnt( ll a , ll b , ll c , ll d ) {
  vector< ll > v ;
  v.push_back( 1000000000000000LLU ) ;
  v.push_back( a ) ;
  v.push_back( b ) ;
  v.push_back( c ) ;
  v.push_back( d ) ;
  sort( v.begin() , v.end() ) ;
  ll ret = 1 ;
  ll ctt = 0 ;
  for ( int i = 0 ; i < (int)v.size() - 1 ; i ++ ) {
    ctt ++ ;
    if ( v[ i ] != v[ i + 1 ] ) {
      ll tret = C( mp[ v[ i ] ] , ctt ) ;
      for ( int j = 0 ; j < (int)ctt ; j ++ )
        tret *= ctint( v[ i ] ) ;
      ret = ret * tret ;
      ctt = 0 ;
    }
  }
  return ret ;
}

ll ans1 = 0 , ans2 = 0 ;

void process() {
  for ( int i = 0 ; i < n ; i ++ ) {
    mp[ toint( s[ i ][ 0 ] , s[ i ][ 1 ] , s[ i ][ 2 ] , s[ i ][ 3 ] ) ] -- ;
    for ( int j = 0 ; j < n ; j ++ ) if ( i != j ) {
      mp[ toint( s[ j ][ 0 ] , s[ j ][ 1 ] , s[ j ][ 2 ] , s[ j ][ 3 ] ) ] -- ;

      ans = 0 ;

      ans += cnt( toint( s[ i ][ 1 ] , s[ i ][ 0 ] , s[ j ][ 1 ] , s[ j ][ 0 ] ) ,
                  toint( s[ i ][ 2 ] , s[ i ][ 1 ] , s[ j ][ 0 ] , s[ j ][ 3 ] ) ,
                  toint( s[ i ][ 3 ] , s[ i ][ 2 ] , s[ j ][ 3 ] , s[ j ][ 2 ] ) ,
                  toint( s[ i ][ 0 ] , s[ i ][ 3 ] , s[ j ][ 2 ] , s[ j ][ 1 ] ) ) ;

      ans += cnt( toint( s[ i ][ 1 ] , s[ i ][ 0 ] , s[ j ][ 2 ] , s[ j ][ 1 ] ) ,
                  toint( s[ i ][ 2 ] , s[ i ][ 1 ] , s[ j ][ 1 ] , s[ j ][ 0 ] ) ,
                  toint( s[ i ][ 3 ] , s[ i ][ 2 ] , s[ j ][ 0 ] , s[ j ][ 3 ] ) ,
                  toint( s[ i ][ 0 ] , s[ i ][ 3 ] , s[ j ][ 3 ] , s[ j ][ 2 ] ) ) ;

      ans += cnt( toint( s[ i ][ 1 ] , s[ i ][ 0 ] , s[ j ][ 3 ] , s[ j ][ 2 ] ) ,
                  toint( s[ i ][ 2 ] , s[ i ][ 1 ] , s[ j ][ 2 ] , s[ j ][ 1 ] ) ,
                  toint( s[ i ][ 3 ] , s[ i ][ 2 ] , s[ j ][ 1 ] , s[ j ][ 0 ] ) ,
                  toint( s[ i ][ 0 ] , s[ i ][ 3 ] , s[ j ][ 0 ] , s[ j ][ 3 ] ) ) ;

      ans += cnt( toint( s[ i ][ 1 ] , s[ i ][ 0 ] , s[ j ][ 0 ] , s[ j ][ 3 ] ) ,
                  toint( s[ i ][ 2 ] , s[ i ][ 1 ] , s[ j ][ 3 ] , s[ j ][ 2 ] ) ,
                  toint( s[ i ][ 3 ] , s[ i ][ 2 ] , s[ j ][ 2 ] , s[ j ][ 1 ] ) ,
                  toint( s[ i ][ 0 ] , s[ i ][ 3 ] , s[ j ][ 1 ] , s[ j ][ 0 ] ) ) ;

      ans1 += ans / 6LLU ;
      ans2 += ans % 6 ;

      mp[ toint( s[ j ][ 0 ] , s[ j ][ 1 ] , s[ j ][ 2 ] , s[ j ][ 3 ] ) ] ++ ;
    }
    mp[ toint( s[ i ][ 0 ] , s[ i ][ 1 ] , s[ i ][ 2 ] , s[ i ][ 3 ] ) ] ++ ;
  }
  ans1 += ans2 / 6 ;
  printf( "%lld\n" , ans1 ) ;
}

int main() {
  init() ;
  process() ;
  return 0 ;
}


Measured memory_bytes: 80000