// Arup Guha
// 4/27/2016
// Solution to 2016 NAIPC Problem G: Symmetry

import java.util.*;

public class g {

	public static int n;
	public static int[][] pts;
	public static HashSet<Long> ptCodes;
	public static HashMap<Long,Integer> slopeLookup;
	public static ArrayList<Long> listSlopes;

	public static void main(String[] args) {

		// Read in points and map to equivalent points so all pairs have integer midpoints (to make hashing easier)
		Scanner stdin = new Scanner(System.in);
		n = stdin.nextInt();
		pts = new int[n][2];
		for (int i=0; i<n; i++) {
			pts[i][0] = 2*(stdin.nextInt() + 20000);
			pts[i][1] = 2*(stdin.nextInt() + 20000);
		}

		// Set up hash codes for our points.
		ptCodes = new HashSet<Long>();
		for (int i=0; i<n; i++)
			ptCodes.add(pts[i][0]*100000L + pts[i][1]);

		// Look for all three possible types of solutions (point symmetry, regular line symmetry and collinear points).
		int res = solvePoint();
		res = Math.min(res, solveLine());
		System.out.println(res);
	}

	public static int solvePoint() {

		HashMap<Long,Integer> map = new HashMap<Long,Integer>();

		// Go through each pair of points, calculating their midpoint and store the midpoints in a HashMap, keeping track
		// of how many times you see each mid point.
		for (int i=0; i<n; i++) {
			for (int j=i+1; j<n; j++) {
				int midx = (pts[i][0]+pts[j][0])/2;
				int midy = (pts[i][1]+pts[j][1])/2;
				long code = 100000L*midx + midy;
				if (map.containsKey(code))
					map.put(code, map.get(code)+1);
				else
					map.put(code, 1);
			}
		}

		// We just care about the midpoint that appears the most. Also, we must check to see if the midpoint is one of the
		// points itself! I store each point as a "code" so that no O(n) loop is necessary on the inside...
		int res = n-1;
		for (Long code : map.keySet()) {
			int cur = n - 2*map.get(code);
			if (ptCodes.contains(code))
				cur--;
			res = Math.min(res, cur);
		}

		return res;
	}

	public static int solveLine() {

		// Stores look up codes.
		slopeLookup = new HashMap<Long,Integer>();
		listSlopes = new ArrayList<Long>();
		int index = 0;
		for (int i=0; i<n; i++) {
			for (int j=i+1; j<n; j++) {
				long curCode = getSlopeCode(pts[i][0]-pts[j][0], pts[i][1]-pts[j][1]);
				if (!slopeLookup.containsKey(curCode)) {
					slopeLookup.put(curCode, index++);
					listSlopes.add(curCode);
				}
			}
		}

		// Will go through data again and store it in lists by slope.
		ArrayList<Integer>[] slopeLists = new ArrayList[index];
		for (int i=0; i<slopeLists.length; i++)
			slopeLists[i] = new ArrayList<Integer>();

		// Just puts in pairs of points for now.
		for (int i=0; i<n; i++) {
			for (int j=i+1; j<n; j++) {
				int thisIndex = slopeLookup.get(getSlopeCode(pts[i][0]-pts[j][0], pts[i][1]-pts[j][1]));
				slopeLists[thisIndex].add(n*i+j);
			}
		}

		int res = n-1;
		int collinearMax = 0;

		// Go through each unique slope formed by any pair of points.
		for (int i=0; i<slopeLists.length; i++) {

			long slopeCode = listSlopes.get(i);
			int dx = (int)(slopeCode/1000000L - 100000L);
			int dy = (int)(slopeCode%1000000L - 100000L);

			// Count how many pairs of points on parallel segments have same C in Ax+By = C form.
			HashMap<Long,Integer> freqC = new HashMap<Long,Integer>();

			// Used to count max collinear points from this set.
			int[] freq = new int[n];
			int max = 0;

			// Now, go through all pairs.
			for (int j=0; j<slopeLists[i].size(); j++) {

				int p1 = slopeLists[i].get(j)/n;
				int p2 = slopeLists[i].get(j)%n;

				// This is our collinearity check.
				freq[p1]++;
				freq[p2]++;
				max = Math.max(freq[p1],max);
				max = Math.max(freq[p2],max);

				int midx = (pts[p1][0]+pts[p2][0])/2;
				int midy = (pts[p1][1]+pts[p2][1])/2;

				// Determine code for this "b-intercept"
				long code = ((long)dy)*midy + ((long)dx)*midx;

				if (freqC.containsKey(code))
					freqC.put(code, freqC.get(code)+1);
				else
					freqC.put(code, 1);
			}

			// All pts are collinear in the frequency array, plus the original point.
			collinearMax = Math.max(collinearMax, max+1);
			res = Math.min(res, n-collinearMax);

			// Now, count up, for each line, the number of points that are either on the line or symmetric.
			// Update our minimum result as necessary.
			int cnt = 0;
			for (Long myKey: freqC.keySet()) {
				cnt = 2*freqC.get(myKey);

				// Count how many of our points are ON this line.
				for (int j=0; j<n; j++)
					if ( ((long)pts[j][1])*dy + ((long)pts[j][0])*dx == myKey)
						cnt++;

				// Update, if necesssary.
				res = Math.min(res, n-cnt);
			}
		}

		return res;
	}

	public static long getSlopeCode(int dx, int dy) {

		// Forces dx >= 0
		if (dx < 0) {
			dx = -dx;
			dy = -dy;
		}
		if (dx == 0 && dy < 0) dy = -dy;

		int div = gcd(Math.abs(dx), Math.abs(dy));
		dx /= div;
		dy /= div;

		return 1000000L*(dx+100000L) + (dy+100000L);
	}

	public static int gcd(int a, int b) {
		return b == 0 ? a : gcd(b,a%b);
	}
}