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;
const int M = 20480;
bool c[M];
int n;
const int MAXN = 222, MAXM = 30000;
struct Dinic {
  struct edge {
    int x, y;
    int c;
    int f;
    edge *next, *back;
    edge(int x, int y, int c, edge* next)
        : x(x), y(y), c(c), f(0), next(next), back(0) {}
    void* operator new(size_t, void* p) { return p; }
  } * E[MAXN], *data;
  char storage[2 * MAXM * sizeof(edge)];
  int S, T;
  int Q[MAXN];
  int D[MAXN];
  vector<edge*> ee;
  void DFS() {
    memset(D, -1, sizeof(D));
    int head = 0, tail = 0;
    Q[tail++] = S;
    D[S] = 0;
    for (;;) {
      int i = Q[head++];
      for (edge* e = E[i]; e; e = e->next) {
        if (e->c == 0) continue;
        int j = e->y;
        if (D[j] == -1) {
          D[j] = D[i] + 1;
          Q[tail++] = j;
          if (j == T) return;
        }
      }
      if (head == tail) break;
    }
  }
  edge* cur[MAXN];
  edge* path[MAXN];
  int flow() {
    int res = 0;
    int path_n;
    for (;;) {
      DFS();
      if (D[T] == -1) break;
      memcpy(cur, E, sizeof(E));
      path_n = 0;
      int i = S;
      for (;;) {
        if (i == T) {
          int mink = 0;
          int delta = INT_MAX;
          for (int k = 0; k < path_n; ++k) {
            if (path[k]->c < delta) {
              delta = path[k]->c;
              mink = k;
            }
          }
          for (int k = 0; k < path_n; ++k) {
            path[k]->c -= delta;
            path[k]->back->c += delta;
          }
          path_n = mink;
          i = path[path_n]->x;
          res += delta;
        }
        edge* e;
        for (e = cur[i]; e; e = e->next) {
          if (e->c == 0) continue;
          int j = e->y;
          if (D[i] + 1 == D[j]) break;
        }
        cur[i] = e;
        if (e) {
          path[path_n++] = e;
          i = e->y;
        } else {
          D[i] = -1;
          if (path_n == 0) break;
          path_n--;
          i = path[path_n]->x;
        }
      }
    }
    return res;
  }
  void init(int _S, int _T) {
    S = _S, T = _T;
    data = (edge*)storage;
    memset(E, 0, sizeof(E));
  }
  void add_edge(int x, int y, int w) {
    E[x] = new ((void*)data++) edge(x, y, w, E[x]);
    E[y] = new ((void*)data++) edge(y, x, 0, E[y]);
    ee.push_back(E[y]);
    E[x]->back = E[y];
    E[y]->back = E[x];
  }
} dd;
bool ok[256];
vector<int> e[256];
vector<vector<int>> ans;
int main() {
  for (int i = 2; i < M; ++i)
    if (!c[i])
      for (int j = i * i; j < M; j += i) c[j] = true;
  cin >> n;
  c[2] = true;
  int a[256];
  for (int i = 1; i <= n; ++i) cin >> a[i];
  dd.init(0, n + 1);
  for (int i = 1; i <= n; ++i)
    if (a[i] & 1)
      dd.add_edge(0, i, 2);
    else
      dd.add_edge(i, n + 1, 2);
  for (int i = 1; i <= n; ++i)
    if (a[i] & 1)
      for (int j = 1; j <= n; ++j)
        if (!c[a[i] + a[j]]) {
          dd.add_edge(i, j, 1);
        }
  if (dd.flow() != n) return puts("Impossible") & 0;
  for (auto e : dd.ee)
    if (e->c == 1) {
      ::e[e->x].push_back(e->y);
      ::e[e->y].push_back(e->x);
    }
  for (int i = 1; i <= n; ++i)
    if (!ok[i]) {
      ans.push_back({i});
      ok[i] = true;
      vector<int>& v = ans.back();
      for (int j = e[i][0], l = i; j != i;) {
        v.push_back(j);
        ok[j] = true;
        assert(e[j].size() == 2);
        int t = e[j][0] == l ? e[j][1] : e[j][0];
        l = j;
        j = t;
      }
    }
  printf("%d\n", ans.size());
  for (auto v : ans) {
    printf("%d", v.size());
    for (int t : v) printf(" %d", t);
    puts("");
  }
}