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;
struct debugger {
  template <typename T>
  debugger& operator,(const T v) {
    cout << v << " ";
    return *this;
  }
} dbg;
const double pi = acos(-1.0);
const double eps = 1e-7;
template <class TT>
TT sqr(TT a) {
  return a * a;
}
template <class TT>
TT abs(TT a) {
  if (a < 0) return -a;
  return a;
}
const int S = 201;
int a[S];
const int pN = 30000;
bool ip[pN + 1];
void genPrime() {
  for (int i = 4; i <= pN; i += 2) ip[i] = true;
  for (int i = 3; i <= pN; i += 2)
    if (!ip[i]) {
      if (i * i <= pN) {
        for (int j = i * i; j <= pN; j += 2 * i) ip[j] = true;
      }
    }
}
class Flow {
 public:
  const static int N = 202;
  vector<int> g[N];
  int cap[N][N], par[N], flag[N], mat[N / 2][N];
  int source, sink;
  int flagN;
  Flow() {}
  Flow(int source, int sink) {
    this->source = source;
    this->sink = sink;
    flagN = 1;
    memset(mat, 0, sizeof mat);
    memset(cap, 0, sizeof cap);
  }
  bool isPath(int u) {
    flag[u] = flagN;
    for (int i = 0; i < ((int)g[u].size()); i++) {
      int v = g[u][i];
      if (flagN == flag[v]) continue;
      if (cap[u][v] > 0) {
        par[v] = u;
        if (v == sink) return true;
        if (isPath(v)) return true;
      }
    }
    return false;
  }
  int getSet(int u) {
    if (u && u <= m) return 1;
    if (u > m && u < sink) return 2;
    return 0;
  }
  void makeAug(int v) {
    if (v == 0) return;
    int u = par[v];
    if (1 == getSet(u) && 2 == getSet(v))
      mat[u][v] = 1;
    else if (1 == getSet(v) && 2 == getSet(u))
      mat[v][u] = 0;
    makeAug(u);
    cap[u][v]--;
    cap[v][u]++;
  }
  int maxFlow() {
    int sum = 0, flow = 1;
    while (isPath(source)) {
      flagN++;
      sum++;
      makeAug(sink);
    }
    return sum;
  }
  void addEdge(int u, int v, int weight) {
    g[u].push_back(v);
    g[v].push_back(u);
    cap[u][v] += weight;
  }
  int n, m;
  void buildGraph(int n);
  void match();
  bool dfs(int u, vector<int>& vec);
};
vector<int> o, e, po, pe;
void Flow::buildGraph(int n) {
  memset(cap, 0, sizeof cap);
  for (int i = 0; i < ((int)e.size()); i++)
    for (int j = 0; j < ((int)o.size()); j++)
      if (!ip[e[i] + o[j]]) addEdge(i + 1, m + j + 1, 1);
  for (int i = 0; i < m; i++) {
    addEdge(0, i + 1, 2);
    addEdge(m + i + 1, sink, 2);
  }
}
void Flow::match() {
  for (int i = 1; i <= n; i++) g[i].clear();
  for (int i = 1; i <= m; i++) {
    for (int j = m + 1; j < sink; j++)
      if (mat[i][j]) {
        g[i].push_back(j);
        g[j].push_back(i);
      }
  }
  vector<vector<int> > ans;
  flagN++;
  flagN++;
  for (int i = 1; i <= n; i++)
    if (flagN != flag[i]) {
      vector<int> v;
      dfs(i, v);
      ans.push_back(v);
    }
  e.insert(e.end(), (o).begin(), (o).end());
  pe.insert(pe.end(), (po).begin(), (po).end());
  printf("%d\n", ((int)ans.size()));
  for (int i = 0; i < ((int)ans.size()); i++) {
    printf("%d", ((int)ans[i].size()));
    for (int j = 0; j < ((int)ans[i].size()); j++)
      printf(" %d", pe[ans[i][j] - 1]);
    printf("\n");
  }
}
bool Flow::dfs(int u, vector<int>& vec) {
  flag[u] = flagN;
  vec.push_back(u);
  for (int i = 0; i < ((int)g[u].size()); i++) {
    int v = g[u][i];
    if (flagN == flag[v]) continue;
    dfs(v, vec);
  }
}
int main() {
  int n;
  genPrime();
  while (scanf("%d", &n) == 1 && n) {
    for (int i = 1; i <= n; i++) {
      scanf("%d", a + i);
      if (a[i] & 1) {
        o.push_back(a[i]);
        po.push_back(i);
      } else {
        e.push_back(a[i]);
        pe.push_back(i);
      }
    }
    if (((int)o.size()) != ((int)e.size())) {
      puts("Impossible");
      continue;
    }
    Flow* mx = new Flow(0, n + 1);
    mx->n = n;
    mx->m = n / 2;
    mx->buildGraph(n);
    int flow = mx->maxFlow();
    if (flow != n)
      puts("Impossible");
    else
      mx->match();
  }
  return 0;
}