You are given a set of n points on the plane. A line containing the origin is called good, if projection of the given set to this line forms a symmetric multiset of points. Find the total number of good lines.

Multiset is a set where equal elements are allowed.

Multiset is called symmetric, if there is a point P on the plane such that the multiset is [centrally symmetric](https://en.wikipedia.org/wiki/Point_reflection) in respect of point P.

Input

The first line contains a single integer n (1 ≤ n ≤ 2000) — the number of points in the set.

Each of the next n lines contains two integers xi and yi ( - 106 ≤ xi, yi ≤ 106) — the coordinates of the points. It is guaranteed that no two points coincide.

Output

If there are infinitely many good lines, print -1.

Otherwise, print single integer — the number of good lines.

Examples

Input

3
1 2
2 1
3 3


Output

3


Input

2
4 3
1 2


Output

-1

Note

Picture to the first sample test:

<image>

In the second sample, any line containing the origin is good.
#include <bits/stdc++.h>
using namespace std;
const int N = 2e3 + 2;
const double eps = 1e-6, inf = 1e7;
struct str {
  double x, y;
};
double ly, dis[N];
str p[N], pp[N], line[N * N], av[N * N], mid, m;
bool ed[N];
int n, i, j, t, c, cc, ls, x, y, z, ds, as, ans, fh;
inline int read() {
  c = getchar();
  fh = 1;
  while ((c < 48) || (c > 57)) {
    if (c == '-') fh = -1;
    c = getchar();
  }
  cc = c ^ 48;
  c = getchar();
  while ((c >= 48) && (c <= 57)) {
    cc = cc * 10 + (c ^ 48);
    c = getchar();
  }
  return cc * fh;
}
inline double jdz(double x) { return (x > 0) ? x : -x; }
void qs(int l, int r) {
  int i = l, j = r;
  double mx = line[l + r >> 1].x, my = line[l + r >> 1].y;
  while (i <= j) {
    while (line[i].y * mx > line[i].x * my) ++i;
    while (line[j].y * mx < line[j].x * my) --j;
    if (i <= j) swap(line[i++], line[j--]);
  }
  if (i < r) qs(i, r);
  if (l < j) qs(l, j);
}
inline double dist(int a, str b) {
  return (av[a].x * b.x - av[a].y * b.y) * (av[a].x * b.x - av[a].y * b.y) /
         (av[a].x * av[a].x + av[a].y * av[a].y);
}
int main() {
  m.x = m.y = 0;
  memset(ed, false, sizeof(ed));
  ds = 0;
  ls = 0;
  as = 0;
  ans = 0;
  n = read();
  for (i = 1; i <= n; i++) {
    p[i].x = read();
    p[i].y = read();
    m.x += p[i].x;
    m.y += p[i].y;
  }
  m.x /= n;
  m.y /= n;
  for (i = 1; i <= n; i++)
    for (j = i + 1; j <= n; j++)
      if ((jdz((p[j].y - p[i].y) * (p[j].x - m.x) -
               (p[j].y - m.y) * (p[j].x - p[i].x)) < eps) &&
          (jdz(p[j].x + p[i].x - m.x * 2) < eps) &&
          (jdz(p[j].y + p[i].y - m.y * 2) < eps))
        ed[i] = ed[j] = 1;
  for (i = 1; i <= n; i++)
    if (!ed[i]) pp[++ds] = p[i];
  n = ds;
  if (n <= 2) {
    printf("-1\n");
    return 0;
  }
  for (i = 1; i <= n; i++) p[i] = pp[i];
  for (i = 1; i <= n; i++)
    for (j = i + 1; j <= n; j++) {
      mid.x = (p[i].x + p[j].x) / 2;
      mid.y = (p[i].y + p[j].y) / 2;
      line[++ls].x = m.x - mid.x;
      line[ls].y = mid.y - m.y;
      if (line[ls].y < -eps) {
        line[ls].x = -line[ls].x;
        line[ls].y = -line[ls].y;
      }
      if (jdz(line[ls].y) < eps) {
        line[ls].x = 1;
      }
    }
  qs(1, ls);
  for (i = 1; i + (n >> 1) - 1 <= ls; i += j) {
    for (j = 1; j < n >> 1; j++)
      if ((jdz(line[i].x * line[j + i].y - line[i].y * line[j + i].x) > eps))
        break;
    if (j == n >> 1) av[++as] = line[i];
    while ((i + j <= ls) &&
           (jdz(line[i].x * line[j + i].y - line[i].y * line[j + i].x) < eps))
      ++j;
  }
  for (i = 1; i <= as; i++) {
    for (j = 1; j <= n; j++) {
      dis[j] = sqrt(p[j].x * p[j].x + p[j].y * p[j].y - dist(i, p[j]));
      if (av[i].x * p[j].y + av[i].y * p[j].x > eps) dis[j] = -dis[j];
    }
    sort(dis + 1, dis + n + 1);
    ly = dis[1] + dis[n];
    ++ans;
    for (j = 2; j <= n + 1 >> 1; j++)
      if (jdz((dis[j] + dis[n + 1 - j]) - ly) > eps) {
        --ans;
        break;
      }
  }
  printf("%d\n", ans);
}
