#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
using namespace std;
void * wmem;
char memarr[ 96000000 ] ;
template < class T> inline void walloc1d( T ** arr, int x, void ** mem = & wmem) {
static int skip[ 16 ] = { 0 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 } ;
( * mem) = ( void * ) ( ( ( char * ) ( * mem) ) + skip[ ( ( unsigned long long ) ( * mem) ) & 15 ] ) ;
( * arr) = ( T* ) ( * mem) ;
( * mem) = ( ( * arr) + x) ;
}
template < class T> inline void walloc1d( T ** arr, int x1, int x2, void ** mem = & wmem) {
walloc1d( arr, x2- x1, mem) ;
( * arr) - = x1;
}
template < class T1, class T2, class T3> void sortA_L( int N, T1 a[ ] , T2 b[ ] , T3 c[ ] , void * mem = wmem) {
int i;
pair< T1, pair< T2, T3> > * arr;
walloc1d( & arr, N, & mem) ;
for ( i= ( 0 ) ; i< ( N) ; i++ ) {
arr[ i] .first = a[ i] ;
arr[ i] .second .first = b[ i] ;
arr[ i] .second .second = c[ i] ;
}
sort( arr, arr+ N) ;
for ( i= ( 0 ) ; i< ( N) ; i++ ) {
a[ i] = arr[ i] .first ;
b[ i] = arr[ i] .second .first ;
c[ i] = arr[ i] .second .second ;
}
}
template < class T1, class T2, class T3, class T4> void sortA_L( int N, T1 a[ ] , T2 b[ ] , T3 c[ ] , T4 d[ ] , void * mem = wmem) {
int i;
pair< pair< T1, T2> , pair< T3, T4> > * arr;
walloc1d( & arr, N, & mem) ;
for ( i= ( 0 ) ; i< ( N) ; i++ ) {
arr[ i] .first .first = a[ i] ;
arr[ i] .first .second = b[ i] ;
arr[ i] .second .first = c[ i] ;
arr[ i] .second .second = d[ i] ;
}
sort( arr, arr+ N) ;
for ( i= ( 0 ) ; i< ( N) ; i++ ) {
a[ i] = arr[ i] .first .first ;
b[ i] = arr[ i] .first .second ;
c[ i] = arr[ i] .second .first ;
d[ i] = arr[ i] .second .second ;
}
}
inline int my_getchar_unlocked( ) {
static char buf[ 1048576 ] ;
static int s = 1048576 ;
static int e = 1048576 ;
if ( s == e && e == 1048576 ) {
e = fread_unlocked( buf, 1 , 1048576 , stdin ) ;
s = 0 ;
}
if ( s == e) {
return EOF ;
}
return buf[ s++ ] ;
}
inline void rd( int & x) {
int k;
int m= 0 ;
x= 0 ;
for ( ;; ) {
k = my_getchar_unlocked( ) ;
if ( k== '-' ) {
m= 1 ;
break ;
}
if ( '0' <= k&& k<= '9' ) {
x= k- '0' ;
break ;
}
}
for ( ;; ) {
k = my_getchar_unlocked( ) ;
if ( k< '0' || k> '9' ) {
break ;
}
x= x* 10 + k- '0' ;
}
if ( m) {
x= - x;
}
}
inline void rd( long long & x) {
int k;
int m= 0 ;
x= 0 ;
for ( ;; ) {
k = my_getchar_unlocked( ) ;
if ( k== '-' ) {
m= 1 ;
break ;
}
if ( '0' <= k&& k<= '9' ) {
x= k- '0' ;
break ;
}
}
for ( ;; ) {
k = my_getchar_unlocked( ) ;
if ( k< '0' || k> '9' ) {
break ;
}
x= x* 10 + k- '0' ;
}
if ( m) {
x= - x;
}
}
struct MY_WRITER{
char buf[ 1048576 ] ;
int s;
int e;
MY_WRITER( ) {
s = 0 ;
e = 1048576 ;
}
~MY_WRITER( ) {
if ( s) {
fwrite_unlocked( buf, 1 , s, stdout ) ;
}
}
}
;
MY_WRITER MY_WRITER_VAR;
void my_putchar_unlocked( int a) {
if ( MY_WRITER_VAR.s == MY_WRITER_VAR.e ) {
fwrite_unlocked( MY_WRITER_VAR.buf , 1 , MY_WRITER_VAR.s , stdout ) ;
MY_WRITER_VAR.s = 0 ;
}
MY_WRITER_VAR.buf [ MY_WRITER_VAR.s ++ ] = a;
}
inline void wt_L( char a) {
my_putchar_unlocked( a) ;
}
inline void wt_L( long long x) {
int s= 0 ;
int m= 0 ;
char f[ 20 ] ;
if ( x< 0 ) {
m= 1 ;
x= - x;
}
while ( x) {
f[ s++ ] = x% 10 ;
x/ = 10 ;
}
if ( ! s) {
f[ s++ ] = 0 ;
}
if ( m) {
my_putchar_unlocked( '-' ) ;
}
while ( s-- ) {
my_putchar_unlocked( f[ s] + '0' ) ;
}
}
template < class T, class U> inline T GCD_L( T a, U b) {
T r;
while ( b) {
r= a;
a= b;
b= r% a;
}
return a;
}
template < class S> inline void arrInsert( const int k, int & sz, S a[ ] , const S aval) {
int i;
sz++ ;
for ( i= sz- 1 ; i> k; i-- ) {
a[ i] = a[ i- 1 ] ;
}
a[ k] = aval;
}
template < class S, class T> inline void arrInsert( const int k, int & sz, S a[ ] , const S aval, T b[ ] , const T bval) {
int i;
sz++ ;
for ( i= sz- 1 ; i> k; i-- ) {
a[ i] = a[ i- 1 ] ;
}
for ( i= sz- 1 ; i> k; i-- ) {
b[ i] = b[ i- 1 ] ;
}
a[ k] = aval;
b[ k] = bval;
}
template < class S, class T, class U> inline void arrInsert( const int k, int & sz, S a[ ] , const S aval, T b[ ] , const T bval, U c[ ] , const U cval) {
int i;
sz++ ;
for ( i= sz- 1 ; i> k; i-- ) {
a[ i] = a[ i- 1 ] ;
}
for ( i= sz- 1 ; i> k; i-- ) {
b[ i] = b[ i- 1 ] ;
}
for ( i= sz- 1 ; i> k; i-- ) {
c[ i] = c[ i- 1 ] ;
}
a[ k] = aval;
b[ k] = bval;
c[ k] = cval;
}
template < class S, class T, class U, class V> inline void arrInsert( const int k, int & sz, S a[ ] , const S aval, T b[ ] , const T bval, U c[ ] , const U cval, V d[ ] , const V dval) {
int i;
sz++ ;
for ( i= sz- 1 ; i> k; i-- ) {
a[ i] = a[ i- 1 ] ;
}
for ( i= sz- 1 ; i> k; i-- ) {
b[ i] = b[ i- 1 ] ;
}
for ( i= sz- 1 ; i> k; i-- ) {
c[ i] = c[ i- 1 ] ;
}
for ( i= sz- 1 ; i> k; i-- ) {
d[ i] = d[ i- 1 ] ;
}
a[ k] = aval;
b[ k] = bval;
c[ k] = cval;
d[ k] = dval;
}
template < class T, class S> T inline cDiv( T a, S b) {
T m;
if ( b < 0 ) {
a = - a;
b = - b;
}
m = a % b;
if ( m == 0 ) {
return a / b;
}
if ( m < 0 ) {
m + = b;
}
return ( a + b - m) / b;
}
int N;
long long X[ 1000 ] ;
long long Y[ 1000 ] ;
int sz;
long long dx[ 1000000 ] ;
long long dy[ 1000000 ] ;
long long dp1[ 1000000 ] ;
long long dp2[ 1000000 ] ;
int ls;
long long lss[ 1000000 ] ;
int main( ) {
wmem = memarr;
long long a;
long long b;
long long c;
long long d;
long long i;
long long j;
long long k;
long long res = 0 ;
map< long long ,int > s;
map< pair< long long ,long long > ,int > ss;
rd( N) ;
{
int Lj4PdHRW;
for ( Lj4PdHRW= ( 0 ) ; Lj4PdHRW< ( N) ; Lj4PdHRW++ ) {
rd( X[ Lj4PdHRW] ) ;
rd( Y[ Lj4PdHRW] ) ;
}
}
for ( i= ( 0 ) ; i< ( N) ; i++ ) {
for ( j= ( i+ 1 ) ; j< ( N) ; j++ ) {
a = X[ i] - X[ j] ;
b = Y[ i] - Y[ j] ;
if ( a < 0 || ( a == 0 && b < 0 ) ) {
{
auto xr20shxY = ( - 1 ) ;
a * = xr20shxY;
b * = xr20shxY;
}
}
{
auto t_ynMSdg = ( GCD_L( abs ( a) , abs ( b) ) ) ;
a / = t_ynMSdg;
b / = t_ynMSdg;
}
{
auto KrdatlYV = ( X[ i] ) ;
auto ao_dF3pO = ( Y[ i] ) ;
c = KrdatlYV;
d = ao_dF3pO;
}
if ( a > 0 ) {
k = cDiv( - c, a) ;
{
auto tU__gIr_ = ( k* a) ;
auto a2conNHc = ( k* b) ;
c + = tU__gIr_;
d + = a2conNHc;
}
}
else {
d = 0 ;
}
arrInsert( sz, sz, dx, a, dy, b, dp1, c, dp2, d) ;
}
}
sortA_L( sz, dx, dy, dp1, dp2) ;
for ( i= ( 0 ) ; i< ( sz) ; i++ ) {
ls = 1 ;
lss[ 0 ] = 1 ;
while ( i+ 1 < sz && dx[ i] == dx[ i+ 1 ] && dy[ i] == dy[ i+ 1 ] ) {
if ( dp1[ i] ! = dp1[ i+ 1 ] || dp2[ i] ! = dp2[ i+ 1 ] ) {
lss[ ls++ ] = 0 ;
}
lss[ ls- 1 ] ++ ;
i++ ;
}
{
int jZyWAPpY;
long long jbtyPBGc;
if ( ls== 0 ) {
jbtyPBGc = 0 ;
}
else {
jbtyPBGc = lss[ 0 ] ;
for ( jZyWAPpY= ( 1 ) ; jZyWAPpY< ( ls) ; jZyWAPpY++ ) {
jbtyPBGc + = lss[ jZyWAPpY] ;
}
}
k = jbtyPBGc;
}
res + = k * ( k- 1 ) / 2 ;
for ( j= ( 0 ) ; j< ( ls) ; j++ ) {
res - = lss[ j] * ( lss[ j] - 1 ) / 2 ;
}
}
for ( i= ( 0 ) ; i< ( N) ; i++ ) {
for ( j= ( i+ 1 ) ; j< ( N) ; j++ ) {
d = ( X[ i] + X[ j] ) * ( 4000000000LL + 5 ) + ( Y[ i] + Y[ j] ) ;
a = X[ i] - X[ j] ;
b = Y[ i] - Y[ j] ;
if ( a < 0 || ( a == 0 && b < 0 ) ) {
{
auto gEg5UqEA = ( - 1 ) ;
a * = gEg5UqEA;
b * = gEg5UqEA;
}
}
{
auto Hjfu7Vx7 = ( GCD_L( abs ( a) , abs ( b) ) ) ;
a / = Hjfu7Vx7;
b / = Hjfu7Vx7;
}
c = a * ( 4000000000LL + 5 ) + b;
res - = ( s[ d] ++ ) ;
res + = ( ss[ make_pair( d,c) ] ++ ) ;
}
}
wt_L( res) ;
wt_L( '\n ' ) ;
return 0 ;
}
// cLay varsion 20201102-1
// --- original code ---
// int N;
// ll X[1000], Y[1000];
//
// int sz; ll dx[1d6], dy[1d6], dp1[1d6], dp2[1d6];
// int ls; ll lss[1d6];
// {
// ll a, b, c, d, i, j, k;
// ll res = 0;
// map<ll,int> s;
// map<pair<ll,ll>,int> ss;
// rd(N,(X,Y)(N));
//
// rep(i,N) rep(j,i+1,N){
// a = X[i] - X[j];
// b = Y[i] - Y[j];
// if(a < 0 || (a == 0 && b < 0)) (a, b) *= -1;
// (a, b) /= gcd(abs(a), abs(b));
// (c, d) = (X[i], Y[i]);
// if(a > 0){
// k = cDiv(-c, a);
// (c, d) += (k*a, k*b);
// } else {
// d = 0;
// }
// arrInsert(sz, sz, dx, a, dy, b, dp1, c, dp2, d);
// }
//
// sortA(sz, dx, dy, dp1, dp2);
// rep(i,sz){
// ls = 1;
// lss[0] = 1;
// while(i+1 < sz && dx[i]==dx[i+1] && dy[i]==dy[i+1]){
// if(dp1[i]!=dp1[i+1] || dp2[i]!=dp2[i+1]) lss[ls++] = 0;
// lss[ls-1]++;
// i++;
// }
// k = sum(lss(ls));
// res += k * (k-1) / 2;
// rep(j,ls) res -= lss[j] * (lss[j]-1) / 2;
// }
//
// rep(i,N) rep(j,i+1,N){
// d = (X[i] + X[j]) * (4d9 + 5) + (Y[i] + Y[j]);
//
// a = X[i] - X[j];
// b = Y[i] - Y[j];
// if(a < 0 || (a == 0 && b < 0)) (a, b) *= -1;
// (a, b) /= gcd(abs(a), abs(b));
// c = a * (4d9 + 5) + b;
//
// res -= (s[d]++);
// res += (ss[make_pair(d,c)]++);
// }
// wt(res);
// }
I3ByYWdtYSBHQ0Mgb3B0aW1pemUgKCJPZmFzdCIpCiNpbmNsdWRlPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CnZvaWQqd21lbTsKY2hhciBtZW1hcnJbOTYwMDAwMDBdOwp0ZW1wbGF0ZTxjbGFzcyBUPiBpbmxpbmUgdm9pZCB3YWxsb2MxZChUICoqYXJyLCBpbnQgeCwgdm9pZCAqKm1lbSA9ICZ3bWVtKXsKICBzdGF0aWMgaW50IHNraXBbMTZdID0gezAsIDE1LCAxNCwgMTMsIDEyLCAxMSwgMTAsIDksIDgsIDcsIDYsIDUsIDQsIDMsIDIsIDF9OwogICgqbWVtKSA9ICh2b2lkKikoICgoY2hhciopKCptZW0pKSArIHNraXBbKCh1bnNpZ25lZCBsb25nIGxvbmcpKCptZW0pKSAmIDE1XSApOwogICgqYXJyKT0oVCopKCptZW0pOwogICgqbWVtKT0oKCphcnIpK3gpOwp9CnRlbXBsYXRlPGNsYXNzIFQ+IGlubGluZSB2b2lkIHdhbGxvYzFkKFQgKiphcnIsIGludCB4MSwgaW50IHgyLCB2b2lkICoqbWVtID0gJndtZW0pewogIHdhbGxvYzFkKGFyciwgeDIteDEsIG1lbSk7CiAgKCphcnIpIC09IHgxOwp9CnRlbXBsYXRlPGNsYXNzIFQxLCBjbGFzcyBUMiwgY2xhc3MgVDM+IHZvaWQgc29ydEFfTChpbnQgTiwgVDEgYVtdLCBUMiBiW10sIFQzIGNbXSwgdm9pZCAqbWVtID0gd21lbSl7CiAgaW50IGk7CiAgcGFpcjxUMSwgcGFpcjxUMiwgVDM+ID4qYXJyOwogIHdhbGxvYzFkKCZhcnIsIE4sICZtZW0pOwogIGZvcihpPSgwKTtpPChOKTtpKyspewogICAgYXJyW2ldLmZpcnN0ID0gYVtpXTsKICAgIGFycltpXS5zZWNvbmQuZmlyc3QgPSBiW2ldOwogICAgYXJyW2ldLnNlY29uZC5zZWNvbmQgPSBjW2ldOwogIH0KICBzb3J0KGFyciwgYXJyK04pOwogIGZvcihpPSgwKTtpPChOKTtpKyspewogICAgYVtpXSA9IGFycltpXS5maXJzdDsKICAgIGJbaV0gPSBhcnJbaV0uc2Vjb25kLmZpcnN0OwogICAgY1tpXSA9IGFycltpXS5zZWNvbmQuc2Vjb25kOwogIH0KfQp0ZW1wbGF0ZTxjbGFzcyBUMSwgY2xhc3MgVDIsIGNsYXNzIFQzLCBjbGFzcyBUND4gdm9pZCBzb3J0QV9MKGludCBOLCBUMSBhW10sIFQyIGJbXSwgVDMgY1tdLCBUNCBkW10sIHZvaWQgKm1lbSA9IHdtZW0pewogIGludCBpOwogIHBhaXI8cGFpcjxUMSwgVDI+LCBwYWlyPFQzLCBUND4gPiphcnI7CiAgd2FsbG9jMWQoJmFyciwgTiwgJm1lbSk7CiAgZm9yKGk9KDApO2k8KE4pO2krKyl7CiAgICBhcnJbaV0uZmlyc3QuZmlyc3QgPSBhW2ldOwogICAgYXJyW2ldLmZpcnN0LnNlY29uZCA9IGJbaV07CiAgICBhcnJbaV0uc2Vjb25kLmZpcnN0ID0gY1tpXTsKICAgIGFycltpXS5zZWNvbmQuc2Vjb25kID0gZFtpXTsKICB9CiAgc29ydChhcnIsIGFycitOKTsKICBmb3IoaT0oMCk7aTwoTik7aSsrKXsKICAgIGFbaV0gPSBhcnJbaV0uZmlyc3QuZmlyc3Q7CiAgICBiW2ldID0gYXJyW2ldLmZpcnN0LnNlY29uZDsKICAgIGNbaV0gPSBhcnJbaV0uc2Vjb25kLmZpcnN0OwogICAgZFtpXSA9IGFycltpXS5zZWNvbmQuc2Vjb25kOwogIH0KfQppbmxpbmUgaW50IG15X2dldGNoYXJfdW5sb2NrZWQoKXsKICBzdGF0aWMgY2hhciBidWZbMTA0ODU3Nl07CiAgc3RhdGljIGludCBzID0gMTA0ODU3NjsKICBzdGF0aWMgaW50IGUgPSAxMDQ4NTc2OwogIGlmKHMgPT0gZSAmJiBlID09IDEwNDg1NzYpewogICAgZSA9IGZyZWFkX3VubG9ja2VkKGJ1ZiwgMSwgMTA0ODU3Niwgc3RkaW4pOwogICAgcyA9IDA7CiAgfQogIGlmKHMgPT0gZSl7CiAgICByZXR1cm4gRU9GOwogIH0KICByZXR1cm4gYnVmW3MrK107Cn0KaW5saW5lIHZvaWQgcmQoaW50ICZ4KXsKICBpbnQgazsKICBpbnQgbT0wOwogIHg9MDsKICBmb3IoOzspewogICAgayA9IG15X2dldGNoYXJfdW5sb2NrZWQoKTsKICAgIGlmKGs9PSctJyl7CiAgICAgIG09MTsKICAgICAgYnJlYWs7CiAgICB9CiAgICBpZignMCc8PWsmJms8PSc5Jyl7CiAgICAgIHg9ay0nMCc7CiAgICAgIGJyZWFrOwogICAgfQogIH0KICBmb3IoOzspewogICAgayA9IG15X2dldGNoYXJfdW5sb2NrZWQoKTsKICAgIGlmKGs8JzAnfHxrPic5Jyl7CiAgICAgIGJyZWFrOwogICAgfQogICAgeD14KjEwK2stJzAnOwogIH0KICBpZihtKXsKICAgIHg9LXg7CiAgfQp9CmlubGluZSB2b2lkIHJkKGxvbmcgbG9uZyAmeCl7CiAgaW50IGs7CiAgaW50IG09MDsKICB4PTA7CiAgZm9yKDs7KXsKICAgIGsgPSBteV9nZXRjaGFyX3VubG9ja2VkKCk7CiAgICBpZihrPT0nLScpewogICAgICBtPTE7CiAgICAgIGJyZWFrOwogICAgfQogICAgaWYoJzAnPD1rJiZrPD0nOScpewogICAgICB4PWstJzAnOwogICAgICBicmVhazsKICAgIH0KICB9CiAgZm9yKDs7KXsKICAgIGsgPSBteV9nZXRjaGFyX3VubG9ja2VkKCk7CiAgICBpZihrPCcwJ3x8az4nOScpewogICAgICBicmVhazsKICAgIH0KICAgIHg9eCoxMCtrLScwJzsKICB9CiAgaWYobSl7CiAgICB4PS14OwogIH0KfQpzdHJ1Y3QgTVlfV1JJVEVSewogIGNoYXIgYnVmWzEwNDg1NzZdOwogIGludCBzOwogIGludCBlOwogIE1ZX1dSSVRFUigpewogICAgcyA9IDA7CiAgICBlID0gMTA0ODU3NjsKICB9CiAgfk1ZX1dSSVRFUigpewogICAgaWYocyl7CiAgICAgIGZ3cml0ZV91bmxvY2tlZChidWYsIDEsIHMsIHN0ZG91dCk7CiAgICB9CiAgfQp9CjsKTVlfV1JJVEVSIE1ZX1dSSVRFUl9WQVI7CnZvaWQgbXlfcHV0Y2hhcl91bmxvY2tlZChpbnQgYSl7CiAgaWYoTVlfV1JJVEVSX1ZBUi5zID09IE1ZX1dSSVRFUl9WQVIuZSl7CiAgICBmd3JpdGVfdW5sb2NrZWQoTVlfV1JJVEVSX1ZBUi5idWYsIDEsIE1ZX1dSSVRFUl9WQVIucywgc3Rkb3V0KTsKICAgIE1ZX1dSSVRFUl9WQVIucyA9IDA7CiAgfQogIE1ZX1dSSVRFUl9WQVIuYnVmW01ZX1dSSVRFUl9WQVIucysrXSA9IGE7Cn0KaW5saW5lIHZvaWQgd3RfTChjaGFyIGEpewogIG15X3B1dGNoYXJfdW5sb2NrZWQoYSk7Cn0KaW5saW5lIHZvaWQgd3RfTChsb25nIGxvbmcgeCl7CiAgaW50IHM9MDsKICBpbnQgbT0wOwogIGNoYXIgZlsyMF07CiAgaWYoeDwwKXsKICAgIG09MTsKICAgIHg9LXg7CiAgfQogIHdoaWxlKHgpewogICAgZltzKytdPXglMTA7CiAgICB4Lz0xMDsKICB9CiAgaWYoIXMpewogICAgZltzKytdPTA7CiAgfQogIGlmKG0pewogICAgbXlfcHV0Y2hhcl91bmxvY2tlZCgnLScpOwogIH0KICB3aGlsZShzLS0pewogICAgbXlfcHV0Y2hhcl91bmxvY2tlZChmW3NdKycwJyk7CiAgfQp9CnRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzIFU+IGlubGluZSBUIEdDRF9MKFQgYSwgVSBiKXsKICBUIHI7CiAgd2hpbGUoYil7CiAgICByPWE7CiAgICBhPWI7CiAgICBiPXIlYTsKICB9CiAgcmV0dXJuIGE7Cn0KdGVtcGxhdGU8Y2xhc3MgUz4gaW5saW5lIHZvaWQgYXJySW5zZXJ0KGNvbnN0IGludCBrLCBpbnQgJnN6LCBTIGFbXSwgY29uc3QgUyBhdmFsKXsKICBpbnQgaTsKICBzeisrOwogIGZvcihpPXN6LTE7aT5rO2ktLSl7CiAgICBhW2ldID0gYVtpLTFdOwogIH0KICBhW2tdID0gYXZhbDsKfQp0ZW1wbGF0ZTxjbGFzcyBTLCBjbGFzcyBUPiBpbmxpbmUgdm9pZCBhcnJJbnNlcnQoY29uc3QgaW50IGssIGludCAmc3osIFMgYVtdLCBjb25zdCBTIGF2YWwsIFQgYltdLCBjb25zdCBUIGJ2YWwpewogIGludCBpOwogIHN6Kys7CiAgZm9yKGk9c3otMTtpPms7aS0tKXsKICAgIGFbaV0gPSBhW2ktMV07CiAgfQogIGZvcihpPXN6LTE7aT5rO2ktLSl7CiAgICBiW2ldID0gYltpLTFdOwogIH0KICBhW2tdID0gYXZhbDsKICBiW2tdID0gYnZhbDsKfQp0ZW1wbGF0ZTxjbGFzcyBTLCBjbGFzcyBULCBjbGFzcyBVPiBpbmxpbmUgdm9pZCBhcnJJbnNlcnQoY29uc3QgaW50IGssIGludCAmc3osIFMgYVtdLCBjb25zdCBTIGF2YWwsIFQgYltdLCBjb25zdCBUIGJ2YWwsIFUgY1tdLCBjb25zdCBVIGN2YWwpewogIGludCBpOwogIHN6Kys7CiAgZm9yKGk9c3otMTtpPms7aS0tKXsKICAgIGFbaV0gPSBhW2ktMV07CiAgfQogIGZvcihpPXN6LTE7aT5rO2ktLSl7CiAgICBiW2ldID0gYltpLTFdOwogIH0KICBmb3IoaT1zei0xO2k+aztpLS0pewogICAgY1tpXSA9IGNbaS0xXTsKICB9CiAgYVtrXSA9IGF2YWw7CiAgYltrXSA9IGJ2YWw7CiAgY1trXSA9IGN2YWw7Cn0KdGVtcGxhdGU8Y2xhc3MgUywgY2xhc3MgVCwgY2xhc3MgVSwgY2xhc3MgVj4gaW5saW5lIHZvaWQgYXJySW5zZXJ0KGNvbnN0IGludCBrLCBpbnQgJnN6LCBTIGFbXSwgY29uc3QgUyBhdmFsLCBUIGJbXSwgY29uc3QgVCBidmFsLCBVIGNbXSwgY29uc3QgVSBjdmFsLCBWIGRbXSwgY29uc3QgViBkdmFsKXsKICBpbnQgaTsKICBzeisrOwogIGZvcihpPXN6LTE7aT5rO2ktLSl7CiAgICBhW2ldID0gYVtpLTFdOwogIH0KICBmb3IoaT1zei0xO2k+aztpLS0pewogICAgYltpXSA9IGJbaS0xXTsKICB9CiAgZm9yKGk9c3otMTtpPms7aS0tKXsKICAgIGNbaV0gPSBjW2ktMV07CiAgfQogIGZvcihpPXN6LTE7aT5rO2ktLSl7CiAgICBkW2ldID0gZFtpLTFdOwogIH0KICBhW2tdID0gYXZhbDsKICBiW2tdID0gYnZhbDsKICBjW2tdID0gY3ZhbDsKICBkW2tdID0gZHZhbDsKfQp0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcyBTPiBUIGlubGluZSBjRGl2KFQgYSwgUyBiKXsKICBUIG07CiAgaWYoYiA8IDApewogICAgYSA9IC1hOwogICAgYiA9IC1iOwogIH0KICBtID0gYSAlIGI7CiAgaWYobSA9PSAwKXsKICAgIHJldHVybiBhIC8gYjsKICB9CiAgaWYobSA8IDApewogICAgbSArPSBiOwogIH0KICByZXR1cm4gKGEgKyBiIC0gbSkgLyBiOwp9CmludCBOOwpsb25nIGxvbmcgWFsxMDAwXTsKbG9uZyBsb25nIFlbMTAwMF07CmludCBzejsKbG9uZyBsb25nIGR4WzEwMDAwMDBdOwpsb25nIGxvbmcgZHlbMTAwMDAwMF07CmxvbmcgbG9uZyBkcDFbMTAwMDAwMF07CmxvbmcgbG9uZyBkcDJbMTAwMDAwMF07CmludCBsczsKbG9uZyBsb25nIGxzc1sxMDAwMDAwXTsKaW50IG1haW4oKXsKICB3bWVtID0gbWVtYXJyOwogIGxvbmcgbG9uZyBhOwogIGxvbmcgbG9uZyBiOwogIGxvbmcgbG9uZyBjOwogIGxvbmcgbG9uZyBkOwogIGxvbmcgbG9uZyBpOwogIGxvbmcgbG9uZyBqOwogIGxvbmcgbG9uZyBrOwogIGxvbmcgbG9uZyByZXMgPSAwOwogIG1hcDxsb25nIGxvbmcsaW50PiBzOwogIG1hcDxwYWlyPGxvbmcgbG9uZyxsb25nIGxvbmc+LGludD4gc3M7CiAgcmQoTik7CiAgewogICAgaW50IExqNFBkSFJXOwogICAgZm9yKExqNFBkSFJXPSgwKTtMajRQZEhSVzwoTik7TGo0UGRIUlcrKyl7CiAgICAgIHJkKFhbTGo0UGRIUlddKTsKICAgICAgcmQoWVtMajRQZEhSV10pOwogICAgfQogIH0KICBmb3IoaT0oMCk7aTwoTik7aSsrKXsKICAgIGZvcihqPShpKzEpO2o8KE4pO2orKyl7CiAgICAgIGEgPSBYW2ldIC0gWFtqXTsKICAgICAgYiA9IFlbaV0gLSBZW2pdOwogICAgICBpZihhIDwgMCB8fCAoYSA9PSAwICYmIGIgPCAwKSl7CiAgICAgICAgewogICAgICAgICAgYXV0byB4cjIwc2h4WSA9ICgtMSk7CiAgICAgICAgICBhICo9IHhyMjBzaHhZOwogICAgICAgICAgYiAqPSB4cjIwc2h4WTsKICAgICAgICB9CiAgICAgIH0KICAgICAgewogICAgICAgIGF1dG8gdF95bk1TZGcgPSAoR0NEX0woYWJzKGEpLCBhYnMoYikpKTsKICAgICAgICBhIC89IHRfeW5NU2RnOwogICAgICAgIGIgLz0gdF95bk1TZGc7CiAgICAgIH0KICAgICAgewogICAgICAgIGF1dG8gS3JkYXRsWVYgPSAoWFtpXSk7CiAgICAgICAgYXV0byBhb19kRjNwTyA9ICggWVtpXSk7CiAgICAgICAgYyA9IEtyZGF0bFlWOwogICAgICAgIGQgPSBhb19kRjNwTzsKICAgICAgfQogICAgICBpZihhID4gMCl7CiAgICAgICAgayA9IGNEaXYoLWMsIGEpOwogICAgICAgIHsKICAgICAgICAgIGF1dG8gdFVfX2dJcl8gPSAoayphKTsKICAgICAgICAgIGF1dG8gYTJjb25OSGMgPSAoIGsqYik7CiAgICAgICAgICBjICs9IHRVX19nSXJfOwogICAgICAgICAgZCArPSBhMmNvbk5IYzsKICAgICAgICB9CiAgICAgIH0KICAgICAgZWxzZXsKICAgICAgICBkID0gMDsKICAgICAgfQogICAgICBhcnJJbnNlcnQoc3osIHN6LCBkeCwgYSwgZHksIGIsIGRwMSwgYywgZHAyLCBkKTsKICAgIH0KICB9CiAgc29ydEFfTChzeiwgZHgsIGR5LCBkcDEsIGRwMik7CiAgZm9yKGk9KDApO2k8KHN6KTtpKyspewogICAgbHMgPSAxOwogICAgbHNzWzBdID0gMTsKICAgIHdoaWxlKGkrMSA8IHN6ICYmIGR4W2ldPT1keFtpKzFdICYmIGR5W2ldPT1keVtpKzFdKXsKICAgICAgaWYoZHAxW2ldIT1kcDFbaSsxXSB8fCBkcDJbaV0hPWRwMltpKzFdKXsKICAgICAgICBsc3NbbHMrK10gPSAwOwogICAgICB9CiAgICAgIGxzc1tscy0xXSsrOwogICAgICBpKys7CiAgICB9CiAgICB7CiAgICAgIGludCBqWnlXQVBwWTsKICAgICAgbG9uZyBsb25nIGpidHlQQkdjOwogICAgICBpZihscz09MCl7CiAgICAgICAgamJ0eVBCR2MgPSAwOwogICAgICB9CiAgICAgIGVsc2V7CiAgICAgICAgamJ0eVBCR2MgPSBsc3NbMF07CiAgICAgICAgZm9yKGpaeVdBUHBZPSgxKTtqWnlXQVBwWTwobHMpO2paeVdBUHBZKyspewogICAgICAgICAgamJ0eVBCR2MgKz0gbHNzW2paeVdBUHBZXTsKICAgICAgICB9CiAgICAgIH0KICAgICAgayA9amJ0eVBCR2M7CiAgICB9CiAgICByZXMgKz0gayAqIChrLTEpIC8gMjsKICAgIGZvcihqPSgwKTtqPChscyk7aisrKXsKICAgICAgcmVzIC09IGxzc1tqXSAqIChsc3Nbal0tMSkgLyAyOwogICAgfQogIH0KICBmb3IoaT0oMCk7aTwoTik7aSsrKXsKICAgIGZvcihqPShpKzEpO2o8KE4pO2orKyl7CiAgICAgIGQgPSAoWFtpXSArIFhbal0pICogKDQwMDAwMDAwMDBMTCArIDUpICsgKFlbaV0gKyBZW2pdKTsKICAgICAgYSA9IFhbaV0gLSBYW2pdOwogICAgICBiID0gWVtpXSAtIFlbal07CiAgICAgIGlmKGEgPCAwIHx8IChhID09IDAgJiYgYiA8IDApKXsKICAgICAgICB7CiAgICAgICAgICBhdXRvIGdFZzVVcUVBID0gKC0xKTsKICAgICAgICAgIGEgKj0gZ0VnNVVxRUE7CiAgICAgICAgICBiICo9IGdFZzVVcUVBOwogICAgICAgIH0KICAgICAgfQogICAgICB7CiAgICAgICAgYXV0byBIamZ1N1Z4NyA9IChHQ0RfTChhYnMoYSksIGFicyhiKSkpOwogICAgICAgIGEgLz0gSGpmdTdWeDc7CiAgICAgICAgYiAvPSBIamZ1N1Z4NzsKICAgICAgfQogICAgICBjID0gYSAqICg0MDAwMDAwMDAwTEwgKyA1KSArIGI7CiAgICAgIHJlcyAtPSAoc1tkXSsrKTsKICAgICAgcmVzICs9IChzc1ttYWtlX3BhaXIoZCxjKV0rKyk7CiAgICB9CiAgfQogIHd0X0wocmVzKTsKICB3dF9MKCdcbicpOwogIHJldHVybiAwOwp9Ci8vIGNMYXkgdmFyc2lvbiAyMDIwMTEwMi0xCgovLyAtLS0gb3JpZ2luYWwgY29kZSAtLS0KLy8gaW50IE47Ci8vIGxsIFhbMTAwMF0sIFlbMTAwMF07Ci8vIAovLyBpbnQgc3o7IGxsIGR4WzFkNl0sIGR5WzFkNl0sIGRwMVsxZDZdLCBkcDJbMWQ2XTsKLy8gaW50IGxzOyBsbCBsc3NbMWQ2XTsKLy8gewovLyAgIGxsIGEsIGIsIGMsIGQsIGksIGosIGs7Ci8vICAgbGwgcmVzID0gMDsKLy8gICBtYXA8bGwsaW50PiBzOwovLyAgIG1hcDxwYWlyPGxsLGxsPixpbnQ+IHNzOwovLyAgIHJkKE4sKFgsWSkoTikpOwovLyAKLy8gICByZXAoaSxOKSByZXAoaixpKzEsTil7Ci8vICAgICBhID0gWFtpXSAtIFhbal07Ci8vICAgICBiID0gWVtpXSAtIFlbal07Ci8vICAgICBpZihhIDwgMCB8fCAoYSA9PSAwICYmIGIgPCAwKSkgKGEsIGIpICo9IC0xOwovLyAgICAgKGEsIGIpIC89IGdjZChhYnMoYSksIGFicyhiKSk7Ci8vICAgICAoYywgZCkgPSAoWFtpXSwgWVtpXSk7Ci8vICAgICBpZihhID4gMCl7Ci8vICAgICAgIGsgPSBjRGl2KC1jLCBhKTsKLy8gICAgICAgKGMsIGQpICs9IChrKmEsIGsqYik7Ci8vICAgICB9IGVsc2UgewovLyAgICAgICBkID0gMDsKLy8gICAgIH0KLy8gICAgIGFyckluc2VydChzeiwgc3osIGR4LCBhLCBkeSwgYiwgZHAxLCBjLCBkcDIsIGQpOwovLyAgIH0KLy8gCi8vICAgc29ydEEoc3osIGR4LCBkeSwgZHAxLCBkcDIpOwovLyAgIHJlcChpLHN6KXsKLy8gICAgIGxzID0gMTsKLy8gICAgIGxzc1swXSA9IDE7Ci8vICAgICB3aGlsZShpKzEgPCBzeiAmJiBkeFtpXT09ZHhbaSsxXSAmJiBkeVtpXT09ZHlbaSsxXSl7Ci8vICAgICAgIGlmKGRwMVtpXSE9ZHAxW2krMV0gfHwgZHAyW2ldIT1kcDJbaSsxXSkgbHNzW2xzKytdID0gMDsKLy8gICAgICAgbHNzW2xzLTFdKys7Ci8vICAgICAgIGkrKzsKLy8gICAgIH0KLy8gICAgIGsgPSBzdW0obHNzKGxzKSk7Ci8vICAgICByZXMgKz0gayAqIChrLTEpIC8gMjsKLy8gICAgIHJlcChqLGxzKSByZXMgLT0gbHNzW2pdICogKGxzc1tqXS0xKSAvIDI7Ci8vICAgfQovLyAKLy8gICByZXAoaSxOKSByZXAoaixpKzEsTil7Ci8vICAgICBkID0gKFhbaV0gKyBYW2pdKSAqICg0ZDkgKyA1KSArIChZW2ldICsgWVtqXSk7Ci8vIAovLyAgICAgYSA9IFhbaV0gLSBYW2pdOwovLyAgICAgYiA9IFlbaV0gLSBZW2pdOwovLyAgICAgaWYoYSA8IDAgfHwgKGEgPT0gMCAmJiBiIDwgMCkpIChhLCBiKSAqPSAtMTsKLy8gICAgIChhLCBiKSAvPSBnY2QoYWJzKGEpLCBhYnMoYikpOwovLyAgICAgYyA9IGEgKiAoNGQ5ICsgNSkgKyBiOwovLyAKLy8gICAgIHJlcyAtPSAoc1tkXSsrKTsKLy8gICAgIHJlcyArPSAoc3NbbWFrZV9wYWlyKGQsYyldKyspOwovLyAgIH0KLy8gICB3dChyZXMpOwovLyB9Cg==