from itertools import combinations
from itertools import groupby
def solve(xyuv):
    if len(xyuv) <= 2 or is_all_same(xyuv) or is_all_same_attime(xyuv):
        return len(xyuv)
    max_ij = 0
    for i, j in combinations(range(len(xyuv)), 2):
        if xyuv[i] == xyuv[j]:
            continue
        xyi,uvi = xyuv[i]
        xyj,uvj = xyuv[j]
            
        always_lined_point = 0
        t = []
        for k in range(len(xyuv)):
            if i == k or j == k:
                continue
            xyk,uvk = xyuv[k]
            ans, flg = get_t(xyi - xyk, uvi - uvk, xyj - xyk, uvj - uvk)
            t.extend(ans)
            if flg:
                always_lined_point += 1

        t = [round(ti, 10) for ti in t] #?????????
        t = [ti for ti in t if 0 <= ti] #t<0?????????
        t.sort()
        
        xyi -= xyj
        uvi -= uvj

        max_group_length = 0
        for k, g in groupby(t):
            group_length = 1 if eq(xyi + uvi * k, 0) else sum(1 for _ in g)
            max_group_length = max(max_group_length, group_length)
            
        max_ij = max(max_ij, max_group_length + always_lined_point + 2)
    return max_ij

def get_t(xy1,uv1,xy2,uv2):
    a = cross(uv1, uv2)
    b = cross(xy1, uv2) + cross(uv1, xy2)
    c = cross(xy1, xy2)
    ans, flg = quadratic_equation(a, b, c)
    return ans, flg

def is_all_same_attime(xyuv):
    xy0, uv0 = xyuv[0]
    for i in range(len(xyuv)):
        if xyuv[0] == xyuv[i]:
            continue
        xyi,uvi = xyuv[i]

        t = get_cross_time(xy0,xyi,xy0 + uv0,xyi + uvi)

        if t is None or t < 0:
            return False

        p0 = xy0 + uv0 * t
        for j in range(i + 1,len(xyuv)):
            xyj, uvj = xyuv[j]
            pj = xyj + uvj * t
            if eq(pj, p0):
                continue
            return False
        break
    return True

def get_cross_time(p1,p2,p3,p4):
    s1 = cross(p4-p2,p1-p2)
    s2 = cross(p4-p2,p2-p3)
    if s1 + s2 == 0:
        return None
    return s1 / (s1 + s2)
def take2(i):
    while True:
        yield next(i),next(i)
def main(f):
    _ = int(f.readline())
    xyuv = [[x+y*1j for x,y in take2(map(int, line.split()))] for line in f]

    print(solve(xyuv))
def is_all_same(xyuv):
    for xyuvi in xyuv:
        if xyuvi != xyuv[0]:
            return False
    return True
def cross(v1,v2):
    return v1.real * v2.imag - v1.imag * v2.real
def eq(a, b):
    return abs(a - b) <= 10 ** -9
# return [2?¬?????¨????????§£],0==a==b==c
def quadratic_equation(a,b,c):
    if a:
        d = b * b - 4 * a * c
        if d < 0:
            ans = []
        elif d == 0:
            ans = [-b / (2 * a)]
        else:
            d **= 0.5
            d /= 2 * a
            b /= 2 * a
            ans = [-b + d, -b - d]
    elif b:
        ans = [-c / b]
    else:
        ans = []
    return ans, 0 == a == b == c


import sys
f = sys.stdin

main(f)

### FIXED CODE ###

def take2(i):
    while True:
        yield next(i),next(i)
def main(f):
    _ = int(f.readline())
    xyuv = [[x+y*1j for x,y in take2(map(int, line.split()))] for line in f]

    print(solve(xyuv))
def is_all_same_attime(xyuv):
    xy0, uv0 = xyuv[0]
    for i in range(len(xyuv)):
        if xyuv[0] == xyuv[i]:
            continue
        xyi,uvi = xyuv[i]

        t = get_cross_time(xy0 - xyi, uv0 - uvi)

        if t is None or t < 0:
            return False

        p0 = xy0 + uv0 * t
        for j in range(i + 1,len(xyuv)):
            xyj, uvj = xyuv[j]
            pj = xyj + uvj * t
            if is_zero(pj - p0):
                continue
            return False
        break
    return True
def get_cross_time(xy,uv):
     denominator = uv.real - uv.imag
     return (xy.imag - xy.real) / denominator if denominator else None

def is_all_same(xyuv):
    for xyuvi in xyuv:
        if xyuvi != xyuv[0]:
            return False
    return True

def is_zero(a):
    return abs(a) < 0.00001

def get_t(xy1,uv1,xy2,uv2):
    a = uv1.real * uv2.imag - uv1.imag * uv2.real
    b = xy1.real * uv2.imag - xy1.imag * uv2.real + uv1.real * xy2.imag - uv1.imag * xy2.real
    c = xy1.real * xy2.imag - xy1.imag * xy2.real
    if a:
        d = b * b - 4 * a * c
        if d < 0:
            return []
        elif d == 0:
            return [-b / (2 * a)]
        else:
            d = d ** 0.5 / (2 * a)
            b /= 2 * a
            return [-b + d, -b - d]
    if b:
        return [-c / b]
    if not c:
        global always_lined_point
        always_lined_point += 1
    return []

from itertools import combinations
from itertools import groupby
from collections import Counter
#@profile
def solve(xyuv):
    global always_lined_point
    if len(xyuv) <= 2 or is_all_same(xyuv) or is_all_same_attime(xyuv):
        return len(xyuv)
    max_ij = 0
    for i, j in combinations(range(len(xyuv)), 2):
        if xyuv[i] == xyuv[j]:
            continue
        xyi,uvi = xyuv[i]
        xyj,uvj = xyuv[j]
            
        always_lined_point = 0
        t = []
        for indeces in (range(i),range(i + 1,j),range(j + 1,len(xyuv))):
            for k in indeces:
                xyk,uvk = xyuv[k]
                t.extend(get_t(xyi - xyk, uvi - uvk, xyj - xyk, uvj - uvk))

        t = [ti for ti in t if 0 <= ti] #t<0?????????
        t = [round(ti, 10) for ti in t] #?????????
        t = Counter(t)

        xyi -= xyj
        uvi -= uvj

        group_lengths = [0]
        for k, c in t.most_common(2):
            group_length = 1 if is_zero(xyi + uvi * k) else c
            group_lengths.append(group_length)
             
        max_ij = max(max_ij, max(group_lengths) + always_lined_point + 2)
    return max_ij

import sys
f = sys.stdin

main(f)