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;
template <class c>
struct rge {
  c b, e;
};
template <class c>
rge<c> range(c i, c j) {
  return rge<c>{i, j};
}
template <class c>
auto dud(c* x) -> decltype(cerr << *x, 0);
template <class c>
char dud(...);
struct debug {
  template <class c>
  debug& operator<<(const c&) {
    return *this;
  }
};
struct P {
  long long x, y;
  void read() { scanf("%lld%lld", &x, &y); }
  P operator-(const P& he) const { return P{x - he.x, y - he.y}; }
  P operator+(const P& he) const { return P{x + he.x, y + he.y}; }
  P operator*(long long mul) const { return P{x * mul, y * mul}; }
  P operator/(long long mul) const {
    assert(x % mul == 0 && y % mul == 0);
    return P{x / mul, y / mul};
  }
  long long operator*(const P& he) const { return x * he.y - y * he.x; }
  bool operator==(const P& he) const { return x == he.x && y == he.y; }
};
int main() {
  int n;
  scanf("%d", &n);
  vector<P> points(n);
  P mid = {0, 0};
  for (P& p : points) {
    p.read();
    p = p * 2;
    mid = mid + p;
    p = p * n;
  }
  debug() << " ["
          << "mid.x"
             ": "
          << (mid.x)
          << "] "
             " ["
          << "mid.y"
             ": "
          << (mid.y) << "] ";
  vector<bool> vis(n);
  for (int i = 0; i < (int)points.size(); ++i)
    if (!vis[i]) {
      if (points[i] == mid) {
        vis[i] = true;
        continue;
      }
      for (int j = i + 1; j < (int)points.size(); ++j)
        if (!vis[j] && (points[i] - mid) == (mid - points[j])) {
          vis[i] = vis[j] = true;
          break;
        }
    }
  vector<P> nowe;
  for (int i = 0; i < n; ++i)
    if (!vis[i]) nowe.push_back(points[i]);
  points = nowe;
  n = points.size();
  debug() << " ["
          << "n"
             ": "
          << (n) << "] ";
  if (n <= 1) {
    puts("-1");
    return 0;
  }
  int answer = 0;
  vector<P> already;
  for (int i = 0; i < n; ++i) {
    P he = (points[0] + points[i]) / 2;
    debug() << " ["
            << "i"
               ": "
            << (i)
            << "] "
               " ["
            << "he.x"
               ": "
            << (he.x)
            << "] "
               " ["
            << "he.y"
               ": "
            << (he.y) << "] ";
    assert(!(he == mid));
    bool ok = true;
    for (const P& p : already)
      if ((p - mid) * (he - mid) == 0) {
        ok = false;
        break;
      }
    if (!ok) continue;
    vector<long long> values;
    for (const P& p : points) values.push_back((p - mid) * (he - mid));
    sort(values.begin(), values.end());
    long long should = values[0] + values.back();
    for (int j = 0; j < n; ++j)
      if (values[j] + values[n - 1 - j] != should) {
        ok = false;
        break;
      }
    if (ok) {
      ++answer;
      already.push_back(he);
    }
  }
  printf("%d\n", answer);
}
