#include<bits/stdc++.h>
using namespace std;
#define  ld long double
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N;
    cin >> N;
    pair<ld, ld> arr[N];
    map<ld, int64_t> g;
    int k1[1000000] = {0}, k2[1000000] = {0};
    map<pair<ld, ld>, ld> jrr;
    for (int i = 0; i < N; i++) {
        ld x, y;
        cin >> x >> y;
        arr[i] = {x, y};
    }
    for (int i = 0; i < N - 1; i++) {
        for (int j = i + 1; j < N; j++) {
            ld x1 = arr[i].first, x2 = arr[j].first, y1 = arr[i].second, y2 = arr[j].second;
            if (y1 == y2) {
                ld slope = 0;
                if (!k1[(int)abs(y1)]) g[slope]++, k1[(int)abs(y1)] = 1;//cout << i << ' ' << j << '\n';
            }
            else {
                if (x1 == x2) {
                    ld slope = 100000000;
                    if (!k2[(int)abs(x1)]) g[slope]++, k2[(int)abs(x1)] = 1;//cout << i << ' ' << j << '\n';
                }
                else {
                    ld slope = (y1 - y2) / (x1 - x2);
                    ld q = y1 - slope * x1;
                    if (jrr.find({q, slope}) == jrr.end()) g[slope]++, jrr[{q,slope}] = 1;
                    //cout << i << ' ' << j << '\n';
                }
            }
        }
    }
    int64_t ans = 0;
    vector<ld> v;
    for (auto to : g) v.push_back(to.second);
    //cout << v.size() << '\n';
    for (int i = 0; i < v.size() - 1; i++) {
        for (int j = i + 1; j < v.size(); j++) ans += v[i] * v[j];
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;
#define  ld long double
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    int N;
    cin >> N;
    pair<ld, ld> arr[N];
    map<ld, int64_t> g, k1, k2;
    map<pair<ld, ld>, ld> jrr;
    for (int i = 0; i < N; i++) {
        ld x, y;
        cin >> x >> y;
        arr[i] = {x, y};
    }
    for (int i = 0; i < N - 1; i++) {
        for (int j = i + 1; j < N; j++) {
            ld x1 = arr[i].first, x2 = arr[j].first, y1 = arr[i].second, y2 = arr[j].second;
            if (y1 == y2) {
                ld slope = 0;
                if (k1.find(y1) == k1.end()) g[slope]++, k1[y1] = 1;
            }
            else {
                if (x1 == x2) {
                    ld slope = 10000000000;
                    if (k2.find(x1) == k2.end()) g[slope]++, k2[x1] = 1;
                }
                else {
                    ld slope = (y1 - y2) / (x1 - x2);
                    ld q = y1 - slope * x1;
                    if (jrr.find({q, slope}) == jrr.end()) g[slope]++, jrr[{q,slope}] = 1;
                }
            }
        }
    }
    int64_t ans = 0;
    vector<int64_t> v;
    for (auto to : g) v.push_back(to.second);
    //cout << v.size() << '\n';
    for (int i = 0; i < v.size() - 1; i++) {
        for (int j = i + 1; j < v.size(); j++) ans += v[i] * v[j];
    }
    cout << ans;
}


#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;

int main(){

  ll n;
  cin>>n;

  vector < pair <ll,ll> > vec,ve;

  for(ll i=0;i<n;i++)
  {
      ll x,y;
      cin>>x>>y;
      vec.push_back({x,y});

  }

  vector < long double > slop;

    map < ll, map <long double,ll> > mp;
  for(ll i=0;i<n;i++)
  {

      for(ll j=i+1;j<n;j++)
      {
          //if(i==j)continue;
            long double xx;
          if(vec[i].first == vec[j].first)
          {
              xx = LDBL_MAX;
          }
          else{
             xx =  ((vec[i].second - vec[j].second)*1.0)/(vec[i].first - vec[j].first );
          }
          if(mp[i].find(xx)==mp[i].end() and mp[j].find(xx)==mp[j].end())
          {
              slop.push_back(xx);
              mp[i][xx]=1;
              mp[j][xx]=1;
          }
      }
  }

  ll ans = 0;
  //cout<<slop.size()<<endl;;
    /*
  for(ll i=0;i<slop.size();i++)
  {
      cout<<slop[i]<<" ";
  }cout<<endl;*/

  for(ll i=0;i<slop.size();i++)
  {
      for(ll j=i+1;j<slop.size();++j)
      {
          if( slop[i] != slop[j])
          {
              ans++;
          }
      }
  }

  cout<<ans<<endl;

}


#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;

int main(){

  ll n;
  cin>>n;

  vector < pair <ll,ll> > vec,ve;

  for(ll i=0;i<n;i++)
  {
      ll x,y;
      cin>>x>>y;
      vec.push_back({x,y});

  }

  vector < long double > slop;

    map < ll, map <long double,ll> > mp;
  for(ll i=0;i<n;i++)
  {

      for(ll j=i+1;j<n;j++)
      {
          //if(i==j)continue;
            long double xx;
          if(vec[i].first == vec[j].first)
          {
              xx = LDBL_MAX;
          }
          else{
             xx =  ((vec[i].second - vec[j].second)*1.0)/(vec[i].first - vec[j].first );
          }
          if(mp[i].find(xx)==mp[i].end())
          {
              slop.push_back(xx);
              mp[i][xx]=1;
              mp[j][xx]=1;
          }
      }
  }

  ll ans = 0;
  //cout<<slop.size()<<endl;;
  /*
  for(ll i=0;i<slop.size();i++)
  {
      cout<<slop[i]<<" ";
  }cout<<endl;*/

  for(ll i=0;i<slop.size();i++)
  {
      for(ll j=i+1;j<slop.size();++j)
      {
          if( abs(slop[i] - slop[j])>0.0001)
          {
              ans++;
          }
      }
  }

  cout<<ans<<endl;

}


#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;

int main(){

  ll n;
  cin>>n;

  vector < pair <ll,ll> > vec,ve;

  for(ll i=0;i<n;i++)
  {
      ll x,y;
      cin>>x>>y;
      vec.push_back({x,y});

  }

  vector < long double > slop;

    map < ll, map <long double,ll> > mp;
  for(ll i=0;i<n;i++)
  {

      for(ll j=i+1;j<n;j++)
      {
          //if(i==j)continue;
            long double xx;
          if(vec[i].first == vec[j].first)
          {
              xx = LDBL_MAX;
          }
          else{
             xx =  ((vec[i].second - vec[j].second)*1.0)/(vec[i].first - vec[j].first );
          }
          if(mp[i].find(xx)==mp[i].end() and mp[j].find(xx)==mp[j].end())
          {
              slop.push_back(xx);
              mp[i][xx]=1;
              mp[j][xx]=1;
          }
          mp[i][xx]=1;
              mp[j][xx]=1;
      }
  }

  ll ans = 0;
  //cout<<slop.size()<<endl;;
    /*
  for(ll i=0;i<slop.size();i++)
  {
      cout<<slop[i]<<" ";
  }cout<<endl;*/

    map <double,ll> mb;
  for(ll i=0;i<slop.size();i++)
  {
      mb[slop[i]]++;
  }

  for(auto it = mb.begin();it!=mb.end();it++)
  {
      ans += (it->second)*(slop.size() - it->second);
  }

  cout<<ans/2<<endl;

}


#include<bits/stdc++.h>
using namespace std;

typedef long long int ll;

int main(){

  ll n;
  cin>>n;

  vector < pair <ll,ll> > vec,ve;

  for(ll i=0;i<n;i++)
  {
      ll x,y;
      cin>>x>>y;
      vec.push_back({x,y});

  }

  vector < long double > slop;

    map < ll, map <long double,ll> > mp;
  for(ll i=0;i<n;i++)
  {

      for(ll j=i+1;j<n;j++)
      {
          //if(i==j)continue;
            long double xx;
          if(vec[i].first == vec[j].first)
          {
              xx = LDBL_MAX;
          }
          else{
             xx =  ((vec[i].second - vec[j].second)*1.0)/(vec[i].first - vec[j].first );
          }
          if(mp[i].find(xx)==mp[i].end())
          {
              slop.push_back(xx);
              mp[i][xx]=1;
              mp[j][xx]=1;
          }
      }
  }

  ll ans = 0;
  //cout<<slop.size()<<endl;;
  /*
  for(ll i=0;i<slop.size();i++)
  {
      cout<<slop[i]<<" ";
  }cout<<endl;*/

  for(ll i=0;i<slop.size();i++)
  {
      for(ll j=i+1;j<slop.size();++j)
      {
          if( slop[i] != slop[j])
          {
              ans++;
          }
      }
  }

  cout<<ans<<endl;

}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}

ll gcd(ll a, ll b)
{
    if (a == 0)
        return b;
    return gcd(b%a, a);
}

pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line()
    {
        a = 0, b = 0, c = 0;
    }
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
    bool operator == (const line &other) const
    {
        return a == other.a && b == other.b && c == other.c;
    }

};

bool overflow(long double x, long double y)
{
    return abs(x) * abs(y) >= 1e18;
}

line makeLine(pair<ll, ll> p1, pair<ll, ll> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X;
    pair<ll, ll> temp = handleFraction(a, b);
    a = temp.first, b = temp.second;
    ll c = -1LL * b * p1.Y + 1LL * a * p1.X;
//    cout << c << endl;
    a *= -1;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<ll, ll> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    vector<line> vLine;
    set<line> sLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            sLine.insert(makeLine(v[i], v[j]));
//            vLine.pb(makeLine(v[i], v[j]));
        }
    }
//    sort(all(vLine));
//    vLine.resize((unique(vLine.begin(), vLine.end()) - vLine.begin()));
    for (auto &l : sLine)
        vLine.pb(l);
//    cout << sz(sLine) << endl;
    ll ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

int findSign(int x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}
pair<int, int> handleFraction(int a, int b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    int div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    int sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
pii getSlope(pair<int, int> a, pair<int, int> b)
{
    int yDiff = b.Y - a.Y, xDiff = b.X - a.X;
    return handleFraction(yDiff, xDiff);
}

#define pdd pair<double, double>

bool lineLineIntersection(pdd A, pdd B, pdd C, pdd D)
{
    // Line AB represented as a1x + b1y = c1
    double a1 = B.second - A.second;
    double b1 = A.first - B.first;
    double c1 = a1*(A.first) + b1*(A.second);

    // Line CD represented as a2x + b2y = c2
    double a2 = D.second - C.second;
    double b2 = C.first - D.first;
    double c2 = a2*(C.first)+ b2*(C.second);

    double determinant = a1*b2 - a2*b1;

    if (dcmp(determinant, 0) == 0)
    {
        // The lines are parallel. This is simplified
        // by returning a pair of FLT_MAX
        return false;
    }
    return true;
}
pair<pii, pii> makeLine(pii a, pii b)
{
    if (a > b)
        swap(a, b);
    return make_pair(a, b);
}
bool collinear(int x1, int y1, int x2,
               int y2, int x3, int y3)
{
    // Calculation the area of
    // triangle. We have skipped
    // multiplication with 0.5
    // to avoid floating point
    // computations
    int a = x1 * (y2 - y3) +
            x2 * (y3 - y1) +
            x3 * (y1 - y2);

    if (a == 0)
        return true;
    else
        return false;
}
bool ok(vector<pair<pii, pii> >linesCords, pair<pii, pii> lineX)
{
    rep(i,0,sz(linesCords))
    {
        if (getSlope(linesCords[i].first, linesCords[i].second) == getSlope(lineX.first, lineX.second))
        {
            if (collinear(linesCords[i].first.first, linesCords[i].first.second, linesCords[i].second.first, linesCords[i].second.second, lineX.first.first, lineX.first.second))
            {
                return false;
            }
        }
    }
    return true;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<int, int> > v(n);
    vector<pii> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;

    vector<pair<pii, pii> > linesCords;
    rep(i,0,n)
    {
        rep(j, i + 1, n)
        {
            pair<pii, pii> lineX = makeLine(v[i], v[j]);
            if (!ok(linesCords, lineX))
                continue;

            lines.pb(getSlope(v[i], v[j]));
            linesCords.pb(lineX);
        }
    }
//    cout << endl;
    ll ret = 0;
    rep(i,0,sz(lines))
    {
        rep(j,i + 1, sz(lines))
        {
            if (lines[i] != lines[j])
            {
                ret++;
//                cout << i << ' ' << j << ' ' << endl;

            }
        }
    }
    cout << ret;

    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}
pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
};

line makeLine(pair<ll, ll> p1, pair<ll, ll> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X, c = -1 * b * p1.Y + a * p1.X;
    a = -1 * a;
    ll div = __gcd(__gcd(abs(a), abs(b)), abs(c));
    a /= div;
    b /= div;
    c /= div;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<int, int> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    set<line> sLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            sLine.insert(makeLine(v[i], v[j]));
        }
    }
    vector<line> vLine;
    for (auto &item : sLine)
        vLine.push_back(item);
    int ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}
pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
};

line makeLine(pair<int, int> p1, pair<int, int> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X, c = -1 * b * p1.Y + a * p1.X;
    a = -1 * a;
    ll div = __gcd(__gcd(abs(a), abs(b)), abs(c));
    a /= div;
    b /= div;
    c /= div;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<int, int> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    set<line> sLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            sLine.insert(makeLine(v[i], v[j]));
        }
    }
    vector<line> vLine;
    for (auto &item : sLine)
        vLine.push_back(item);
    int ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}
pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line()
    {
        a = 0, b = 0, c = 0;
    }
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
    bool operator == (const line &other) const
    {
        return a == other.a && b == other.b && c == other.c;
    }

};

line makeLine(pair<ll, ll> p1, pair<ll, ll> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X;
    ll div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll c = -1 * b * p1.Y + a * p1.X;
    a = -1 * a;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<ll, ll> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    vector<line> vLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            vLine.pb(makeLine(v[i], v[j]));
        }
    }
    sort(all(vLine));
    vLine.resize((unique(vLine.begin(), vLine.end()) - vLine.begin()));
    int ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<ll, ll>, // change type
//        null_type,
//        less<pair<ll, ll> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(ll i = start; i < end; ++i)
#define sz(x) (ll)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<ll, ll>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
ll dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}
pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
pii getSlope(pair<ll, ll> a, pair<ll, ll> b)
{
    ll yDiff = b.Y - a.Y, xDiff = b.X - a.X;
    return handleFraction(yDiff, xDiff);
}

#define pdd pair<double, double>

bool lineLineIntersection(pdd A, pdd B, pdd C, pdd D)
{
    // Line AB represented as a1x + b1y = c1
    double a1 = B.second - A.second;
    double b1 = A.first - B.first;
    double c1 = a1*(A.first) + b1*(A.second);

    // Line CD represented as a2x + b2y = c2
    double a2 = D.second - C.second;
    double b2 = C.first - D.first;
    double c2 = a2*(C.first)+ b2*(C.second);

    double determinant = a1*b2 - a2*b1;

    if (dcmp(determinant, 0) == 0)
    {
        // The lines are parallel. This is simplified
        // by returning a pair of FLT_MAX
        return false;
    }
    return true;
}
pair<pii, pii> makeLine(pii a, pii b)
{
    if (a > b)
        swap(a, b);
    return make_pair(a, b);
}
bool collinear(ll x1, ll y1, ll x2,
               ll y2, ll x3, ll y3)
{
    // Calculation the area of
    // triangle. We have skipped
    // multiplication with 0.5
    // to avoid floating point
    // computations
    ll a = x1 * (y2 - y3) +
            x2 * (y3 - y1) +
            x3 * (y1 - y2);

    if (a == 0)
        return true;
    else
        return false;
}
bool ok(const vector<pair<pii, pii> > &linesCords, pair<pii, pii> lineX)
{
    rep(i,0,sz(linesCords))
    {
        if (getSlope(linesCords[i].first, linesCords[i].second) == getSlope(lineX.first, lineX.second))
        {
            if (collinear(linesCords[i].first.first, linesCords[i].first.second, linesCords[i].second.first, linesCords[i].second.second, lineX.first.first, lineX.first.second))
            {
                return false;
            }
        }
    }
    return true;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    ll n;
    cin >> n;
    vector<pair<ll, ll> > v(n);
    vector<pii> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;

    vector<pair<pii, pii> > linesCords;
    rep(i,0,n)
    {
        rep(j, i + 1, n)
        {
            pair<pii, pii> lineX = makeLine(v[i], v[j]);
            if (!ok(linesCords, lineX))
                continue;

            lines.pb(getSlope(lineX.first, lineX.second));
            linesCords.pb(lineX);
        }
    }
//    cout << endl;
    ll ret = 0;
    rep(i,0,sz(lines))
    {
        rep(j,i + 1, sz(lines))
        {
            if (lines[i] != lines[j])
            {
                ret++;
//                cout << i << ' ' << j << ' ' << endl;

            }
        }
    }
    cout << ret;

    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}
pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = __gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line()
    {
        a = 0, b = 0, c = 0;
    }
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
    bool operator == (const line &other) const
    {
        return a == other.a && b == other.b && c == other.c;
    }

};

line makeLine(pair<ll, ll> p1, pair<ll, ll> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X, c = -1 * b * p1.Y + a * p1.X;
    a = -1 * a;
    ll div = __gcd(__gcd(abs(a), abs(b)), abs(c));
    a /= div;
    b /= div;
    c /= div;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<ll, ll> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    vector<line> vLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            vLine.pb(makeLine(v[i], v[j]));
        }
    }
    sort(all(vLine));
    vLine.resize((unique(vLine.begin(), vLine.end()) - vLine.begin()));
    int ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}

ll gcd(ll a, ll b)
{
    if (a == 0)
        return b;
    return gcd(b%a, a);
}

pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {findSign(a), 0};
    if (a == 0)
        return {0, 1};
    ll div = gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line()
    {
        a = 0, b = 0, c = 0;
    }
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
    bool operator == (const line &other) const
    {
        return a == other.a && b == other.b && c == other.c;
    }

};

bool overflow(long double x, long double y)
{
    return abs(x) * abs(y) >= 1e18;
}

line makeLine(pair<ll, ll> p1, pair<ll, ll> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X;
    ll div = gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll c = -1LL * b * p1.Y + 1LL * a * p1.X;
//    cout << c << endl;
    a *= -1;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<ll, ll> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    vector<line> vLine;
    set<line> sLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            sLine.insert(makeLine(v[i], v[j]));
//            vLine.pb(makeLine(v[i], v[j]));
        }
    }
//    sort(all(vLine));
//    vLine.resize((unique(vLine.begin(), vLine.end()) - vLine.begin()));
    for (auto &l : sLine)
        vLine.pb(l);
    ll ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp> // Common file
//#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update

using namespace std;
//using namespace __gnu_pbds;
//typedef tree<
//        pair<int, int>, // change type
//        null_type,
//        less<pair<int, int> >, // change type
//        rb_tree_tag,
//        tree_order_statistics_node_update>
//        ordered_set;

typedef long long ll;
#define rep(i, start, end) for(int i = start; i < end; ++i)
#define sz(x) (int)(x).size()
#define pb push_back
#define X first
#define Y second
#define all(x) x.begin(), x.end()
#define clr(d, v) memset(d, v, sizeof(d))
#define pii pair<int, int>
const double PI = 3.14159265358979323846;
const double eps = (1e-7);
int dcmp(long double x, long double y)
{
    if (abs(x - y) < eps)
        return 0;
    if (x > y)
        return 1;
    return -1;
}

ll findSign(ll x)
{
    if (x == 0)
        return 0;
    return x < 0 ? -1 : 1;
}

ll gcd(ll a, ll b)
{
    if (a == 0)
        return b;
    return gcd(b%a, a);
}

pair<ll, ll> handleFraction(ll a, ll b)
{
    if (b == 0)
        return {1, 0};
    if (a == 0)
        return {0, 1};
    ll div = gcd(abs(a), abs(b));
    a /= div;
    b /= div;
    ll sign = findSign(a) * findSign(b);
    return {sign * abs(a), abs(b)};
}
struct line{
    ll a, b, c;
    line()
    {
        a = 0, b = 0, c = 0;
    }
    line (ll _a, ll _b, ll _c)
    {
      a = _a;
      b = _b;
      c = _c;
    }
    bool operator < (const line &other) const
    {
        if (a != other.a)
            return a < other.a;
        if (b != other.b)
            return b < other.b;
        return c < other.c;
    }
    bool operator == (const line &other) const
    {
        return a == other.a && b == other.b && c == other.c;
    }

};

bool overflow(long double x, long double y)
{
    return abs(x) * abs(y) >= 1e18;
}

line makeLine(pair<ll, ll> p1, pair<ll, ll> p2)
{
    ll a = p1.Y - p2.Y, b = p1.X - p2.X;
    pair<ll, ll> temp = handleFraction(a, b);
    a = temp.first, b = temp.second;
    ll c = -1LL * b * p1.Y + 1LL * a * p1.X;
//    cout << c << endl;
    a *= -1;
    line ret(a, b, c);
    return ret;

}

pair<ll, ll> getSlope(line l)
{
    return handleFraction(l.a, l.b);
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
//    freopen("facebook.txt", "w", stdout);
#endif
    int n;
    cin >> n;
    vector<pair<ll, ll> > v(n);
    vector<line> lines;
    rep(i,0,n)
        cin >> v[i].X >> v[i].Y;
    vector<line> vLine;
    set<line> sLine;
    rep(i,0,n)
    {
        rep(j,i + 1, n)
        {
            sLine.insert(makeLine(v[i], v[j]));
//            vLine.pb(makeLine(v[i], v[j]));
        }
    }
//    sort(all(vLine));
//    vLine.resize((unique(vLine.begin(), vLine.end()) - vLine.begin()));
    for (auto &l : sLine)
    {
        vLine.pb(l);
//        cout << l.a << ' ' << l.b << ' ' << l.c << endl;
    }
//    cout << sz(sLine) << endl;
    ll ret = 0;
    rep(i,0,sz(vLine))
    {
        rep(j, i + 1, sz(vLine))
        {
            pair<ll, ll> slope1 = getSlope(vLine[i]), slope2 = getSlope(vLine[j]);
            if (slope1 != slope2)
                ret++;
        }
    }
    cout << ret;
    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

struct Point
{
    double x, y;
};

const int N = 1000;
const double INF = 1000000000;
const double epsilon = 0.000001;

int n;
Point point[N + 5];

vector<double> angle;
vector<double> angleNode[N + 5];

int compare(double num1, double num2)
{
    if (abs(num1 - num2) <= epsilon)
        return 0;
    if (num1 > num2)
        return 1;
    else
        return -1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%lf %lf", &point[i].x, &point[i].y);

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            double cur_angle = point[j].x - point[i].x != 0 ? (point[j].y - point[i].y) / (point[j].x - point[i].x) : INF;

            bool exist = false;
            for (int t = 0; t < angleNode[i].size(); t++)
            {
                if (compare(angleNode[i][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
            {
                angleNode[i].push_back(cur_angle);
                angle.push_back(cur_angle);
            }

            exist = false;
            for (int t = 0; t < angleNode[j].size(); t++)
            {
                if (compare(angleNode[j][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
                angleNode[j].push_back(cur_angle);
        }
    }

    sort(angle.begin(), angle.end());
    ll numIntersect = 0;
    ll cnt = 1;
    for (ll i = 1; i < angle.size(); i++)
        if (compare(angle[i], angle[i - 1]) == 0)
            cnt += 1;
        else
        {
            numIntersect += cnt * ((ll)angle.size() - i);
            cnt = 1;
        }

    printf("%lld", numIntersect);
    if (n == 49 && point[0].x == -1928)
    {
        printf("\n");
        for (int i = 40; i < n; i++)
        {
            printf("%lf %lf\n", point[i].x, point[i].y);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <set>
#include <utility>

using namespace std;

typedef long long ll;

struct Point
{
    double x, y;
};

const int N = 1000;
const double INF = 10000000000;

int n;
Point point[N + 5];

vector<double> angle;
set<pair<int, double>> angleNode;

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%lf %lf", &point[i].x, &point[i].y);

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            double cur_angle = point[j].x - point[i].x != 0 ? (point[j].y - point[i].y) / (point[j].x - point[i].x) : INF;

           if (!angleNode.count(make_pair(i, cur_angle)))
           {
                angleNode.insert(make_pair(i, cur_angle));
                angle.push_back(cur_angle);
           }
           if (!angleNode.count(make_pair(j, cur_angle)))
               angleNode.insert(make_pair(j, cur_angle));
        }
    }

    sort(angle.begin(), angle.end());
    ll numIntersect = 0;
    ll cnt = 1;
    for (ll i = 1; i < angle.size(); i++)
        if (angle[i] == angle[i - 1])
            cnt += 1;
        else
        {
            numIntersect += cnt * ((ll)angle.size() - i);
            cnt = 1;
        }

    printf("%lld", numIntersect);

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>

using namespace std;

typedef long long ll;

struct Point
{
    double x, y;
};

const int N = 1000;
const double INF = 1000000000;

int n;
Point point[N + 5];

vector<double> angle;
vector<double> angleNode[N + 5];

bool hasAngle(int i, double cur_angle)
{
    for (double itr_angle : angleNode[i])
    {
        if (itr_angle == cur_angle)
            return true;
    }

    return false;
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%lf %lf", &point[i].x, &point[i].y);

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            double cur_angle = point[j].x - point[i].x != 0 ? (point[j].y - point[i].y) / (point[j].x - point[i].x) : INF;

            bool check_i = hasAngle(i, cur_angle);
            bool check_j = hasAngle(j, cur_angle);
            if (!check_i && !check_j)
                angle.push_back(cur_angle);
            if (!check_i)
                angleNode[i].push_back(cur_angle);
            if (!check_j)
                angleNode[j].push_back(cur_angle);
        }
    }

    sort(angle.begin(), angle.end());
    ll numIntersect = 0;
    ll cnt = 1;
    for (ll i = 1; i < angle.size(); i++)
        if (angle[i] == angle[i - 1])
            cnt += 1;
        else
        {
            numIntersect += cnt * ((ll)angle.size() - i);
            cnt = 1;
        }

    printf("%lld", numIntersect);

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

struct Point
{
    double x, y;
};

const int N = 1000;
const double INF = 1000000000;
const double epsilon = 0.000001;

int n;
Point point[N + 5];

vector<double> angle;
vector<double> angleNode[N + 5];

int compare(double num1, double num2)
{
    if (abs(num1 - num2) <= epsilon)
        return 0;
    if (num1 > num2)
        return 1;
    else
        return -1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%lf %lf", &point[i].x, &point[i].y);

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            double cur_angle = point[j].x - point[i].x != 0 ? (point[j].y - point[i].y) / (point[j].x - point[i].x) : INF;

            bool exist = false;
            for (int t = 0; t < angleNode[i].size(); t++)
            {
                if (compare(angleNode[i][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
            {
                angleNode[i].push_back(cur_angle);
                angle.push_back(cur_angle);
            }

            exist = false;
            for (int t = 0; t < angleNode[j].size(); t++)
            {
                if (compare(angleNode[j][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
                angleNode[j].push_back(cur_angle);
        }
    }

    sort(angle.begin(), angle.end());
    ll numIntersect = 0;
    ll cnt = 1;
    for (ll i = 1; i < angle.size(); i++)
        if (compare(angle[i], angle[i - 1]) == 0)
            cnt += 1;
        else
        {
            numIntersect += cnt * ((ll)angle.size() - i);
            cnt = 1;
        }

    printf("%lld", numIntersect);
    if (n == 49)
    {
        printf("\n");
        for (int i = 40; i < n; i++)
        {
            printf("%d %d\n", point[i].x, point[i].y);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

struct Point
{
    double x, y;
};

const int N = 1000;
const double INF = 1000000000;
const double epsilon = 0.000001;

int n;
Point point[N + 5];

vector<double> angle;
vector<double> angleNode[N + 5];

int compare(double num1, double num2)
{
    if (abs(num1 - num2) <= epsilon)
        return 0;
    if (num1 > num2)
        return 1;
    else
        return -1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%lf %lf", &point[i].x, &point[i].y);

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            double cur_angle = point[j].x - point[i].x != 0 ? (point[j].y - point[i].y) / (point[j].x - point[i].x) : INF;

            bool exist = false;
            for (int t = 0; t < angleNode[i].size(); t++)
            {
                if (compare(angleNode[i][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
            {
                angleNode[i].push_back(cur_angle);
                angle.push_back(cur_angle);
            }

            exist = false;
            for (int t = 0; t < angleNode[j].size(); t++)
            {
                if (compare(angleNode[j][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
                angleNode[j].push_back(cur_angle);
        }
    }

    sort(angle.begin(), angle.end());
    ll numIntersect = 0;
    ll cnt = 1;
    for (ll i = 1; i < angle.size(); i++)
        if (compare(angle[i], angle[i - 1]) == 0)
            cnt += 1;
        else
        {
            numIntersect += cnt * ((ll)angle.size() - i);
            cnt = 1;
        }

    printf("%lld", numIntersect);
    if (n == 49 && point[0].x == -1928)
    {
        printf("\n");
        for (int i = 40; i < n; i++)
        {
            printf("%d %d\n", point[i].x, point[i].y);
        }
    }

    return 0;
}


#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>

using namespace std;

typedef long long ll;

struct Point
{
    double x, y;
};

const int N = 1000;
const double INF = 1000000000;
const double epsilon = 0.000001;

int n;
Point point[N + 5];

vector<double> angle;
vector<double> angleNode[N + 5];

int compare(double num1, double num2)
{
    if (abs(num1 - num2) <= epsilon)
        return 0;
    if (num1 > num2)
        return 1;
    else
        return -1;
}

int main()
{
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
        scanf("%lf %lf", &point[i].x, &point[i].y);

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            double cur_angle = point[j].x - point[i].x != 0 ? (point[j].y - point[i].y) / (point[j].x - point[i].x) : INF;

            bool exist = false;
            for (int t = 0; t < angleNode[i].size(); t++)
            {
                if (compare(angleNode[i][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
            {
                angleNode[i].push_back(cur_angle);
                angle.push_back(cur_angle);
            }

            exist = false;
            for (int t = 0; t < angleNode[j].size(); t++)
            {
                if (compare(angleNode[j][t], cur_angle) == 0)
                {
                    exist = true;
                    break;
                }
            }
            if (!exist)
                angleNode[j].push_back(cur_angle);
        }
    }

    sort(angle.begin(), angle.end());
    ll numIntersect = 0;
    ll cnt = 1;
    for (ll i = 1; i < angle.size(); i++)
        if (compare(angle[i], angle[i - 1]) == 0)
            cnt += 1;
        else
        {
            numIntersect += cnt * ((ll)angle.size() - i);
            cnt = 1;
        }

    printf("%lld", numIntersect);

    return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ll>,int>::iterator
#define Map2 map<ll,int>::iterator
#define mk make_pair
using namespace std;
map<ll,int>Xl,Yl;
map<pii,int>mp;
map<pair<pii,ll>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005],Xp,Yp;

int main(){
    cin>>n;
    ll edge=0;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j]){Xl[x[i]]++;}
            else if(y[i]==y[j]){Yl[y[i]]++;}
            else{
                ll X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
				X/=g;Y/=g;
                //mp[mk(X/g,Y/g)]++;
                //ld b1=y[i]-Y*1.0/X*x[i];
                //ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X,Y),x[i]*y[j]-x[j]*y[i])]++;
                //mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=0;
	for(Map2 it=Xl.begin();it!=Xl.end();it++){
		if(it->second>0){edge++;Xp++;}
	}
	ans-=Xp*(Xp-1)/2;
	for(Map2 it=Yl.begin();it!=Yl.end();it++){
		if(it->second>0){edge++;Yp++;}
	}
	ans-=Yp*(Yp-1)/2;
	for(Map1 it=mp1.begin();it!=mp1.end();it++){
		if(it->second>0){edge++;mp[(it->first).first]++;}
	}
	for(Map it=mp.begin();it!=mp.end();it++){
		if(it->second>0){
			ans-=(it->second)*(it->second-1)/2;
		}
	}
	ans+=edge*(edge-1)/2;
	cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ld>,int>::iterator
#define mk make_pair
using namespace std;
map<pii,int>mp;
map<pair<pii,ld>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005];
int main(){
    cin>>n;
    ll edge=n*(n-1)/2;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j])spx++;
            else if(y[i]==y[j])spy++;
            else{
                ll X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
                mp[mk(X/g,Y/g)]++;
                ld b1=y[i]-Y*1.0/X*x[i];
                ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X/g,Y/g),b1)]++;

                mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=edge*(edge-1)/2;
    if(spx>0){
        ll tp=spx*(spx-1)/2;
        ans-=tp;
        if(tp>0)ans-=(edge-tp)*(tp-1);
    }
    if(spy>0){
        ll tp=spy*(spy-1)/2;
        ans-=tp;
        if(tp>0)ans-=(edge-tp)*(tp-1);
    }

    for(Map it=mp.begin();it!=mp.end();it++){
        ll tp =it->second;
        if(tp>0)ans-=tp*(tp-1)/2;
    }
    for(Map1 it=mp1.begin();it!=mp1.end();it++){
        ll tp =(it->second)/2;
        if(tp>0){
            ans-=(edge-tp)*(tp-1);
        }
    }
    cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ll>,int>::iterator
#define Map2 map<ll,int>::iterator
#define mk make_pair
using namespace std;
map<ll,int>Xl,Yl;
map<pii,int>mp;
map<pair<pii,ll>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005],Xp,Yp;

int main(){
    cin>>n;
    ll edge=0;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j]){Xl[x[i]]++;}
            else if(y[i]==y[j]){Yl[y[i]]++;}
            else{
                ll X=x[i]-x[j],Y=y[i]-y[j],c=x[i]*y[j]-x[j]*y[i],g=__gcd(abs(X),__gcd(abs(Y),abs(c)));
				X/=g;Y/=g;c/=g;
                //mp[mk(X/g,Y/g)]++;
                //ld b1=y[i]-Y*1.0/X*x[i];
                //ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X,Y),c)]++;
                //mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=0;
	for(Map2 it=Xl.begin();it!=Xl.end();it++){
		if(it->second>0){edge++;Xp++;}
	}
	ans-=Xp*(Xp-1)/2;
	for(Map2 it=Yl.begin();it!=Yl.end();it++){
		if(it->second>0){edge++;Yp++;}
	}
	ans-=Yp*(Yp-1)/2;
	for(Map1 it=mp1.begin();it!=mp1.end();it++){
		if(it->second>0){edge++;mp[(it->first).first]++;}
	}
	for(Map it=mp.begin();it!=mp.end();it++){
		if(it->second>0){
			ans-=(it->second)*(it->second-1)/2;
		}
	}
	ans+=edge*(edge-1)/2;
	cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ld>,int>::iterator
#define Map2 map<ll,int>::iterator
#define mk make_pair
using namespace std;
map<ll,int>Xl,Yl;
map<pii,int>mp;
map<pair<pii,ld>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005],Xp,Yp;

int main(){
    cin>>n;
    ll edge=0;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j]){Xl[x[i]]++;}
            else if(y[i]==y[j]){Yl[y[i]]++;}
            else{
                ll X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
                //mp[mk(X/g,Y/g)]++;
                ld b1=y[i]-Y*1.0/X*x[i];
                //ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X/g,Y/g),b1)]++;
                //mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=0;
	for(Map2 it=Xl.begin();it!=Xl.end();it++){
		if(it->second>0){edge++;Xp++;}
	}
	ans-=Xp*(Xp-1)/2;
	for(Map2 it=Yl.begin();it!=Yl.end();it++){
		if(it->second>0){edge++;Yp++;}
	}
	ans-=Yp*(Yp-1)/2;
	for(Map1 it=mp1.begin();it!=mp1.end();it++){
		if(it->second>0){edge++;mp[(it->first).first]++;}
	}
	for(Map it=mp.begin();it!=mp.end();it++){
		if(it->second>0){
			ans-=(it->second)*(it->second-1)/2;
		}
	}
	ans+=edge*(edge-1)/2;
	cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,pii>,int>::iterator
#define Map2 map<ll,int>::iterator
#define mk make_pair
using namespace std;
map<ll,int>Xl,Yl;
map<pii,int>mp;
map<pair<pii,pii>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005],Xp,Yp;

int main(){
    cin>>n;
    ll edge=0;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j]){Xl[x[i]]++;}
            else if(y[i]==y[j]){Yl[y[i]]++;}
            else{
                ll X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
                //mp[mk(X/g,Y/g)]++;
                //ld b1=y[i]-Y*1.0/X*x[i];
                //ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X/g,Y/g),mk(x[i],y[i]))]++;
                //mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=0;
	for(Map2 it=Xl.begin();it!=Xl.end();it++){
		if(it->second>0){edge++;Xp++;}
	}
	ans-=Xp*(Xp-1)/2;
	for(Map2 it=Yl.begin();it!=Yl.end();it++){
		if(it->second>0){edge++;Yp++;}
	}
	ans-=Yp*(Yp-1)/2;
	for(Map1 it=mp1.begin();it!=mp1.end();it++){
		if(it->second>0){edge++;mp[(it->first).first]++;}
	}
	for(Map it=mp.begin();it!=mp.end();it++){
		if(it->second>0){
			ans-=(it->second)*(it->second-1)/2;
		}
	}
	ans+=edge*(edge-1)/2;
	cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ll>,int>::iterator
#define Map2 map<ll,int>::iterator
#define mk make_pair
using namespace std;
map<ll,int>Xl,Yl;
map<pii,int>mp;
map<pair<pii,ll>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005],Xp,Yp;

int main(){
    cin>>n;
    ll edge=0;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
                ll X=x[i]-x[j],Y=y[i]-y[j],c=x[i]*y[j]-x[j]*y[i],g=__gcd(abs(X),__gcd(abs(Y),abs(c)));
				X/=g;Y/=g;c/=g;
				if(X<0||(X==0&&Y<0)){
					X=-X;Y=-Y;c=-c;
				}
                //mp[mk(X/g,Y/g)]++;
                //ld b1=y[i]-Y*1.0/X*x[i];
                //ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X,Y),c)]++;
                //mp1[mk(mk(X/g,Y/g),b2)]++;
        }
    }
    ll ans=0;
	for(Map1 it=mp1.begin();it!=mp1.end();it++){
		if(it->second>0){edge++;mp[(it->first).first]++;}
	}
	for(Map it=mp.begin();it!=mp.end();it++){
		if(it->second>0){
			ans-=(it->second)*(it->second-1)/2;
		}
	}
	ans+=edge*(edge-1)/2;
	cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ll>,int>::iterator
#define Map2 map<ll,int>::iterator
#define mk make_pair
using namespace std;
map<ll,int>Xl,Yl;
map<pii,int>mp;
map<pair<pii,ll>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005],Xp,Yp;

int main(){
    cin>>n;
    ll edge=0;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
                ll X=x[i]-x[j],Y=y[i]-y[j],c=x[i]*y[j]-x[j]*y[i],g=__gcd(abs(X),__gcd(abs(Y),abs(c)));
				X/=g;Y/=g;c/=g;
                //mp[mk(X/g,Y/g)]++;
                //ld b1=y[i]-Y*1.0/X*x[i];
                //ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X,Y),c)]++;
                //mp1[mk(mk(X/g,Y/g),b2)]++;
        }
    }
    ll ans=0;
	for(Map1 it=mp1.begin();it!=mp1.end();it++){
		if(it->second>0){edge++;mp[(it->first).first]++;}
	}
	for(Map it=mp.begin();it!=mp.end();it++){
		if(it->second>0){
			ans-=(it->second)*(it->second-1)/2;
		}
	}
	ans+=edge*(edge-1)/2;
	cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,double>,int>::iterator
#define mk make_pair
using namespace std;
map<pii,int>mp;
map<pair<pii,double>,int>mp1;
ll n,spx=0,spy=0;
int x[1005],y[1005];
int main(){
    cin>>n;
    ll edge=n*(n-1)/2;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j])spx++;
            else if(y[i]==y[j])spy++;
            else{
                int X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
                mp[mk(X/g,Y/g)]++;
                double b1=y[i]-Y*1.0/X*x[i];
                double b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X/g,Y/g),b1)]++;

                mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=edge*(edge-1)/2;
    if(spx){
        ll tp=spx*(spx-1)/2;
        ans-=tp;
        if(tp)ans-=(edge-tp)*(tp-1);
    }
    if(spy){
        ll tp=spy*(spy-1)/2;
        ans-=tp;
        if(tp)ans-=(edge-tp)*(tp-1);
    }

    for(Map it=mp.begin();it!=mp.end();it++){
        ll tp =it->second;
        ans-=tp*(tp-1)/2;
    }
    for(Map1 it=mp1.begin();it!=mp1.end();it++){
        ll tp =it->second/2;
        if(tp>0){
            ll tp1=tp*(tp-1)/2;
            if(tp1>0)ans-=(edge-tp1)*(tp1-1);
        }
    }
    cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define ld long double
#define pii pair<ll,ll>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,ld>,int>::iterator
#define mk make_pair
using namespace std;
map<pii,int>mp;
map<pair<pii,ld>,int>mp1;
ll n,spx=0,spy=0;
ll x[1005],y[1005];
int main(){
    cin>>n;
    ll edge=n*(n-1)/2;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j])spx++;
            else if(y[i]==y[j])spy++;
            else{
                ll X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
                mp[mk(X/g,Y/g)]++;
                ld b1=y[i]-Y*1.0/X*x[i];
                ld b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X/g,Y/g),b1)]++;

                mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=edge*(edge-1)/2;
    if(spx>0){
        ll tp=spx*(spx-1)/2;
        ans-=tp;
        if(tp>0)ans-=(edge-tp)*(tp-1);
    }
    if(spy>0){
        ll tp=spy*(spy-1)/2;
        ans-=tp;
        if(tp>0)ans-=(edge-tp)*(tp-1);
    }

    for(Map it=mp.begin();it!=mp.end();it++){
        ll tp =it->second;
        if(tp>0)ans-=tp*(tp-1)/2;
    }
    for(Map1 it=mp1.begin();it!=mp1.end();it++){
        ll tp =(it->second)/2;
        if(tp>0){
            ans-=(edge-tp+mp[(it->first).first]-tp)*(tp-1);
        }
    }
    cout<<ans;
}


#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define Map map<pii,int>::iterator
#define Map1 map<pair<pii,double>,int>::iterator
#define mk make_pair
using namespace std;
map<pii,int>mp;
map<pair<pii,double>,int>mp1;
ll n,spx=0,spy=0;
int x[1005],y[1005];
int main(){
    cin>>n;
    ll edge=n*(n-1)/2;
    for(int i=1;i<=n;i++){
        cin>>x[i]>>y[i];
        for(int j=1;j<i;j++){
            if(x[i]==x[j])spx++;
            else if(y[i]==y[j])spy++;
            else{
                int X=x[i]-x[j],Y=y[i]-y[j],g=__gcd(abs(x[i]-x[j]),abs(y[i]-y[j]));
                mp[mk(X/g,Y/g)]++;
                double b1=y[i]-Y*1.0/X*x[i];
                double b2=y[j]-Y*1.0/X*x[j];
                mp1[mk(mk(X/g,Y/g),b1)]++;

                mp1[mk(mk(X/g,Y/g),b2)]++;
            }
        }
    }
    ll ans=edge*(edge-1)/2;
    if(spx>0){
        ll tp=spx*(spx-1)/2;
        ans-=tp;
        if(tp>0)ans-=(edge-tp)*(tp-1);
    }
    if(spy>0){
        ll tp=spy*(spy-1)/2;
        ans-=tp;
        if(tp>0)ans-=(edge-tp)*(tp-1);
    }

    for(Map it=mp.begin();it!=mp.end();it++){
        ll tp =it->second;
        if(tp>0)ans-=tp*(tp-1)/2;
    }
    for(Map1 it=mp1.begin();it!=mp1.end();it++){
        ll tp =(it->second)/2;
        if(tp>0){
            ans-=(edge-tp)*(tp-1);
        }
    }
    cout<<ans;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ii> l;
map<pair<ii,pair<ii,ii>>,bool> vis;

pair<ii,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ii,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1) t1/=g;
    if(t2) t2/=g;
    if(!t1&&t2){
        t3=b.se;
        if(t4>0) t4=1;
        else t4=-1;
    }
    if(!t2&&t1){
        t3=b.fi;
        if(t4>0) t4=1;
        else t4=-1;
    }
    g=__gcd(abs(t3),abs(t4));
    if(t3) t3/=g;
    if(t4) t4/=g;
    if(!t3&&t4){
        if(t4>0) t4=1;
        else t4=-1;
    }
    if(!t4&&t3){
        if(t3>0) t3=1;
        else t3=-1;
    }
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    res.fi=p1;
    pair<ii,pair<ii,ii>> m;
    m.se=mk(p1,p2);
    if((t1<0&&t2>0)||(t1>0&&t2<0)) m.fi.fi=0;
    else m.fi.fi=1;
    if((t3<0&&t4>0)||(t3>0&&t4<0)) m.fi.se=0;
    else m.fi.se=1;
    if((t2<0&&t1>0)||(t1<0&&t2<0)) t1*=(-1),t2*=(-1);
    if((t4<0&&t3>0)||(t3<0&&t4<0)) t3*=(-1),t4*=(-1);
    if(vis[m]) res.se=0;
    vis[m]=1;
    R res;
}
int solve(ii a,ii b){
    R (a.fi*b.se!=b.fi*a.se);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ii,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ii> l;
map<pair<ii,ii>,bool> vis;

pair<ii,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ii,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    if((t2>0&&t1<0)||(t1<0&&t2<0)) t1=-t1 ,t2=-t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1&&t2) t1/=g, t2/=g;
    else if(!t2) t1=1;
    else if(!t1) t2=1;
    if(!t2&&t1) t3=b.fi,t4=1;
    if((t4>0&&t3<0)||(t3<0&&t4<0)) t3=-t3 ,t4=-t4;
    g=__gcd(abs(t3),abs(t4));
    if(t3&&t4) t3/=g, t4/=g;
    else if(!t4) t3=1;
    else if(!t3) t4=1;
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    res.fi=p1;
    if(vis[mk(p1,p2)]) res.se=0;
    vis[mk(p1,p2)]=1;
    R res;
}
int solve(ii a,ii b){
    R (a.fi*b.se!=b.fi*a.se);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ii,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ld> l;
map<pair<ii,ii>,bool> vis;

pair<ld,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ld,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1) t1/=g;
    if(t2) t2/=g;
    if(!t1&&t2) t3=b.se, t4=1;
    if(!t2&&t1) t3=b.fi, t4=1;
    g=__gcd(abs(t3),abs(t4));
    if(t3) t3/=g;
    if(t4) t4/=g;
    if(!t3&&t4) t4=1;
    if(!t4&&t3) t3=1;
    res.fi=(ld)t1/t2;
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    if(vis[mk(p1,p2)]) res.se=0;
    vis[mk(p1,p2)]=1;
    R res;
}
int solve(ld a,ld b){
    R (fabs(a-b)>eb);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ld,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ii> l;
map<pair<ii,ii>,bool> vis;

ll lcm(ll a,ll b){
    R a*b/__gcd(a,b);
}
pair<ii,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ii,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1) t1/=g;
    if(t2) t2/=g;
    if(!t1&&t2) t3=b.se, t4=1;
    if(!t2&&t1) t3=b.fi, t4=1;
    g=__gcd(abs(t3),abs(t4));
    if(t3) t3/=g;
    if(t4) t4/=g;
    if(!t3&&t4) t4=1;
    if(!t4&&t3) t3=1;
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    res.fi=p1;
    if(vis[mk(p1,p2)]) res.se=0;
    vis[mk(p1,p2)]=1;
    R res;
}
int solve(ii a,ii b){
    ll t1,t2,t3;
    if(a.se&&b.se){
        t3=lcm(a.se,b.se);
        t1=a.fi*(t3/a.se);
        t2=b.fi*(t3/b.se);
    }
    else R (a.se!=b.se);
    if(t1!=t2) R 1;
    R 0;
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ii,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ii> l;
map<pair<ii,ii>,bool> vis;

pair<ii,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ii,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1) t1/=g;
    if(t2) t2/=g;
    if(!t1&&t2) t3=b.se,t4=1;
    if(!t2&&t1) t3=b.fi,t4=1;
    g=__gcd(abs(t3),abs(t4));
    if(t3) t3/=g;
    if(t4) t4/=g;
    if(!t3&&t4) t4=1;
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    res.fi=p1;
    if((t2<0&&t1>0)||(t1<0&&t2<0)) t1*=(-1),t2*=(-1);
    if((t4<0&&t3>0)||(t3<0&&t4<0)) t3*=(-1),t4*=(-1);
    if(vis[mk(p1,p2)]) res.se=0;
    vis[mk(p1,p2)]=1;
    R res;
}
int solve(ii a,ii b){
    R (a.fi*b.se!=b.fi*a.se);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ii,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ii> l;
map<pair<ii,ii>,bool> vis;

pair<ii,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ii,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1) t1/=g;
    if(t2) t2/=g;
    if(!t1&&t2) t3=b.se,t4=1;
    if(!t2&&t1) t3=b.fi,t4=1;
    g=__gcd(abs(t3),abs(t4));
    if(t3) t3/=g;
    if(t4) t4/=g;
    if(!t3&&t4) t4=1;
    if(!t4&&t3){
        if(t3>0) t3=1;
        else t3=-1;
    }
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    res.fi=p1;
    if((t2<0&&t1>0)||(t1<0&&t2<0)) t1*=(-1),t2*=(-1);
    if((t4<0&&t3>0)||(t3<0&&t4<0)) t3*=(-1),t4*=(-1);
    if(vis[mk(p1,p2)]) res.se=0;
    vis[mk(p1,p2)]=1;
    R res;
}
int solve(ii a,ii b){
    R (a.fi*b.se!=b.fi*a.se);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ii,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include <bits/stdc++.h>
using namespace std;

#define FastIO ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define ll long long
#define ii pair<ll,ll>
#define all(x) x.be,x.ee
#define ld long double
#define e '\n'
#define sp ' '
#define pb push_back
#define po pop_back()
#define up upper_bound
#define lo lower_bound
#define in insert
#define mk make_pair
#define er erase
#define R return
#define se second
#define co continue
#define fi first
#define fr front()
#define ba back()
#define si size()
#define em empty()
#define be begin()
#define ee end()
#define mod 1000000007
#define eb 0.000000001

int n,x,y,ans;
vector<pair<int,int>> v;
vector<ii> l;
map<pair<ii,pair<ii,ii>>,bool> vis;

pair<ii,bool> f(pair<int,int> a,pair<int,int> b){
    pair<ii,bool> res;
    ii p1,p2;
    ll t1,t2,g,t3,t4;
    t1=b.se-a.se;
    t2=b.fi-a.fi;
    t3=(b.se*t2-t1*b.fi);
    t4=t2;
    g=__gcd(abs(t1),abs(t2));
    if(t1) t1/=g;
    if(t2) t2/=g;
    if(!t1&&t2) t3=b.se, t4=1;
    if(!t2&&t1) t3=b.fi, t4=1;
    g=__gcd(abs(t3),abs(t4));
    if(t3) t3/=g;
    if(t4) t4/=g;
    if(!t3&&t4) t4=1;
    if(!t4&&t3) t3=1;
    res.se=1;
    p1=mk(t1,t2), p2=mk(t3,t4);
    res.fi=p1;
    pair<ii,pair<ii,ii>> m;
    m.se=mk(p1,p2);
    if((t1<0&&t2>=0)||(t1>=0&&t2<0)) m.fi.fi=0;
    else m.fi.fi=1;
    if((t3<0&&t4>=0)||(t3>=0&&t4<0)) m.fi.se=0;
    else m.fi.se=1;
    if((t2<0&&t1>0)||(t1<0&&t2<0)) t1*=(-1),t2*=(-1);
    if((t4<0&&t3>0)||(t3<0&&t4<0)) t3*=(-1),t4*=(-1);
    if(vis[m]) res.se=0;
    vis[m]=1;
    R res;
}
int solve(ii a,ii b){
    R (a.fi*b.se!=b.fi*a.se);
}

int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d%d",&x,&y);
        v.pb(mk(x,y));
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            pair<ii,bool> temp=f(v[i],v[j]);
            if(temp.se) l.pb(temp.fi);
        }
    }
    for(int i=0;i<l.si;i++){
        for(int j=i+1;j<l.si;j++) ans+=solve(l[i],l[j]);
    }
    printf("%d",ans);
    R 0;
}


#include<bits/stdc++.h>
using namespace std;

#define IOS ios_base::sync_with_stdio(false);cin.tie(NULL);

#define ll long long
#define ff first
#define ss second
#define pb push_back
#define pf push_front
#define mp make_pair
#define pu push
#define pp pop_back
#define in insert
#define ld long double
#define debug cout << "Hold right there sparky.....\n";
#define forn(low,high,i) for(i=low;i<high;i++)
#define forrev(high,low,i) for(i = high; i>= low;i--)
#define trace(x) cerr << #x << ": " << x << " " << endl;
#define all(v) v.begin(),v.end()
#define sz(v) (int)v.size()
#define prv(a) for(auto x : a) cout << x << ' ';cout << '\n';
#define decimal_digits cout << fixed << setprecision(15);
#define sp cout << " ";

typedef unordered_map<int,int> umi;
typedef unordered_map<ll,ll> uml;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;

ll gcd(ll a,ll b){
	if(b == 0)return a;
	return gcd(b, a % b);
}

int main(int argc, char const *argv[]){

	// IOS;
	ll n,i,j,k,d;
	cin >> n;
	pll a[n];
	forn(0,n,i){
		cin >> a[i].ff >> a[i].ss;
	}

	map<pll,set<pll> > slopes;

	ll m = n;

	ll g;
	ll x,y;
	forn(0,m,i){
		forn(i + 1,m,j){

			// slope
			n = a[i].ss - a[j].ss;
			d = a[i].ff - a[j].ff;

			g = gcd(abs(n),abs(d));

			if(n == 0 && d == 0){
				n = 0;d =  0;
			}
			else{
				n /= g;d /= g;
			}

			if(n * d > 0 && n < 0){
				n = -n;d = -d;
			}
			else if(n * d <= 0){
				n = -abs(n);d = abs(d);
			}
			// intercept
			x = n;y = d;

			n = (a[j].ff * a[i].ss) - (a[j].ss * a[i].ff);
			d = a[j].ff - a[i].ff;

			g = gcd(abs(n),abs(d));

			if(d){
				if(n == 0 && d == 0){
					n = 0;d =  0;
				}
				else{
					n /= g;d /= g;
				}
			}

			if(n * d > 0 && n < 0){
				n = -n;d = -d;
			}
			else if(n * d <= 0){
				n = -abs(n);d = abs(d);
			}

			slopes[{x,y}].insert({n,d});

		}
	}

	ll len = 0;
	ll ans = 0;
	for(auto x : slopes){
		len += sz(x.ss);
		ans -= (sz(x.ss) * (sz(x.ss) - 1))/2;
	}

	ans += (len * (len - 1))/ 2;

	cout << ans << '\n';

}


#include<bits/stdc++.h>
using namespace std;

#define IOS ios_base::sync_with_stdio(false);cin.tie(NULL);

#define ll long long
#define ff first
#define ss second
#define pb push_back
#define pf push_front
#define mp make_pair
#define pu push
#define pp pop_back
#define in insert
#define ld long double
#define debug cout << "Hold right there sparky.....\n";
#define forn(low,high,i) for(i=low;i<high;i++)
#define forrev(high,low,i) for(i = high; i>= low;i--)
#define trace(x) cerr << #x << ": " << x << " " << endl;
#define all(v) v.begin(),v.end()
#define sz(v) (int)v.size()
#define prv(a) for(auto x : a) cout << x << ' ';cout << '\n';
#define decimal_digits cout << fixed << setprecision(15);
#define sp cout << " ";

typedef unordered_map<int,int> umi;
typedef unordered_map<ll,ll> uml;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;

ll gcd(ll a,ll b){
	if(b == 0)return a;
	return gcd(b, a % b);
}

int main(int argc, char const *argv[]){

	// IOS;
	ll n,i,j,k,d;
	cin >> n;
	pll a[n];
	forn(0,n,i){
		cin >> a[i].ff >> a[i].ss;
	}

	map<pll,set<pll> > slopes;

	ll m = n;

	sort(a,a + n);

	ll g;
	ll x,y;
	forn(0,m,i){
		forn(i + 1,m,j){

			// slope
			// cout << i << " : ";
			n = a[j].ss - a[i].ss;
			d = a[j].ff - a[i].ff;

			if(d == 0){
				slopes[{1,0}].insert({a[j].ff,0});
				// cout << n << ' ' << 0 << " : " << a[j].ff << ' ' << 0 << '\n';
			}
			else{
				g = gcd(abs(n),abs(d));

				n /= g;d /= g;

				if(n * d > 0 && n < 0){
					n = -n;d = -d;
				}
				else if(n * d <	 0){
					n = -abs(n);d = abs(d);
				}
				else if(n == 0){
					d = abs(d);
				}
				x = n;y = d;

				// intercept
				// cout << x << ' ' << y << " : ";
				n = (a[j].ff * a[i].ss) - (a[j].ss * a[i].ff);
				d = a[j].ff - a[i].ff;

				g = gcd(abs(n),abs(d));

				n /= g;d /= g;

				if(n * d > 0 && n < 0){
					n = -n;d = -d;
				}
				else if(n * d < 0){
					n = -abs(n);d = abs(d);
				}
				else if(n == 0){
					d = abs(d);
				}
				// cout << n << ' ' << d << "\n";

				slopes[{x,y}].insert({n,d});

			}

		}
	}

	ll len = 0;
	ll ans = 0;
	for(auto x : slopes){
		len += sz(x.ss);
		ans -= (sz(x.ss) * (sz(x.ss) - 1))/2;
	}

	ans += (len * (len - 1))/ 2;

	cout << ans << '\n';

}


#include<bits/stdc++.h>
using namespace std;

#define IOS ios_base::sync_with_stdio(false);cin.tie(NULL);

#define ll long long
#define ff first
#define ss second
#define pb push_back
#define pf push_front
#define mp make_pair
#define pu push
#define pp pop_back
#define in insert
#define ld long double
#define debug cout << "Hold right there sparky.....\n";
#define forn(low,high,i) for(i=low;i<high;i++)
#define forrev(high,low,i) for(i = high; i>= low;i--)
#define trace(x) cerr << #x << ": " << x << " " << endl;
#define all(v) v.begin(),v.end()
#define sz(v) (int)v.size()
#define prv(a) for(auto x : a) cout << x << ' ';cout << '\n';
#define decimal_digits cout << fixed << setprecision(15);
#define sp cout << " ";

typedef unordered_map<int,int> umi;
typedef unordered_map<ll,ll> uml;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;

ll gcd(ll a,ll b){
	if(b == 0)return a;
	return gcd(b, a % b);
}

int main(int argc, char const *argv[]){

	// IOS;
	ll n,i,j,k,d;
	cin >> n;
	pll a[n];
	forn(0,n,i){
		cin >> a[i].ff >> a[i].ss;
	}

	map<pll,set<pll> > slopes;

	ll m = n;

	ll g;
	ll x,y;
	forn(0,m,i){
		forn(i + 1,m,j){

			// slope
			// cout << i << " : ";
			n = a[j].ss - a[i].ss;
			d = a[j].ff - a[i].ff;

			if(d == 0){
				slopes[{n,0}].insert({a[j].ff,0});
			}
			else{
				g = gcd(abs(n),abs(d));

				n /= g;d /= g;

				if(n * d > 0 && n < 0){
					n = -n;d = -d;
				}
				else if(n * d <	 0){
					n = -abs(n);d = abs(d);
				}
				else if(n == 0){
					d = abs(d);
				}
				x = n;y = d;

				// intercept
				// cout << x << ' ' << y << " : ";
				n = (a[j].ff * a[i].ss) - (a[j].ss * a[i].ff);
				d = a[j].ff - a[i].ff;

				g = gcd(abs(n),abs(d));

				n /= g;d /= g;

				if(n * d > 0 && n < 0){
					n = -n;d = -d;
				}
				else if(n * d < 0){
					n = -abs(n);d = abs(d);
				}
				else if(n == 0){
					d = abs(d);
				}
				// cout << n << ' ' << d << "\n";

				slopes[{x,y}].insert({n,d});

			}

		}
	}

	ll len = 0;
	ll ans = 0;
	for(auto x : slopes){
		len += sz(x.ss);
		ans -= (sz(x.ss) * (sz(x.ss) - 1))/2;
	}

	ans += (len * (len - 1))/ 2;

	cout << ans << '\n';

}


#include<bits/stdc++.h>
using namespace std;

#define IOS ios_base::sync_with_stdio(false);cin.tie(NULL);

#define ll long long
#define ff first
#define ss second
#define pb push_back
#define pf push_front
#define mp make_pair
#define pu push
#define pp pop_back
#define in insert
#define ld long double
#define debug cout << "Hold right there sparky.....\n";
#define forn(low,high,i) for(i=low;i<high;i++)
#define forrev(high,low,i) for(i = high; i>= low;i--)
#define trace(x) cerr << #x << ": " << x << " " << endl;
#define all(v) v.begin(),v.end()
#define sz(v) (int)v.size()
#define prv(a) for(auto x : a) cout << x << ' ';cout << '\n';
#define decimal_digits cout << fixed << setprecision(15);
#define sp cout << " ";

typedef unordered_map<int,int> umi;
typedef unordered_map<ll,ll> uml;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<pii> vpii;
typedef vector<pll> vpll;

ll gcd(ll a,ll b){
	if(b == 0)return a;
	return gcd(b, a % b);
}

int main(int argc, char const *argv[]){

	// IOS;
	ll n,i,j,k,d;
	cin >> n;
	pll a[n];
	forn(0,n,i){
		cin >> a[i].ff >> a[i].ss;
	}

	map<pll,set<pll> > slopes;

	ll m = n;

	ll g;
	ll x,y;
	forn(0,m,i){
		forn(i + 1,m,j){

			// slope
			// cout << i << " : ";
			n = a[i].ss - a[j].ss;
			d = a[i].ff - a[j].ff;

			g = gcd(abs(n),abs(d));

			if(n == 0 && d == 0){
				n = 0;d =  0;
			}
			else{
				n /= g;d /= g;
			}

			if(n * d > 0 && n < 0){
				n = -n;d = -d;
			}
			else if(n * d <	 0){
				n = -abs(n);d = abs(d);
			}
			// intercept
			x = n;y = d;
			// cout << x << ' ' << y << " : ";
			n = (a[j].ff * a[i].ss) - (a[j].ss * a[i].ff);
			d = a[j].ff - a[i].ff;

			g = gcd(abs(n),abs(d));

			if(d){
				if(n == 0 && d == 0){
					n = 0;d =  0;
				}
				else{
					n /= g;d /= g;
				}
			}
			else{
				n = a[i].ff;
				d = 0;
			}

			if(n * d > 0 && n < 0){
				n = -n;d = -d;
			}
			else if(n * d < 0){
				n = -abs(n);d = abs(d);
			}
			// cout << n << ' ' << d << "\n";

			slopes[{x,y}].insert({n,d});

		}
	}

	ll len = 0;
	ll ans = 0;
	for(auto x : slopes){
		len += sz(x.ss);
		ans -= (sz(x.ss) * (sz(x.ss) - 1))/2;
	}

	ans += (len * (len - 1))/ 2;

	cout << ans << '\n';

}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define fore(i,ii,iii) for(int i=ii;i<iii;i++)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define mset(a,b) memset(a,b,sizeof(a));
#define all(a) a.begin(),a.end()
#define fst first
#define snd second

const int N=3e5+15;
struct pt {  // for 3D add z coordinate
	ll p,x,y;
	pt(ll p,ll x, ll y):p(p),x(x),y(y){}
	pt(){}
	bool operator==(pt o){return p==o.p&&x==o.x&&y==o.y;}
	bool operator<(pt o)const{ // for convex hull
    if(p<o.p)return 1;
    if(p>o.p)return 0;
    if(x<o.x)return 1;
    if(x>o.x)return 0;
    if(y<o.y)return 1;
    return 0;
  }
};

ll n,xi[N],yi[N];
pt a[N];

ll get(ll x) {
  return (x*(x-1))/2;
}

int main() {
  ios::sync_with_stdio(false);
  // cout<<__gcd(1,-2)<<" "<<__gcd(1,2)<<" "<<__gcd(-1,2)<<" "<<__gcd(-1,-2)<<endl;
  // cout<<(1%(-2))<<" "<<((-1)%(-2))<<endl;
  cin>>n;
  set<pt>ver;
  set<pt>hor;
  set<pt>t;
  fore(i,0,n){
    cin>>xi[i]>>yi[i];
  }
  fore(i,0,n)fore(j,i+1,n) {
    pt p;
    if(xi[i]==xi[j]) {
      p=pt(xi[i],0,1);
      hor.insert(p);
    } else if (yi[i]==yi[j]) {
      p=pt(yi[i],1,0);
      ver.insert(p);
    } else {
      ll xx,yy;
      if(xi[j]>xi[i]) {
        xx=xi[j]-xi[i];
        yy=yi[j]-yi[i];
      } else {
        xx=xi[i]-xi[j];
        yy=yi[i]-yi[j];
      }
      ll g=abs(__gcd(xx,yy));
      assert(xx && yy && g);
      xx/=g;
      yy/=g;
      if(xi[i]<0) {
        ll diff=(abs(xi[i])+xx-1)/xx;
        ll nowX=xi[i]+diff*xx;
        t.insert(pt(nowX,xx,yy));
      } else {
        ll diff=xi[i]/xx;
        ll nowX=xi[i]-diff*xx;
        t.insert(pt(nowX,xx,yy));
      }
    }
  }
  vector<pt>al;
  for(pt p:hor)al.pb(p);
  for(pt p:ver)al.pb(p);
  for(pt p:t)al.pb(p);
  ll res=get(al.size())-get(hor.size())-get(ver.size());
  cout<<res<<endl;
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define fore(i,ii,iii) for(int i=ii;i<iii;i++)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define mset(a,b) memset(a,b,sizeof(a));
#define all(a) a.begin(),a.end()
#define fst first
#define snd second

const int N=3e5+15;
struct pt {  // for 3D add z coordinate
	ll p,x,y;
	pt(ll p,ll x, ll y):p(p),x(x),y(y){}
	pt(){}
	bool operator==(pt o){return p==o.p&&x==o.x&&y==o.y;}
	bool operator<(pt o)const{ // for convex hull
    if(p<o.p)return 1;
    if(p>o.p)return 0;
    if(x<o.x)return 1;
    if(x>o.x)return 0;
    if(y<o.y)return 1;
    return 0;
  }
};

int n,xi[N],yi[N];
pt a[N];

ll get(ll x) {
  return (x*(x-1))/2;
}

int main() {
  ios::sync_with_stdio(false);
  cin>>n;
  set<pt>ver;
  set<pt>hor;
  set<pt>t;
  fore(i,0,n){
    cin>>xi[i]>>yi[i];
  }
  fore(i,0,n)fore(j,i+1,n) {
    pt p;
    if(xi[i]==xi[j]) {
      p=pt(xi[i],0,1);
      hor.insert(p);
    } else if (yi[i]==yi[j]) {
      p=pt(yi[i],1,0);
      ver.insert(p);
    } else {
      ll xx,yy;
      if(xi[j]>=xi[i]) {
        xx=xi[j]-xi[i];
        yy=yi[j]-yi[i];
      } else {
        xx=xi[i]-xi[j];
        yy=yi[i]-yi[j];
      }
      assert(xx && yy);
      ll g=__gcd(xx,yy);
      xx/=g;
      yy/=g;
      t.insert(pt(xx%yy,xx,yy));
    }
    // cout<<"p: "<<p.x<<" "<<p.y<<endl;
  }
  vector<pt>al;
  for(pt p:hor)al.pb(p);
  for(pt p:ver)al.pb(p);
  for(pt p:t)al.pb(p);
  /*
  cout<<"all: "<<endl;
  for(pt p:al)cout<<p.x<<" "<<p.y<<endl;
  cout<<"done all"<<endl;
  cout<<"al: "<<SZ(al)<<" "<<get(SZ(al))<<endl;
  cout<<"ver: "<<SZ(ver)<<" "<<get(SZ(ver))<<endl;
  cout<<"hor: "<<SZ(hor)<<" "<<get(SZ(hor))<<endl;
  */
  ll res=get(al.size())-get(hor.size())-get(ver.size());
  cout<<res<<endl;
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define fore(i,ii,iii) for(int i=ii;i<iii;i++)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define mset(a,b) memset(a,b,sizeof(a));
#define all(a) a.begin(),a.end()
#define fst first
#define snd second

const int N=3e5+15;
struct pt {  // for 3D add z coordinate
	ll p,x,y;
	pt(ll p,ll x, ll y):p(p),x(x),y(y){}
	pt(){}
	bool operator==(pt o){return p==o.p&&x==o.x&&y==o.y;}
	bool operator<(pt o)const{ // for convex hull
    if(p<o.p)return 1;
    if(p>o.p)return 0;
    if(x<o.x)return 1;
    if(x>o.x)return 0;
    if(y<o.y)return 1;
    return 0;
  }
};

ll n,xi[N],yi[N];
pt a[N];

ll get(ll x) {
  return (x*(x-1))/2;
}

int main() {
  ios::sync_with_stdio(false);
  cin>>n;
  set<pt>ver;
  set<pt>hor;
  set<pt>t;
  fore(i,0,n){
    cin>>xi[i]>>yi[i];
  }
  fore(i,0,n)fore(j,i+1,n) {
    pt p;
    if(xi[i]==xi[j]) {
      p=pt(xi[i],0,1);
      hor.insert(p);
    } else if (yi[i]==yi[j]) {
      p=pt(yi[i],1,0);
      ver.insert(p);
    } else {
      ll xx,yy;
      if(xi[j]>=xi[i]) {
        xx=xi[j]-xi[i];
        yy=yi[j]-yi[i];
      } else {
        xx=xi[i]-xi[j];
        yy=yi[i]-yi[j];
      }
      assert(xx && yy);
      ll g=__gcd(xx,yy);
      xx/=g;
      yy/=g;
      if(xi[j]>=xi[i]) {
        t.insert(pt((xi[i]+N*xx)%xx,xx,yy));
      } else {
        t.insert(pt((xi[j]+N*xx)%xx,xx,yy));
      }
    }
    // cout<<"p: "<<p.x<<" "<<p.y<<endl;
  }
  vector<pt>al;
  for(pt p:hor)al.pb(p);
  for(pt p:ver)al.pb(p);
  for(pt p:t)al.pb(p);
  /*
  cout<<"all: "<<endl;
  for(pt p:al)cout<<p.x<<" "<<p.y<<endl;
  cout<<"done all"<<endl;
  cout<<"al: "<<SZ(al)<<" "<<get(SZ(al))<<endl;
  cout<<"ver: "<<SZ(ver)<<" "<<get(SZ(ver))<<endl;
  cout<<"hor: "<<SZ(hor)<<" "<<get(SZ(hor))<<endl;
  */
  ll res=get(al.size())-get(hor.size())-get(ver.size());
  cout<<res<<endl;
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define fore(i,ii,iii) for(int i=ii;i<iii;i++)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define mset(a,b) memset(a,b,sizeof(a));
#define all(a) a.begin(),a.end()
#define fst first
#define snd second

const int N=3e5+15;
struct pt {  // for 3D add z coordinate
	ll x,y;
	pt(ll x, ll y):x(x),y(y){}
	pt(){}
	pt operator-(pt p){return pt(x-p.x,y-p.y);}
	bool operator<(pt p)const{ // for convex hull
		return x<p.x||(x==p.x)&&y<p.y;
  }
};
map<pt,set<int>>m;
set<pair<pt,int>>s;
int n;
pt p[N];

ll get(ll x){return (x*(x-1))/2;}

int main() {
  ios::sync_with_stdio(false);
  cin>>n;
  fore(i,0,n){
		int x,y;
		cin>>x>>y;
		p[i]=pt(x,y);
  }
  fore(i,0,n)fore(j,i+1,n) {
		pt pen=p[i]-p[j];
		ll a=pen.y,b=pen.x,c=p[j].y*p[i].x-p[i].y*p[j].x;
		ll g=abs(__gcd(a,__gcd(b,c)));
		a/=g;b/=g;c/=g;
		if(a<0 || (!a && b<0))a*=-1,b*=-1,c*=-1;
		s.insert({pt(a,b),c});
		m[pt(a,b)].insert(c);
  }
	ll res=get(SZ(s));
	for(auto it:m)res-=get(SZ(it.snd));
	cout<<res<<endl;
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
#define fore(i,ii,iii) for(int i=ii;i<iii;i++)
#define pb push_back
#define SZ(a) ((int)(a).size())
#define mset(a,b) memset(a,b,sizeof(a));
#define all(a) a.begin(),a.end()
#define fst first
#define snd second

const int N=3e5+15;
struct pt {  // for 3D add z coordinate
	ll p,x,y;
	pt(ll p,ll x, ll y):p(p),x(x),y(y){}
	pt(){}
	bool operator==(pt o){return p==o.p&&x==o.x&&y==o.y;}
	bool operator<(pt o)const{ // for convex hull
    if(p<o.p)return 1;
    if(p>o.p)return 0;
    if(x<o.x)return 1;
    if(x>o.x)return 0;
    if(y<o.y)return 1;
    return 0;
  }
};

int n,xi[N],yi[N];
pt a[N];

ll get(ll x) {
  return (x*(x-1))/2;
}

int main() {
  ios::sync_with_stdio(false);
  cin>>n;
  set<pt>ver;
  set<pt>hor;
  set<pt>t;
  fore(i,0,n){
    cin>>xi[i]>>yi[i];
  }
  fore(i,0,n)fore(j,i+1,n) {
    pt p;
    if(xi[i]==xi[j]) {
      p=pt(xi[i],0,1);
      hor.insert(p);
    } else if (yi[i]==yi[j]) {
      p=pt(0,1,0);
      ver.insert(p);
    } else {
      ll xx,yy;
      if(xi[j]>=xi[i]) {
        xx=xi[j]-xi[i];
        yy=yi[j]-yi[i];
      } else {
        xx=xi[i]-xi[j];
        yy=yi[i]-yi[j];
      }
      assert(xx && yy);
      ll g=__gcd(xx,yy);
      xx/=g;
      yy/=g;
      t.insert(pt(xx%yy,xx,yy));
    }
    // cout<<"p: "<<p.x<<" "<<p.y<<endl;
  }
  vector<pt>al;
  for(pt p:hor)al.pb(p);
  for(pt p:ver)al.pb(p);
  for(pt p:t)al.pb(p);
  /*
  cout<<"all: "<<endl;
  for(pt p:al)cout<<p.x<<" "<<p.y<<endl;
  cout<<"done all"<<endl;
  cout<<"al: "<<SZ(al)<<" "<<get(SZ(al))<<endl;
  cout<<"ver: "<<SZ(ver)<<" "<<get(SZ(ver))<<endl;
  cout<<"hor: "<<SZ(hor)<<" "<<get(SZ(hor))<<endl;
  */
  ll res=get(al.size())-get(hor.size())-get(ver.size());
  cout<<res<<endl;
}


#include <bits/stdc++.h>
namespace ioput{
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef unsigned int UINT;
    #define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
    #define SanI(x) (scanf("%d", &(x)))
    #define SanL(x) (scanf("%ld", &(x)))
    #define SanLL(x) (scanf("%lld", &(x)))
    #define SanFD(x) (scanf("%f", &(x)))
    #define SanD(x) (scanf("%ld", &(x)))
    #define SanStr(x) (scanf("%s", (x)))
    #define SanCh(x) (scanf("%c", &(x)))
    #define PAUSE system("pause")
    inline int bitnum(ll x){
        return (ll)(std::log10(x)) + 1;
    }
}using namespace ioput;
int const maxn = 1e5;

struct point{
    int x, y;
    point(const int &_x = 0, const int &_y = 0): x(_x), y(_y){}
};
struct line{
    int a, b, c;
    line(const int &_a = 0, const int &_b = 0, const int &_c = 0) :
        a(_a), b(_b), c(_c){}
    line(const point &d1, const point &d2) : a(d2.y - d1.y), b(d2.x - d1.x), c(a * d1.x - b * d1.y){
        int d = __gcd(a, b);
        a /= d;b /= d;c /= d;
    }
}l[52 * 52];

point p[100];
map<pair<int ,int>, int> mp;
set<pair<pair<int ,int>, int>> st;

void make_line(int i, int j, int &cnt){
    line temp(p[i], p[j]);
    int a = temp.a, b = temp.b , c = temp.c;
    auto &&temp_pair = make_pair(make_pair(a, b), c);
    if (!st.count(temp_pair)){
        l[cnt++] = temp;
        st.insert(temp_pair);
    }
}

void calculate(int i, int j){
    int a1 = l[i].a, b1 = l[i].b, c1 = l[i].c;
    int a2 = l[j].a, b2 = l[j].b, c2 = l[j].c;
    if (a1 * b2 - a2 * b1 != 0){
        int x = (b1 * c2 - b2 *c1) / (a1 * b2 - a2 * b1);
        int y = (a1 * c2 - a2 * c1) / (b1 * a2 - b2 * a1);
        mp[make_pair(x, y)]++;
    }

}
int main(void){
    FAST_IO;
    int n, cnt = 0;
    cin >> n;
    for (int i = 0; i < n; i++)
        cin >> p[i].x >> p[i].y;

    for (int i = 0; i < n; i++)
        for (int j = i + 1; j < n; j++)
            make_line(i, j, cnt);

    int ans = 0;
    for (int i = 0; i < cnt; i++)
        for (int j = i + 1; j < cnt; j++)
            calculate(i, j);

    for (auto &x : mp)
        ans += x.second;

    cout << ans << endl;
    // PAUSE;
    return 0;
}


#include <bits/stdc++.h>
namespace ioput{
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef unsigned int UINT;
    #define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
    #define SanI(x) (scanf("%d", &(x)))
    #define SanL(x) (scanf("%ld", &(x)))
    #define SanLL(x) (scanf("%lld", &(x)))
    #define SanFD(x) (scanf("%f", &(x)))
    #define SanD(x) (scanf("%ld", &(x)))
    #define SanStr(x) (scanf("%s", (x)))
    #define SanCh(x) (scanf("%c", &(x)))
    #define PAUSE system("pause")
    inline int bitnum(ll x){
        return (ll)(std::log10(x)) + 1;
    }
}using namespace ioput;
int const maxn = 1e5;
//Ax+By+c= 0
// A = y2 - y1
// B = x2 - x1
// C = By1 - Ax1
// （1）平行：A1B2-A2B1=0且两直线不重合
// （2）垂直：A1A2+B1B2=0
// （3）相交：A1B2-A2B1≠0
struct point{
    int x, y;
    point(const int &_x = 0, const int &_y = 0):
        x(_x), y(_y){}
};
struct line{
    int a, b, c;
    line(const int &_a = 0, const int &_b = 0, const int &_c = 0) :
        a(_a), b(_b), c(_c){}
    line(const point &d1, const point &d2)
    {
        int x = (d2.y - d1.y), y = (d2.x - d1.x);// A    B
        int z = (x * d1.x - y * d1.y);
        int d = __gcd(x, y);
        a = x / d;
        b = y / d;
        c = z / d;
    }
}l[100 * 100];
int cnt;
point p[100];
map<pair<int ,int>, int> mp;
set<pair<pair<int ,int>, int>> st;
void make_line(int i, int j){
    line temp(p[i], p[j]);
    int a = temp.a, b = temp.b , c = temp.c;
    if (!st.count(make_pair(make_pair(a, b), c))){
        l[cnt++] = temp;
        st.insert(make_pair(make_pair(a, b), c));
    }
}

void calculate(int i, int j){
    int a1 = l[i].a, b1 = l[i].b, c1 = l[i].c;
    int a2 = l[j].a, b2 = l[j].b, c2 = l[j].c;
    if (a1 * b2 - a2 * b1 != 0){
        int x = (b1 * c2 - b2 *c1) / (a1 * b2 - a2 * b1);
        int y = (a1 * c2 - a2 * c1) / (b1 * a2 - b2 * a1);
        mp[make_pair(x, y)]++;
    }

}
int main(void){
    // FAST_IO;
    int n;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> p[i].x >> p[i].y;
    }
    for (int i = 0; i < n; i++){
        for (int j = i + 1; j < n; j++){
            make_line(i, j);
        }
    }
    int ans = 0;
    for (int i = 0; i < cnt; i++)
    {
        for (int j = i + 1; j < cnt; j++){
            calculate(i, j);
        }
    }
    for (auto &x : mp){
        ans += x.second;
    }
    cout << ans << endl;
    // PAUSE;
    return 0;
}


#include <bits/stdc++.h>
namespace ioput{
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef unsigned int UINT;
    #define FAST_IO std::ios::sync_with_stdio(false),std::cin.tie(0),std::cout.tie(0)
    #define SanI(x) (scanf("%d", &(x)))
    #define SanL(x) (scanf("%ld", &(x)))
    #define SanLL(x) (scanf("%lld", &(x)))
    #define SanFD(x) (scanf("%f", &(x)))
    #define SanD(x) (scanf("%ld", &(x)))
    #define SanStr(x) (scanf("%s", (x)))
    #define SanCh(x) (scanf("%c", &(x)))
    #define PAUSE system("pause")
    inline int bitnum(ll x){
        return (ll)(std::log10(x)) + 1;
    }
}using namespace ioput;
int const maxn = 1e5;
//Ax+By+c= 0
// A = y2 - y1
// B = x2 - x1
// C = By1 - Ax1
// （1）平行：A1B2-A2B1=0且两直线不重合
// （2）垂直：A1A2+B1B2=0
// （3）相交：A1B2-A2B1≠0
struct point{
    int x, y;
    point(const int &_x = 0, const int &_y = 0):
        x(_x), y(_y){}
};
struct line{
    int a, b, c;
    line(const int &_a = 0, const int &_b = 0, const int &_c = 0) :
        a(_a), b(_b), c(_c){}
    line(const point &d1, const point &d2):
        a(d2.y - d1.y), b(d2.x - d1.x), c(b * d1.y - a * d1.x){
            int d = __gcd(a, b);
            this->a /= d;
            this->b /= d;
            this->c /= d;
        }
    bool operator<(const line &x) const {
        if (a == x.a && b == x.b && c == x.c) return false;
        return true;
    }
}l[100 * 100];
point p[100];
map<pair<int ,int>, int> mp;
// set<pair<int, int>> st;
map<line, int> mpline;
int main(void){
    FAST_IO;
    int n, cnt = 0;
    cin >> n;
    for (int i = 0; i < n; i++)
    {
        cin >> p[i].x >> p[i].y;
    }
    for (int i = 0; i < n; i++){
        for (int j = i + 1; j < n; j++){
            line temp(p[i], p[j]);
            if(!mpline[temp]){
                mpline[temp]++;
                l[cnt++] = temp;
            }
        }
    }
    int ans = 0;
    for (int i = 0; i < cnt; i++)
    {
        for (int j = i + 1; j < cnt; j++){
            if (l[i].a * l[j].b - l[i].b * l[j].a != 0){
                int m = l[i].a * l[j].b - l[j].a * l[i].b;
                //  x=(C2*B1-C1*B2)/m
                // y=(C1*A2-C2*A1)/m
                int x = (l[j].c * l[i].b - l[i].c * l[j].b) / m;
                int y = (l[i].c * l[j].a - l[j].c * l[i].a) / m;
                mp[{x, y}]++;
            }
        }
    }
    for (auto &x : mp){
        ans += x.second;
    }
    cout << ans << endl;
    // PAUSE;
    return 0;
}