Problem: Author note: I think some of you might remember the problem "Two Melodies" from Eductational Codeforces Round 22. Now it's time to make it a bit more difficult!

Alice is a composer, and recently she had recorded two tracks that became very popular. Now she has got a lot of fans who are waiting for new tracks. 

This time Alice wants to form four melodies for her tracks.

Alice has a sheet with n notes written on it. She wants to take four such non-empty non-intersecting subsequences that all of them form a melody and sum of their lengths is maximal.

Subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements.

Subsequence forms a melody when each two adjacent notes either differ by 1 or are congruent modulo 7.

You should write a program which will calculate maximum sum of lengths of such four non-empty non-intersecting subsequences that all of them form a melody.

Input

The first line contains one integer number n (4 ≤ n ≤ 3000).

The second line contains n integer numbers a1, a2, ..., an (1 ≤ ai ≤ 105) — notes written on a sheet.

Output

Print maximum sum of lengths of such four non-empty non-intersecting subsequences that all of them form a melody.

Examples

Input

5
1 3 5 7 9


Output

4


Input

5
1 3 5 7 2


Output

5

Note

In the first example it is possible to compose 4 melodies by choosing any 4 notes (and each melody will consist of only one note).

In the second example it is possible to compose one melody with 2 notes — {1, 2}. Remaining notes are used in other three melodies (one note per each melody).

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
const int N = 6004, oo = 1e9 + 7;
int n, a[N], rem, cost[N], p[N];
struct edge {
  int u, v, f, w;
} g[28 * N];
void addEdge(int u, int v, int w) {
  g[rem].u = u;
  g[rem].v = v;
  g[rem].f = 1;
  g[rem++].w = -w;
  g[rem].u = v;
  g[rem].v = u;
  g[rem].f = 0;
  g[rem++].w = w;
}
void addEdge1(int u, int v, int w) {
  g[rem].u = u + n;
  g[rem].v = v;
  g[rem].f = 1;
  g[rem++].w = -w;
  g[rem].u = v;
  g[rem].v = u + n;
  g[rem].f = 0;
  g[rem++].w = w;
}
bool getPath() {
  for (int i = 1; i < N; i++) cost[i] = oo;
  bool did = 1;
  for (int i = 0; i < N && did; i++) {
    did = 0;
    for (int j = 0; j < rem; j++)
      if (g[j].f && cost[g[j].u] + g[j].w < cost[g[j].v]) {
        cost[g[j].v] = cost[g[j].u] + g[j].w;
        p[g[j].v] = j;
        did = 1;
      }
  }
  return cost[n + 1] < oo / 2;
}
int minCostMaxFlow() {
  int cost = 0, flow = 0;
  while (flow < 4 && getPath()) {
    for (int cur = 2 * n + 1; cur; cur = g[p[cur]].u) {
      g[p[cur]].f ^= 1;
      g[p[cur] ^ 1].f ^= 1;
    }
    cost += ::cost[2 * n + 1];
    flow++;
  }
  return -cost;
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", a + i);
  for (int i = 1; i <= n; i++) addEdge(0, i, 0);
  for (int i = 1; i <= n; i++) addEdge(i, i + n, 0);
  for (int i = n + 1; i <= 2 * n; i++) addEdge(i, 2 * n + 1, 1);
  for (int i = 1; i <= n; i++) {
    int can[3] = {};
    for (int j = i + 1; j <= n; j++)
      if (a[i] % 7 == a[j] % 7) {
        if (can[0]++ < 4) addEdge1(i, j, 1);
      } else if (a[i] - a[j] == 1) {
        if (can[1]++ < 4) addEdge1(i, j, 1);
      } else if (a[j] - a[i] == 1) {
        if (can[2]++ < 4) addEdge1(i, j, 1);
      }
  }
  printf("%d\n", minCostMaxFlow());
}