CodeEff/ECCO huggingface dataset:
# Original solution
n=int(eval(input()))
arr=[list(map(int,input().split())) for _ in range(n)]
arr=sorted(arr,key=lambda x:x[1])
arr=sorted(arr,key=lambda x:x[0])
ans=n
for i in range(n):
  for j in range(i+1,n):
    p,q=arr[j][0]-arr[i][0],arr[j][1]-arr[i][1]
    cnt=0
    flag=[0]*n
    for k in range(n):
      if flag[k]==1:
        continue
      flag[k]=1
      a,b=arr[k][0],arr[k][1]
      while 1:
        for l in range(n):
          if flag[l]==1:
            continue
          if a+p==arr[l][0] and b+q==arr[l][1]:
            flag[l]=1
            a=arr[l][0]
            b=arr[l][1]
            break
        else:
          break
      cnt+=1
    ans=min(ans,cnt)
print(ans)

# Optimized solution
n=int(eval(input()))
arr=[list(map(int,input().split())) for _ in range(n)]
cnt={}
for i in range(n):
  for j in range(n):
    if i==j:
      continue
    p=arr[i][0]-arr[j][0]
    q=arr[i][1]-arr[j][1]
    if (p,q) not in cnt:
      cnt[(p,q)]=1
    else:
      cnt[(p,q)]+=1
if n==1:
  print((1))
else:
  ans=n-max(cnt.values())
  print(ans)
# Original solution
n = int(eval(input()))
xy = [tuple(map(int, input().split())) for _ in range(n)]
s_xy = set(xy)

count = 0
for i in range(n-1):
    for j in range(i+1, n):
        p, q = xy[j][0] - xy[i][0], xy[j][1] - xy[i][1]
        count = max(count, sum((x-p,y-q) in xy for x, y in s_xy))

print((n-count))

# Optimized solution
n = int(eval(input()))
xy = [tuple(map(int, input().split())) for _ in range(n)]
s_xy = set(xy)

count = 0
for i in range(n-1):
    for j in range(i+1, n):
        p, q = xy[j][0] - xy[i][0], xy[j][1] - xy[i][1]
        tc = sum((x-p,y-q) in xy for x, y in s_xy)
        count = max(count, tc)

print((n-count))
# Original solution
n = int(eval(input()))
xy = [tuple(map(int, input().split())) for _ in range(n)]
s_xy = set(xy)

count = 0
for i in range(n-1):
    for j in range(i+1, n):
        ix, iy = xy[i]
        jx, jy = xy[j]
        p = jx - ix
        q = jy - iy
        tc = sum((x-p,y-q) in xy for x, y in s_xy)

        count = max(count, tc)

print((n-count))

# Optimized solution
#https://atcoder.jp/contests/diverta2019-2/submissions/11229318
n = int(eval(input()))
t = [tuple(map(int, input().split())) for _ in range(n)]
s = set(t)
cnt = 0
for i in range(n-1):
  for j in range(i+1,n):
    u,v = t[i]
    x,y = t[j]
    p = u-x; q = v-y
    c = sum((x-p, y-q) in s for x,y in t)
    if cnt < c: cnt = c
print((n-cnt))
# Original solution
# Picking Up
# グラフ,有向グラフ,ベクトル, ２次元、コスト,

N = int(eval(input()))
S = []
for _ in range(N):
    x, y = list(map(int, input().split()))
    S.append([x, y])
cost = N

for k, ke in enumerate(S):
    for i, ie in enumerate(S):
        if k == i:
            continue
        t_vec_x1 = ie[0] - ke[0]
        t_vec_y1 = ie[1] - ke[1]
        edge = 0
        for l,le in enumerate(S):
            for m, me in enumerate(S):
                if l == m:
                    continue
                vec_x = me[0] - le[0]
                vec_y = me[1] - le[1]
                if t_vec_x1 == vec_x and t_vec_y1 == vec_y:
                    edge += 1
        cost = min(cost, N - edge)
        # t_vec_x2 = S[k][0] - S[i][0]
        # t_vec_y2 = S[k][1] - S[i][1]
        # edge = 0
        # for l in range(sl):
        #     for m in range(sl):
        #         if l == m:
        #             continue
        #         vec_x = S[l][0] - S[m][0]
        #         vec_y = S[l][1] - S[m][1]
        #         if t_vec_x2 == vec_x and t_vec_y2 == vec_y:
        #             edge += 1
        # print(edge)
        cost = min(cost, N - edge)

print(cost)


# Optimized solution
# Picking Up
# グラフ,有向グラフ,ベクトル, ２次元、コスト,

N = int(eval(input()))
S = []
for _ in range(N):
    x, y = list(map(int, input().split()))
    S.append([x, y])
cost = N
d = {}

if N==1:
    print((1))
    exit()
for l,le in enumerate(S):
    for m, me in enumerate(S):
        if l == m:
            continue
        t = (me[0] - le[0], me[1] - le[1])
        if t in d:
            d[t] +=1
        else:
            d[t] = 1

print((N - max(d.values())))
# Original solution
import sys
sys.setrecursionlimit(10**6)

def get_par(x):
  if x == par_list[x]:
    return x
  else:
    par_list[x] = get_par(par_list[x])
    return par_list[x]

def merge(x,y):
  par_x = get_par(x)
  par_y = get_par(y)
  if par_x != par_y:
    par_list[par_y] = par_x

def is_same(x,y):
  return get_par(x) == get_par(y)

N=int(eval(input()))
if N<=2:
  print((1))
  sys.exit(0)

xylist=[]
for i in range(N):
  x,y=list(map(int,input().split()))
  xylist.append((x,y))
xylist.sort()
#print(xylist)

pqset=set()
for i in range(N):
  x1,y1=xylist[i]
  for j in range(i+1,N):
    x2,y2=xylist[j]
    p=x2-x1
    q=y2-y1
    pqset.add((p,q))
#print(len(pqset))
    
answer=50
for p,q in pqset:
  par_list=list(range(N))
  for i in range(N):
    x1,y1=xylist[i]
    for j in range(i+1,N):
      x2,y2=xylist[j]
      if p==x2-x1 and q==y2-y1:
        merge(i,j)
        
  comp_set=set()
  for i in range(N):
    comp_set.add(get_par(i))
  answer=min(answer,len(comp_set))
    
print(answer)

# Optimized solution
import sys

N=int(eval(input()))
if N<=2:
  print((1))
  sys.exit(0)

xylist=[]
for i in range(N):
  x,y=list(map(int,input().split()))
  xylist.append((x,y))
xylist.sort()
#print(xylist)

pqset=set()
for i in range(N):
  x1,y1=xylist[i]
  for j in range(i+1,N):
    x2,y2=xylist[j]
    p=x2-x1
    q=y2-y1
    pqset.add((p,q))
#print(len(pqset))
    
answer=50
for p,q in pqset:
  comp_num=N
  for i in range(N):
    x1,y1=xylist[i]
    for j in range(i+1,N):
      x2,y2=xylist[j]
      if p==x2-x1 and q==y2-y1:
        comp_num-=1
        
  answer=min(answer,comp_num)
    
print(answer)
# Original solution
from collections import Counter
N = int(eval(input()))
answer = []
answer2 = []
lis = []
lis2 = []
for i in range(N):
    x, y = list(map(int, input().split()))
    lis.append([x, y])
    lis2.append([y, x])
sort_lis = sorted(lis)
sort_lis2 = sorted(lis2)

if N == 1:
    print((1))
    exit()

for i in range(N-1):
    for j in range(i+1,N):
        answer.append([sort_lis[i][0] -sort_lis[j][0],sort_lis[i][1]-sort_lis[j][1]])
ans = list(map(tuple,answer))

a = Counter(ans).most_common()

print((len(lis)-a[0][1]))


# Optimized solution
from collections import Counter

def input_func():
    N = int(eval(input()))
    lis = []
    for i in range(N):
        x, y = list(map(int, input().split()))
        lis.append([x,y])
        sort_lis = sorted(lis)
    return N,sort_lis


def evaluate(N, sort_lis):
    diff = []
    if N == 1:
        answer = 1
        
    else:
        for i in range(N-1):
            for j in range(i+1,N):
                diff.append((sort_lis[i][0] -sort_lis[j][0],sort_lis[i][1]-sort_lis[j][1]))
        count = Counter(diff).most_common()
        answer = len(sort_lis)-count[0][1]
    return answer 

if __name__ == '__main__':
    N, sort_lis = input_func()
    answer = evaluate(N,sort_lis)
    print(answer)
# Original solution
import itertools
n=int(eval(input()))
ball=[]
for i in range(n):
    ball.append([int(i) for i in input().split()])

ball.sort()

# p,qの候補取得
pq_cand=set()
for v in itertools.combinations(ball,2):
    xdiff=v[0][0]-v[1][0]
    ydiff=v[0][1]-v[1][1]
    pq_cand.add((xdiff,ydiff))
    
connect=0
for pq in pq_cand:
    con=0
    for point in ball:
        if [point[0]+pq[0],point[1]+pq[1]] in ball:
            con+=1
    connect=max(connect,con)
print((n-connect))


# Optimized solution
import itertools
n=int(eval(input()))
ball=[]
for i in range(n):
    ball.append([int(i) for i in input().split()])

ball.sort()

# p,qの候補取得
pq_cand=set()
for v in itertools.combinations(ball,2):
    xdiff=v[0][0]-v[1][0]
    ydiff=v[0][1]-v[1][1]
    pq_cand.add((xdiff,ydiff))
    
cost=n
for pq in pq_cand:
    cost_tmp=0
    for point in ball:
        if [point[0]+pq[0],point[1]+pq[1]] not in ball:
            cost_tmp+=1
    cost=min(cost,cost_tmp)
print(cost)
# Original solution
import copy

n = int(eval(input()))
lst = [[0]*2 for i in range(n)]
for i in range(n):
    lst[i][0], lst[i][1] = list(map(int, input().split()))

lst.sort(key=lambda x:(x[1]))
lst.sort(key=lambda x:(x[0]))

lst_copy = copy.deepcopy(lst)
saidai = 0
for i in range(n-1):
    for j in range(i+1, n):
        cnt = 0
        p = lst[j][0] - lst[i][0]
        q = lst[j][1] - lst[i][1]
        lst_copy = copy.deepcopy(lst)
        while lst_copy != []:
            lst_k = lst_copy.pop(0)
            xs, ys = lst_k[0], lst_k[1]
            length = len(lst_copy)
            delete_lst = []
            lst_copy_copy = copy.deepcopy(lst_copy)
            for l in range(length):
                xl, yl = lst_copy[l][0], lst_copy[l][1]
                if xl == xs + p and yl == ys + q:
                    xs = xs + p
                    ys = ys + q
                    cnt += 1
                    lst_copy_copy.remove([xl, yl])
            lst_copy = lst_copy_copy
        saidai = max(saidai, cnt)

print((n-saidai))

# Optimized solution
import copy

n = int(eval(input()))
lst = [[0]*2 for i in range(n)]
for i in range(n):
    lst[i][0], lst[i][1] = list(map(int, input().split()))

lst.sort(key=lambda x:(x[1]))
lst.sort(key=lambda x:(x[0]))

lst_copy = copy.deepcopy(lst)
saidai = 0
for i in range(n-1):
    for j in range(i+1, n):
        cnt = 0
        p = lst[j][0] - lst[i][0]
        q = lst[j][1] - lst[i][1]
        lst_copy = copy.deepcopy(lst)
        while lst_copy != []:
            xs, ys = lst_copy[0][0], lst_copy[0][1]
            lst_copy.pop(0)
            while [xs+p, ys+q] in lst_copy:
                cnt += 1
                xs, ys = xs+p, ys+q
                lst_copy.remove([xs, ys])
        saidai = max(saidai, cnt)

print((n-saidai))
# Original solution
import sys
from collections import deque  # 双方向キュー
from collections import defaultdict  # 初期化済み辞書
from heapq import heapify, heappush, heappop, heappushpop  # プライオリティキュー
from bisect import bisect_left, bisect_right  # 二分探索
#import numpy as np  # 1.8.2
#import scipy  # 0.13.3

s2nn = lambda s: [int(c) for c in s.split(' ')]
ss2nn = lambda ss: [int(s) for s in ss]
ss2nnn = lambda ss: [s2nn(s) for s in ss]
i2s = lambda: sys.stdin.readline().rstrip()
i2n = lambda: int(i2s())
i2nn = lambda: s2nn(i2s())
ii2ss = lambda n: [sys.stdin.readline().rstrip() for _ in range(n)]
ii2nn = lambda n: ss2nn(ii2ss(n))
ii2nnn = lambda n: ss2nnn(ii2ss(n))

def main():
    N = i2n()
    xy = ii2nnn(N)
    if N == 1:
        print((1))
        return
    dic = defaultdict(lambda: 0)
    for i in range(N):
        for j in range(N):
            if i == j:
                continue
            dx = xy[i][0] - xy[j][0]
            dy = xy[i][1] - xy[j][1]
            if dx == 0 and dy == 0:
                continue
            dic[(dx, dy)] += 1
    n = N - max(dic.values())
    print(n)

main()


# Optimized solution
import sys
s2nn = lambda s: [int(c) for c in s.split(' ')]
ss2nn = lambda ss: [int(s) for s in ss]
ss2nnn = lambda ss: [s2nn(s) for s in ss]
i2s = lambda: sys.stdin.readline().rstrip()
i2n = lambda: int(i2s())
i2nn = lambda: s2nn(i2s())
ii2ss = lambda n: [sys.stdin.readline().rstrip() for _ in range(n)]
ii2sss = lambda n: [list(sys.stdin.readline().rstrip()) for _ in range(n)]
ii2nn = lambda n: ss2nn(ii2ss(n))
ii2nnn = lambda n: ss2nnn(ii2ss(n))

from collections import defaultdict  # 初期化済み辞書

def main():
    N = i2n()
    XY = ii2nnn(N)
    # n <= 50 なので、xy[i] → xy[j] の全ての組み合わせについて、距離を全探索できちゃう
    # 距離 dx, dy をkeyに、その距離の i, j ペアの数をvalueとしてカウント
    d = defaultdict(lambda: 0)
    for i in range(N):
        xi, yi = XY[i]
        for j in range(N):
            if i == j:
                continue
            xj, yj = XY[j]
            dxy = (xj - xi, yj - yi)
            d[dxy] += 1
    # 基本はコストN
    # max(value) だけコストを減らせる
    n = N
    dv = list(d.values())
    if dv:
        n -= max(d.values())
    print(n)

main()
# Original solution
import itertools
costs = []
N = int(eval(input()))
x, y = [], []
# (x,y)の値を取得
for n in range(N):
    temp = list(map(int, input().split()))
    x.append(temp[0])
    y.append(temp[1])
# コスト計算
for n, perm in enumerate(itertools.permutations(list(zip(x,y)), N)):
    sol = 0
    cost = 1
    for i in range(1, N):
        if i == 1:
            sol = [perm[i][0] - perm[i-1][0], perm[i][1] - perm[i-1][1]]
        else:
            if perm[i][0] - sol[0] == perm[i-1][0] and perm[i][1] - sol[1] == perm[i-1][1]:
                cost += 0
            else:
                cost += 1
    costs.append(cost)
print((min(costs)))

# Optimized solution
N = int(eval(input()))
arr = sorted([list(map(int, input().split())) for _ in range(N)])
cnt = {}
for i in range(N):
    for j in range(i+1,N):
        pq = (arr[j][0] - arr[i][0], arr[j][1] - arr[i][1])
        cnt.setdefault(pq, 0)
        cnt[pq] += 1
print((1 if cnt == {} else N - max(cnt.values())))
# Original solution
from collections import Counter
import math
N = int(eval(input()))
x,y = list(map(int, input().split()))
dis_list = [[x,y]]
for i in range(N-1):
	x , y = list(map(int,input().split()))
	for j in range(len(dis_list)):
		x = abs(x- dis_list[j][0])
		y = abs(y-dis_list[j][1])
		dis_list.append([x,y])
dis_list = dis_list[1:1+N*(N-1)//2]
counter = Counter(list(map(tuple, dis_list)))
if N == 1:
    print((1))
else:
    print((N-counter.most_common()[0][1]))

# Optimized solution
import math
N = int(eval(input()))
s_dict = {}
cood_list=[]
ans = 0
for i in range(N):
    a,b = list(map(int,input().split()))
    for j in range(len(cood_list)):
        p = a - cood_list[j][0]
        q = b - cood_list[j][1]
        if 0 > p:
            p = -p
            q = -q
        elif p == 0:
            q = abs(q)
        s = str(p)+","+str(q)
        if s not in s_dict:
            s_dict[s] = 1
        else:
            s_dict[s] += 1
    cood = [a,b]
    cood_list.append(cood)
if N != 1:
    print((N-max(s_dict.values())))
else:
    print((1))
# Original solution
import sys
import math
import itertools
import bisect
from copy import copy
from collections import deque,Counter
from decimal import Decimal
def s(): return eval(input())
def i(): return int(eval(input()))
def S(): return input().split()
def I(): return list(map(int,input().split()))
def L(): return list(input().split())
def l(): return list(map(int,input().split()))
def lcm(a,b): return a*b//math.gcd(a,b)
sys.setrecursionlimit(10**9)
INF = 10**9
mod = 10**9+7

N = i()
S = [l() for _ in range(N)]
ans = 0
for _ in range(N):
    pq = []
    for i in S:
        for j in S:
            if i == j:
                continue
            pq.append((i[0]-j[0],i[1]-j[1]))
    for p,q in set(pq):
        cnt = 0
        for i in S:
            for j in S:
                if i == j:
                    continue
                if (i[0]-j[0],i[1]-j[1]) == (p,q):
                    cnt += 1
        ans = max(ans,cnt)
print((N-ans))


# Optimized solution
import sys
import math
import itertools
import bisect
from copy import copy
from collections import deque,Counter
from decimal import Decimal
def s(): return eval(input())
def i(): return int(eval(input()))
def S(): return input().split()
def I(): return list(map(int,input().split()))
def L(): return list(input().split())
def l(): return list(map(int,input().split()))
def lcm(a,b): return a*b//math.gcd(a,b)
sys.setrecursionlimit(10**9)
INF = 10**9
mod = 10**9+7

N = i()
S = [l() for _ in range(N)]
ans = 0
pq = []
for i in S:
    for j in S:
        if i == j:
            continue
        pq.append((i[0]-j[0],i[1]-j[1]))
for p,q in set(pq):
    cnt = 0
    for i in S:
        for j in S:
            if i == j:
                continue
            if (i[0]-j[0],i[1]-j[1]) == (p,q):
                cnt += 1
    ans = max(ans,cnt)
print((N-ans))
# Original solution
def cal(dx,dy):
    cnt=0
    for x in s:
        flag=False
        for y in s:
            if(x==y):
                continue
            if(x[0]+dx==y[0] and x[1]+dy==y[1]):
                flag=True
        if(flag==False):
            cnt+=1
    return cnt

n=int(eval(input()))
s=[list(map(int,input().split())) for _ in range(n)]
ans=n
for x in s:
    for y in s:
        if(x==y):
            continue
        dx=x[0]-y[0]
        dy=x[1]-y[1]
        tmp=cal(dx,dy)
        if(tmp<ans):
            ans=tmp
print(ans)

# Optimized solution
N = int(eval(input()))

coodinates = [list(map(int, input().split())) for _ in range(N)]

flag = True
if N == 1:
    print((1))
    flag = False

if flag:
    # p, qを求める
    d = {}  # [p, q]をkeyにもつ辞書
    cnt=0
    for a in coodinates:
        for b in coodinates:
            if a == b:
                continue
            p, q = a[0] - b[0], a[1] - b[1]
            if (p, q) in d:
                d[(p, q)] += 1
            else:
                d[(p, q)] = 1
            cnt=max(cnt,d[(p,q)])

    print((N - cnt))
# Original solution
N = int(eval(input()))
x, y = (
    list(zip(*(list(map(int, input().split())) for _ in range(N)))) if N else
    ((), ())
)

class UnionFindTree:
    def __init__(self, n):
        self.p = [i for i in range(n + 1)]
        self.r = [0 for _ in range(n + 1)]

    def find(self, x):
        if self.p[x] != x:
            self.p[x] = self.find(self.p[x])
        return self.p[x]

    def union(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px != py:
            if self.r[px] < self.r[py]:
                self.p[px] = py
            else:
                self.p[py] = px
                if self.r[px] == self.r[py]:
                    self.r[px] += 1

    def same(self, x, y):
        return self.find(x) == self.find(y)


ans = 10**10

for i in range(N):
    for j in range(N):
        p, q = (x[i] - x[j], y[i] - y[j])
        uft = UnionFindTree(N)
        for u in range(N):
            for v in range(N):
                if (x[u] - x[v], y[u] - y[v]) == (p, q) or (x[u] - x[v], y[u] - y[v]) == (-p, -q):
                    uft.union(u, v)
        ans = min(ans, len({uft.find(z) for z in range(N)}))

print(ans)


# Optimized solution
N = int(eval(input()))
x, y = (
    list(zip(*(list(map(int, input().split())) for _ in range(N)))) if N else
    ((), ())
)

class UnionFindTree:
    def __init__(self, n):
        self.p = [i for i in range(n + 1)]
        self.r = [0 for _ in range(n + 1)]

    def find(self, x):
        if self.p[x] != x:
            self.p[x] = self.find(self.p[x])
        return self.p[x]

    def union(self, x, y):
        px = self.find(x)
        py = self.find(y)
        if px != py:
            if self.r[px] < self.r[py]:
                self.p[px] = py
            else:
                self.p[py] = px
                if self.r[px] == self.r[py]:
                    self.r[px] += 1

    def same(self, x, y):
        return self.find(x) == self.find(y)


ans = 10**10

for i in range(N):
    for j in range(N):
        p, q = (x[i] - x[j], y[i] - y[j])
        uft = UnionFindTree(N)
        for u in range(N - 1):
            for v in range(u + 1, N):
                if (x[u] - x[v], y[u] - y[v]) == (p, q) or (x[u] - x[v], y[u] - y[v]) == (-p, -q):
                    uft.union(u, v)
        ans = min(ans, len({uft.find(z) for z in range(N)}))

print(ans)
# Original solution
from math import ceil,floor,factorial,gcd,sqrt,log2,cos,sin,tan,acos,asin,atan,degrees,radians,pi,inf
from itertools import accumulate,groupby,permutations,combinations,product,combinations_with_replacement
from collections import deque,defaultdict,Counter
from bisect import bisect_left,bisect_right
from operator import itemgetter
from heapq import heapify,heappop,heappush
from queue import Queue,LifoQueue,PriorityQueue
from copy import deepcopy
from time import time
import string
import sys
sys.setrecursionlimit(10 ** 7)
def input() : return sys.stdin.readline().strip()
def INT()   : return int(eval(input()))
def MAP()   : return list(map(int,input().split()))
def LIST()  : return list(MAP())

n = INT()
x = [LIST() for i in range(n)]
reg = 0

for i in range(n):
    for j in range(n):
        if i != j:
            p = x[j][0] - x[i][0]
            q = x[j][1] - x[i][1]
            count = 0
            for k in range(n):
                for l in range(n):
                    if x[l][0] - x[k][0] == p  and x[l][1] - x[k][1] ==  q:
                        count += 1
            reg = max(reg, count)

ans = n - reg
print(ans)

# Optimized solution
from math import ceil,floor,factorial,gcd,sqrt,log2,cos,sin,tan,acos,asin,atan,degrees,radians,pi,inf
from itertools import accumulate,groupby,permutations,combinations,product,combinations_with_replacement
from collections import deque,defaultdict,Counter
from bisect import bisect_left,bisect_right
from operator import itemgetter
from heapq import heapify,heappop,heappush
from queue import Queue,LifoQueue,PriorityQueue
from copy import deepcopy
from time import time
import string
import sys
sys.setrecursionlimit(10 ** 7)
def input() : return sys.stdin.readline().strip()
def INT()   : return int(eval(input()))
def MAP()   : return list(map(int,input().split()))
def LIST()  : return list(MAP())

n = INT()
x = [LIST() for i in range(n)]
 
a = []
for i in range(n):
    for j in range(n):
        if i != j:
            a.append((x[j][0]-x[i][0], x[j][1]-x[i][1]))
 
a.sort()
count = 1
reg = 1

for i in range(1, len(a)):
    if a[i][:] == a[i-1][:]:
        count += 1
        reg = max(reg, count)
    else:
        count = 1

if n == 1:
    ans = n
else:
    ans = n - reg

print(ans)
# Original solution
n = int(eval(input()))
xy = [tuple(map(int, input().split())) for _ in range(n)]
pq = []
for i in range(n):
	for j in range(n):
		if i==j:
			continue
		xi, yi = xy[i]
		xj, yj = xy[j]
		pq.append((xi - xj, yi - yj))
ans = 1e9 if n>1 else 1
for p, q in pq:
	cost = 0
	for x, y in xy:
		if (x + p, y + q) in xy:
			pass
		else:
			cost += 1
	ans = min(ans, cost)
print(ans)


# Optimized solution
n = int(eval(input()))
xy = [tuple(map(int, input().split())) for _ in range(n)]
pq = []
for i in range(n):
	for j in range(i+1,n):
		if i==j:
			continue
		xi, yi = xy[i]
		xj, yj = xy[j]
		pq.append((xi - xj, yi - yj))
ans = n
for p, q in pq:
	cost = 0
	for x, y in xy:
		if (x + p, y + q) in xy:
			pass
		else:
			cost += 1
	ans = min(ans, cost)
print(ans)
# Original solution
import sys

def main():
    N = int(eval(input()))
    xy = [[int(e) for e in input().split()] for _ in range(N)]
    if N == 1:
        print((1))
        return
    else:
        d_list = [(i[0] - j[0], i[1] - j[1]) for i in xy for j in xy if i != j]
        items = list(set(d_list))
        s = 1
        for item in items:
            c = d_list.count(item)
            if c > s:
                s = c
        print((N - s))
        return

main()

# Optimized solution
N = int(eval(input()))
if N == 1:
    print((1))
    exit()
xy = [tuple(int(e) for e in input().split()) for _ in range(N)]
d_list = [(i[0] - j[0], i[1] - j[1]) for i in xy for j in xy if i != j]
items = list(set(d_list))
s = 1
for item in items:
    c = d_list.count(item)
    if c > s:
        s = c
print((N - s))
# Original solution
N = int(eval(input()))
if N == 1:
    print((1))
    exit()
xy = [tuple(int(e) for e in input().split()) for _ in range(N)]
d_list = [(i[0] - j[0], i[1] - j[1]) for i in xy for j in xy if i != j]
items = list(set(d_list))
s = 1
for item in items:
    c = d_list.count(item)
    if c > s:
        s = c
print((N - s))

# Optimized solution
N = int(eval(input()))
if N == 1:
    print((1))
else:
    xy = [tuple(int(e) for e in input().split()) for _ in range(N)]
    xy.sort()
    d = {}
    for i in range(N):
        for j in range(i + 1, N):
            p = xy[i][0] - xy[j][0]
            q = xy[i][1] - xy[j][1]
            if (p, q) in d:
                d[(p, q)] += 1
            else:
                d[(p, q)] = 1
    print((N - max(d.values())))