// dfmt off
T lread(T=long)(){return readln.chomp.to!T;}T[] lreads(T=long)(long n){return iota(n).map!((_)=>lread!T).array;}
T[] aryread(T=long)(){return readln.split.to!(T[]);}void arywrite(T)(T a){a.map!text.join(' ').writeln;}
void scan(L...)(ref L A){auto l=readln.split;foreach(i,T;L){A[i]=l[i].to!T;}}alias sread=()=>readln.chomp();
void dprint(L...)(lazy L A){debug{auto l=new string[](L.length);static foreach(i,a;A)l[i]=a.text;arywrite(l);}}
alias PQueue(T,alias l="b<a")=BinaryHeap!(Array!T,l);import std, core.bitop;
// dfmt on
void main()
{
    auto input = stdin.byLine.map!split.joiner;

    long N;
    N = input.front.to!long;
    input.popFront;

    long[] A = new long[](cast(size_t)(3 * N));
    foreach (i; 0 .. cast(size_t)(3 * N))
    {
        A[i] = input.front.to!long;
        input.popFront;
    }

    solve(N, A);
}

void solve(long N, long[] A)
{
    alias T = Tuple!(long, long, long, long);
    DList!T Q;
    Q.insert(T(0, min(A[0], A[1]), max(A[0], A[1]), 0));
    long ans;
    bool[T] visited;
    while (!Q.empty)
    {
        auto t = Q.front;
        Q.removeFront();
        if (t in visited)
            continue;
        visited[t] = true;
        auto i = t[0];
        auto a = t[1];
        auto b = t[2];
        auto s = t[3];
        dprint(i, a, b, s);
        if (i == 3 * N)
        {
            ans = ans.max(s);
            continue;
        }
        auto v = [
            a, b, !(i + 2 < 3 * N) ? -1 : A[i + 2], !(i + 3 < 3 * N) ? -2 : A[i + 3],
            !(i + 4 < 3 * N) ? -3 : A[i + 4]
        ];
        auto comb = [0, 0, 1, 1, 1];
        do
        {
            long[] r, p;
            foreach (j, c; comb)
            {
                if (c == 0)
                    r ~= v[j];
                if (c == 1)
                    p ~= v[j];
            }
            r.sort();
            Q.insert(T(i + 3, r[0], r[1], s + (p[0] == p[1] && p[1] == p[2])));
        }
        while (nextPermutation(comb));
    }
    writeln(ans);
}
