You are playing a game of Jongmah. You don't need to know the rules to solve this problem. You have n tiles in your hand. Each tile has an integer between 1 and m written on it.

To win the game, you will need to form some number of triples. Each triple consists of three tiles, such that the numbers written on the tiles are either all the same or consecutive. For example, 7, 7, 7 is a valid triple, and so is 12, 13, 14, but 2,2,3 or 2,4,6 are not. You can only use the tiles in your hand to form triples. Each tile can be used in at most one triple.

To determine how close you are to the win, you want to know the maximum number of triples you can form from the tiles in your hand.

Input

The first line contains two integers integer n and m (1 ≤ n, m ≤ 10^6) — the number of tiles in your hand and the number of tiles types.

The second line contains integers a_1, a_2, …, a_n (1 ≤ a_i ≤ m), where a_i denotes the number written on the i-th tile.

Output

Print one integer: the maximum number of triples you can form.

Examples

Input

10 6
2 3 3 3 4 4 4 5 5 6


Output

3


Input

12 6
1 5 3 3 3 4 3 5 3 2 3 3


Output

3


Input

13 5
1 1 5 1 2 3 3 2 4 2 3 4 5


Output

4

Note

In the first example, we have tiles 2, 3, 3, 3, 4, 4, 4, 5, 5, 6. We can form three triples in the following way: 2, 3, 4; 3, 4, 5; 4, 5, 6. Since there are only 10 tiles, there is no way we could form 4 triples, so the answer is 3.

In the second example, we have tiles 1, 2, 3 (7 times), 4, 5 (2 times). We can form 3 triples as follows: 1, 2, 3; 3, 3, 3; 3, 4, 5. One can show that forming 4 triples is not possible.
#include <bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("Ofast")
using namespace std;
namespace olymplib {
namespace {
template <class T>
void writeInt(T x);
template <class T>
void writeUInt(T x);
void writeChar(int x);
void writeWord(const char* s);
void writeDouble(double x, int len = 0);
static const int buf_size = 4096;
static int write_pos = 0;
static char write_buf[buf_size];
static char buf[buf_size];
static int buf_len = 0, buf_pos = 0;
template <class T = int>
T readInt();
double readDouble();
int readUInt();
int readChar();
void readWord(char* s);
bool readLine(char* s);
bool isEof();
int peekChar();
bool seekEof();
void flush();
bool isEof() {
  if (buf_pos == buf_len) {
    buf_pos = 0, buf_len = fread(buf, 1, buf_size, stdin);
    if (buf_pos == buf_len) return 1;
  }
  return 0;
}
int getChar() { return isEof() ? -1 : buf[buf_pos++]; }
int peekChar() { return isEof() ? -1 : buf[buf_pos]; }
bool seekEof() {
  int c;
  while ((c = peekChar()) != -1 && c <= 32) buf_pos++;
  return c == -1;
}
int readChar() {
  int c = getChar();
  while (c != -1 && c <= 32) c = getChar();
  return c;
}
int readUInt() {
  int c = readChar(), x = 0;
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getChar();
  return x;
}
template <class T>
T readInt() {
  int s = 1, c = readChar();
  T x = 0;
  if (c == '-') s = -1, c = getChar();
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getChar();
  return s == 1 ? x : -x;
}
template <class Double = double>
double readDouble() {
  int s = 1, c = readChar();
  Double x = 0;
  if (c == '-') s = -1, c = getChar();
  while ('0' <= c && c <= '9') x = x * 10 + c - '0', c = getChar();
  if (c == '.') {
    c = getChar();
    double coef = 1;
    while ('0' <= c && c <= '9') x += (c - '0') * (coef *= 1e-1), c = getChar();
  }
  return s == 1 ? x : -x;
}
void readWord(char* s) {
  int c = readChar();
  while (c > 32) *s++ = c, c = getChar();
  *s = 0;
}
bool readLine(char* s) {
  int c = getChar();
  while (c != '\n' && c != -1) *s++ = c, c = getChar();
  *s = 0;
  return c != -1;
}
void writeDouble(double x, int output_len) {
  if (x < 0) writeChar('-'), x = -x;
  int t = (int)x;
  writeUInt(t), x -= t;
  writeChar('.');
  for (int i = output_len - 1; i > 0; i--) {
    x *= 10;
    t = 9 < (int)x ? 9 : x;
    writeChar('0' + t), x -= t;
  }
  x *= 10;
  t = 9 < (int)(x + 0.5) ? 9 : (int)(x + 0.5);
  writeChar('0' + t);
}
void writeChar(int x) {
  if (write_pos == buf_size)
    fwrite(write_buf, 1, buf_size, stdout), write_pos = 0;
  write_buf[write_pos++] = x;
}
template <class T>
void writeUInt(T x) {
  char s[24];
  int n = 0;
  while (x || !n) s[n++] = '0' + x % 10, x /= 10;
  while (n--) writeChar(s[n]);
}
template <>
void writeInt<int>(int x) {
  if (x < 0) writeChar('-'), x = -x;
  char s[10];
  int n = 0;
  while (x || !n) s[n++] = '0' + x % 10, x /= 10;
  while (n--) writeChar(s[n]);
}
template <class T>
void writeInt(T x) {
  if (x < 0) writeChar('-'), x = -x;
  char s[24];
  int n = 0;
  while (x || !n) s[n++] = '0' + x % 10, x /= 10;
  while (n--) writeChar(s[n]);
}
void writeWord(const char* s) {
  while (*s) writeChar(*s++);
}
void flush() {
  if (write_pos) {
    fwrite(write_buf, 1, write_pos, stdout), write_pos = 0;
  }
}
}  // namespace
class TOutputStream {
  int precision_;

 public:
  void precision(int new_prec) { precision_ = new_prec; }
  TOutputStream& operator<<(bool arg) {
    writeChar('0' + arg);
    return *this;
  }
  TOutputStream& operator<<(char arg) {
    writeChar(arg);
    return *this;
  }
  TOutputStream& operator<<(const char* arg) {
    writeWord(arg);
    return *this;
  }
  TOutputStream& operator<<(float arg) {
    writeDouble(arg, precision_);
    return *this;
  }
  TOutputStream& operator<<(double arg) {
    writeDouble(arg, precision_);
    return *this;
  }
  TOutputStream& operator<<(long double arg) {
    writeDouble(arg, precision_);
    return *this;
  }
  TOutputStream& operator<<(int arg) {
    writeInt(arg);
    return *this;
  }
  TOutputStream& operator<<(long long arg) {
    writeInt(arg);
    return *this;
  }
  TOutputStream& operator<<(const std::string& arg) {
    writeWord(arg.c_str());
    return *this;
  }
  void flush() { olymplib::flush(); }
  typedef TOutputStream& (*MyStreamManipulator)(TOutputStream&);
  TOutputStream& operator<<(const MyStreamManipulator& manip) {
    return manip(*this);
  }
  ~TOutputStream() { flush(); }
};
class TInputStream {
 public:
  TInputStream& operator>>(bool& arg) {
    arg = readChar() - '0';
    return *this;
  }
  TInputStream& operator>>(char& arg) {
    arg = readChar();
    return *this;
  }
  TInputStream& operator>>(char*& arg) {
    readWord(arg);
    return *this;
  }
  TInputStream& operator>>(float& arg) {
    arg = readDouble<float>();
    return *this;
  }
  TInputStream& operator>>(double& arg) {
    arg = readDouble<double>();
    return *this;
  }
  TInputStream& operator>>(long double& arg) {
    arg = readDouble<long double>();
    return *this;
  }
  TInputStream& operator>>(int& arg) {
    arg = readInt<int>();
    return *this;
  }
  TInputStream& operator>>(long long arg) {
    arg = readInt<long long>();
    return *this;
  }
  TInputStream& operator>>(std::string& arg) {
    arg.clear();
    arg.reserve(16);
    arg.push_back(readChar());
    while (char c = peekChar()) {
      if (c == -1 || c <= 32) break;
      arg.push_back(getChar());
    }
    arg.shrink_to_fit();
    return *this;
  }
};
static TInputStream cin;
static TOutputStream cout;
static TOutputStream& endl(TOutputStream& stream) {
  stream << '\n';
  stream.flush();
  return stream;
}
}  // namespace olymplib
const int N = 1e6 + 1000;
const int M = 1e6 + 100;
const int CAP = 7;
int dp[CAP][CAP][CAP][CAP];
int cnt[N];
int answer = 0;
void relax(int& a, int b) {
  a = max(a, b);
  answer = max(answer, b);
}
int gather(int x, int a) { return x - a; }
int main() {
  int n, m;
  cin >> n >> m;
  for (int i = 0; i < n; ++i) {
    int x;
    cin >> x;
    cnt[x + 3]++;
  }
  int ans = 0;
  memset(dp, -1, sizeof(dp));
  dp[0][0][0][0] = 0;
  for (int x = 0; x < M; ++x) {
    int from = x % CAP;
    int to = (x + 1) % CAP;
    memset(dp[to], -1, sizeof(dp[to]));
    for (int a = 0; a < CAP; ++a) {
      for (int b = 0; b < CAP; ++b) {
        for (int c = 0; c < CAP; ++c) {
          if (dp[from][a][b][c] == -1) continue;
          if (cnt[x] < a) {
            continue;
          }
          int c1 = gather(cnt[x], a);
          int MAX = c1;
          MAX = min(MAX, gather(cnt[x + 1], b));
          MAX = min(MAX, gather(cnt[x + 2], c));
          if (MAX < 0) continue;
          MAX = min(MAX, 3);
          for (int neg = 0; neg <= MAX; ++neg) {
            if (b + neg < CAP && c + neg < CAP) {
              relax(dp[to][b + neg][c + neg][0],
                    dp[from][a][b][c] + neg + (c1 - neg) / 3);
            }
          }
        }
      }
    }
  }
  cout << answer << "\n";
  return 0;
}
