Problem: Fox Ciel is participating in a party in Prime Kingdom. There are n foxes there (include Fox Ciel). The i-th fox is ai years old.

They will have dinner around some round tables. You want to distribute foxes such that:

  1. Each fox is sitting at some table. 
  2. Each table has at least 3 foxes sitting around it. 
  3. The sum of ages of any two adjacent foxes around each table should be a prime number. 



If k foxes f1, f2, ..., fk are sitting around table in clockwise order, then for 1 ≤ i ≤ k - 1: fi and fi + 1 are adjacent, and f1 and fk are also adjacent.

If it is possible to distribute the foxes in the desired manner, find out a way to do that.

Input

The first line contains single integer n (3 ≤ n ≤ 200): the number of foxes in this party. 

The second line contains n integers ai (2 ≤ ai ≤ 104).

Output

If it is impossible to do this, output "Impossible".

Otherwise, in the first line output an integer m (<image>): the number of tables.

Then output m lines, each line should start with an integer k -=– the number of foxes around that table, and then k numbers — indices of fox sitting around that table in clockwise order.

If there are several possible arrangements, output any of them.

Examples

Input

4
3 4 8 9


Output

1
4 1 2 4 3


Input

5
2 2 2 2 2


Output

Impossible


Input

12
2 3 4 5 6 7 8 9 10 11 12 13


Output

1
12 1 2 3 6 5 12 9 8 7 10 11 4


Input

24
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25


Output

3
6 1 2 3 6 5 4
10 7 8 9 12 15 14 13 16 11 10
8 17 18 23 22 19 20 21 24

Note

In example 1, they can sit around one table, their ages are: 3-8-9-4, adjacent sums are: 11, 17, 13 and 7, all those integers are primes.

In example 2, it is not possible: the sum of 2+2 = 4 is not a prime number.

Solution (in CPP):

Solution:
#include <bits/stdc++.h>
using namespace std;
using ll = int64_t;
using ull = uint64_t;
using ld = long double;
using P = pair<int, int>;
using vs = vector<string>;
using vi = vector<int>;
using vvi = vector<vi>;
template <class T>
using PQ = priority_queue<T>;
template <class T>
using PQG = priority_queue<T, vector<T>, greater<T>>;
const int INF = 0xccccccc;
const ll LINF = 0xcccccccccccccccLL;
template <typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) {
  return a < b && (a = b, true);
}
template <typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) {
  return a > b && (a = b, true);
}
template <typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  return is >> p.first >> p.second;
}
template <typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  return os << p.first << ' ' << p.second;
}
struct edge {
  int to, rev;
  int64_t cap;
  edge(int t = 0, int64_t c = 0, int r = 0) : to(t), cap(c), rev(r) {}
};
struct max_flow {
  vector<vector<edge>> G;
  vector<int> level, iter;
  int n;
  max_flow(int n = 0) : n(n), G(n), level(n), iter(n) {}
  inline int add(int from, int to, int64_t cap) {
    G[from].emplace_back(to, cap, G[to].size());
    G[to].emplace_back(from, 0, G[from].size() - 1);
    return G[from].size() - 1;
  }
  void bfs(int s) {
    for (int i = 0; i < n; i++) level[i] = -1;
    queue<int> que;
    level[s] = 0;
    que.emplace(s);
    while (!que.empty()) {
      int now = que.front();
      que.pop();
      for (edge &e : G[now]) {
        if (e.cap > 0 and level[e.to] < 0) {
          level[e.to] = level[now] + 1;
          que.emplace(e.to);
        }
      }
    }
  }
  int64_t dfs(int v, int t, int64_t f) {
    if (v == t) return f;
    for (int &i = iter[v]; i < G[v].size(); i++) {
      edge &e = G[v][i];
      if (e.cap > 0 and level[v] < level[e.to]) {
        int64_t d = dfs(e.to, t, min(f, e.cap));
        if (d > 0) {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
      }
    }
    return 0;
  }
  int64_t Dinic(int s, int t) {
    int64_t flow = 0;
    while (true) {
      bfs(s);
      if (level[t] < 0) return flow;
      for (int i = 0; i < n; i++) iter[i] = 0;
      int64_t f;
      while ((f = dfs(s, t, INT64_MAX)) > 0) flow += f;
    }
  }
};
struct Sieve {
  int n;
  vector<int> f, primes;
  Sieve(int n = 1) : n(n), f(n + 1) {
    f[0] = f[1] = -1;
    for (int i = 2; i <= n; ++i) {
      if (!f[i]) {
        primes.emplace_back(i);
        f[i] = i;
      }
      for (int p : primes) {
        int u = p * i;
        if (u > n or p > f[i]) break;
        f[u] = p;
      }
    }
  }
  bool isPrime(int x) { return f[x] == x; }
  bool isPrime1(int64_t x) {
    bool m = true;
    for (int z : primes) {
      if (!(x % z)) {
        m = false;
        break;
      }
    }
    return m;
  }
  vector<int> factorList(int x) {
    assert(x <= n);
    vector<int> res;
    while (x != 1) {
      res.emplace_back(f[x]);
      x /= f[x];
    }
    return res;
  }
  vector<pair<int, int>> factor(int x) {
    vector<int> fl = factorList(x);
    if (fl.size() == 0) return {};
    vector<pair<int, int>> res(1, pair<int, int>(fl[0], 0));
    for (int p : fl) {
      if (res.back().first == p) {
        ++res.back().second;
      } else {
        res.emplace_back(p, 1);
      }
    }
    return res;
  }
  vector<int64_t> factorList1(int64_t x) {
    vector<int64_t> vec;
    for (int z : primes) {
      while (!(x % z)) {
        vec.emplace_back(z);
        x /= z;
      }
    }
    if (x != 1) vec.emplace_back(x);
    return vec;
  }
  vector<pair<int64_t, int>> factor1(int64_t x) {
    vector<int64_t> vec = factorList1(x);
    vector<pair<int64_t, int>> vecc;
    for (vector<int64_t>::iterator itr = vec.begin(); itr != vec.end(); ++itr) {
      if (itr != vec.begin() && *itr == *(itr - 1)) {
        (vecc.end() - 1)->second++;
      } else {
        vecc.emplace_back(pair<int64_t, int>(*itr, 1));
      }
    }
    return vecc;
  }
  vector<int64_t> div1(int64_t x) {
    vector<int64_t> res(1, 1);
    vector<pair<int64_t, int>> fac = factor1(x);
    for (int i = 0; i < int(fac.size()); ++i) {
      int si = res.size();
      for (int j = 0; j < fac[i].second; ++j) {
        for (int k = 0; k < si; ++k) {
          res.emplace_back(res[k + j * si] * fac[i].first);
        }
      }
    }
    sort(res.begin(), res.end());
    return res;
  }
} pp(100000);
const char imp[] = "Impossible";
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  vi a(n);
  for (int i = 0; i < n; ++i) cin >> a[i];
  max_flow mf(n + 2);
  const int s = n, t = s + 1;
  for (int i = 0; i < n; ++i) {
    if (a[i] & 1) {
      mf.add(i, t, 2);
      for (int j = 0; j < n; ++j)
        if (pp.isPrime(a[i] + a[j])) mf.add(j, i, 1);
    } else {
      mf.add(s, i, 2);
    }
  }
  int u = mf.Dinic(s, t);
  if (u != n) {
    puts(imp);
    return 0;
  }
  vvi ans;
  vi check(n);
  for (int i = 0; i < n; ++i)
    if (!check[i]) {
      ans.push_back(vi());
      int now = i;
      bool done = false;
      do {
        done = false;
        ans.back().emplace_back(now);
        check[now] = 1;
        if (a[now] & 1) {
          for (auto e : mf.G[now]) {
            if (!e.cap or check[e.to]) continue;
            now = e.to;
            done = true;
          }
        } else {
          for (auto e : mf.G[now]) {
            if (e.cap or check[e.to]) continue;
            now = e.to;
            done = true;
          }
        }
      } while (done);
    }
  int m = ans.size();
  cout << m << endl;
  for (int i = 0; i < m; ++i) {
    int z = ans[i].size();
    cout << z;
    for (int j = 0; j < z; ++j) cout << ' ' << ans[i][j] + 1;
    cout << '\n';
  }
}