### BUGGY CODE ###

# coding: utf-8
import sys
#from operator import itemgetter
sysread = sys.stdin.buffer.readline
read = sys.stdin.buffer.read
#from heapq import heappop, heappush
from collections import defaultdict
sys.setrecursionlimit(10**7)
#import math
#from itertools import product, accumulate, combinations, product
#import bisect
#import numpy as np
#from copy import deepcopy
#from collections import deque
#from decimal import Decimal
#from numba import jit

INF = 1 << 50

def check_triple(L):
    dic = defaultdict(lambda:0)
    val = None
    for l in L:
        dic[l] += 1
        if dic[l] == 3:
            val = l
            break
    if val != None:
        ret = []
        cnt = 0
        for l in L:
            if l == val and cnt < 3:
                cnt += 1
                continue
            else:
                ret.append(l)
        return True, ret
    else:
        return False, L


def run():
    N, *A = map(int, read().split())

    dp = [defaultdict(lambda:0) for i in range(N)]
    prim = sorted(A[:2])
    prim = tuple(prim)
    dp[0][prim] = 0
    for i in range(N-1):
        for key, score in dp[i].items():
            a, b = key
            temp_lis = [a,b] + A[2 + i * 3: 5 + i * 3]
            #print(temp_lis, '--->')
            ANS, temp_lis = check_triple(temp_lis)

            #print(temp_lis)
            if ANS:
                temp_lis = tuple(sorted(temp_lis))
                dp[i+1][temp_lis] = max(score + 1, dp[i+1][temp_lis])
            else:
                temp_lis = sorted(temp_lis)
                for idx, a in enumerate(temp_lis):
                    for b in temp_lis[idx+1:]:
                        dp[i+1][(a, b)] = max(dp[i+1][(a,b)], score)

    ans = max(dp[N-1].values())

    for key, score in dp[N-1].items():
        a, b = key
        if a == b and a == A[-1]:
            ans = max(ans, score + 1)

    print(ans)










if __name__ == "__main__":
    #print(check_triple([1,2,1,2,2]))
    run()

### FIXED CODE ###

# coding: utf-8
import sys
#from operator import itemgetter
sysread = sys.stdin.buffer.readline
read = sys.stdin.buffer.read
#from heapq import heappop, heappush
from collections import defaultdict
sys.setrecursionlimit(10**7)
#import math
#from itertools import product, accumulate, combinations, product
#import bisect
#import numpy as np
#from copy import deepcopy
#from collections import deque
#from decimal import Decimal
#from numba import jit

INF = 1 << 50
def run():
    N, *A_ = map(int, read().split())
    dp = [[-INF] * (N+1) for _ in range(N+1)]
    dp_max = [-INF] * (N+1)
    a, b = A_[:2]
    dp[a][b] = dp[b][a] = dp_max[a] = dp_max[b] = 0

    triplets = 0
    chunks = []

    for i in range(N-1):
        x,y,z = A_[3*i+2 : 3*i+5]
        if x == y == z:
            triplets+=1
        else:
            chunks.append((x,y,z))

    for x,y,z in chunks:
        cache = []
        # transition : a = x = y
        if y == z:
            x,y,z = y,z,x
        elif z == x:
            x,y,z = z,x,y

        if x == y:
            for i in range(1, N+1):
                cache.append((z, i, dp[x][i] + 1))

        # trainsition : a = b = x
        cache.append((y, z, dp[x][x] + 1))
        cache.append((z, x, dp[y][y] + 1))
        cache.append((x, y, dp[z][z] + 1))

        # trainsition : only fill next
        MAX = max(dp_max)
        cache.append((x, y, MAX))
        cache.append((y, z, MAX))
        cache.append((z, x, MAX))
        for i in range(1, N+1):
            cache.append((i, x, dp_max[i]))
            cache.append((i, y, dp_max[i]))
            cache.append((i, z, dp_max[i]))

        # Update
        for a, b, value in cache:
            dp[a][b] = dp[b][a] = max(value, dp[a][b])
            dp_max[a] = max(dp_max[a], dp[a][b])
            dp_max[b] = max(dp_max[b], dp[a][b])

    a = A_[-1]
    dp[a][a] += 1
    dp_max[a] = max(dp[a][a], dp_max[a])

    print(max(dp_max) + triplets)
    #print(chunks)


if __name__ == "__main__":
    run()