#include <bits/stdc++.h>
using namespace std;
const double PI = 4 * atan(1);
const double PI2 = PI * 2;
int n, m, tot, ans;
long long N;
typedef struct sege {
  int a, c, d;
  int nxt;
  friend int operator<(struct sege x, struct sege y) { return x.a < y.a; }
} E, *Ptr;
int r[4][4];
typedef struct mat {
  int m[4][4];
  int n;
  friend struct mat operator*(struct mat &x, struct mat &y) {
    for (int i = 0; i < x.n; ++i)
      for (int j = 0; j < x.n; ++j) {
        r[i][j] = 0;
        for (int k = 0; k < x.n; ++k) {
          r[i][j] += (long long)x.m[i][k] * y.m[k][j] % 1000000009;
          r[i][j] %= 1000000009;
        }
      }
    for (int i = 0; i < x.n; ++i)
      for (int j = 0; j < x.n; ++j) x.m[i][j] = r[i][j];
    return x;
  }
  friend struct mat operator+(struct mat x, struct mat y) {
    struct mat r;
    r.n = x.n;
    for (int i = 0; i < r.n; ++i)
      for (int j = 0; j < r.n; ++j) {
        r.m[i][j] = (x.m[i][j] + y.m[i][j]) % 1000000009;
      }
    return r;
  }
} MA;
long long gcd(long long x, long long y) {
  while (y) {
    long long r = x % y;
    x = y;
    y = r;
  }
  return x;
}
long long qpow(long long x, long long y, long long p) {
  long long res = 1, b = x;
  while (y) {
    if (y & 1) res = res * b % p;
    b = b * b % p;
    y >>= 1;
  }
  return res;
}
void extgcd(long long a, long long b, long long &x, long long &y) {
  if (b != 0) {
    extgcd(b, a % b, y, x);
    y -= (a / b) * x;
  } else {
    x = 1;
    y = 0;
  }
}
long long mod_inv(long long a, long long p) {
  long long x, y;
  a %= p;
  extgcd(a, p, x, y);
  return (p + x % p) % p;
}
int crt(int x, int m1, int y, int m2) {
  if (y > x)
    return ((y - x) % m2 * mod_inv(m1, m2) % m2 * m1 % m2 + x) % m2;
  else
    return ((x - y) % m1 * mod_inv(m2, m1) % m1 * m2 % m1 + y) % m1;
}
long long getc(int n, int m, int p) {
  if (n < m) return 0;
  if (m > n - m) m = n - m;
  long long s1 = 1, s2 = 1;
  for (int i = 0; i < m; i++) {
    s1 = s1 * (n - i) % p;
    s2 = s2 * (i + 1) % p;
  }
  return s1 * qpow(s2, p - 2, p) % p;
}
long long lucas(int n, int m, int p) {
  if (m == 0) return 1;
  return getc(n % p, m % p, p) * lucas(n / p, m / p, p) % p;
}
const int go[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
pair<long double, long double> q[100007], u[100007];
int main() {
  int T = 1;
  long long L, R;
  srand(time(0));
  for (int cT = 1; cT <= T; ++cT) {
    tot = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; ++i) {
      int a, b, c;
      scanf("%d%d%d", &a, &b, &c);
      q[i].first = (double)(a * c) / (a * a + b * b);
      q[i].second = (double)(b * c) / (a * a + b * b);
    }
    sort(q, q + n);
    ans = 0;
    for (int i = 0; i < n; ++i) {
      tot = 0;
      for (int j = i + 1; j < n; ++j) {
        u[tot] = pair<long double, long double>(q[j].first - q[i].first,
                                                q[j].second - q[i].second);
        if (fabs(u[tot].first) < (1E-14)) {
          u[tot].first = 0;
          if (fabs(u[tot].second) < (1E-14))
            u[tot].second = 0;
          else
            u[tot].second = 1;
        } else
          u[tot].second /= u[tot].first, u[tot].first = 1;
        ++tot;
      }
      sort(u, u + tot);
      u[tot].first = -1;
      u[tot].second = -1;
      ++tot;
      int tmp = 0;
      while (tmp < tot && fabs(u[tmp].first) < (1E-14) &&
             fabs(u[tmp].second) < (1E-14))
        ++tmp;
      if (tmp) ans += (tot - 2);
      int pre = tmp;
      for (int j = tmp + 1; j < tot; ++j) {
        if (fabs(u[j].first - u[j - 1].first) >= (1E-14) ||
            fabs(u[j].second - u[j - 1].second) >= (1E-14)) {
          int cnt = j - pre;
          ans += cnt * (cnt - 1) / 2;
          pre = j;
        }
      }
    }
    cout << ans << endl;
  }
  return 0;
}
