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.
#include <bits/stdc++.h>
using namespace std;
template <class A, class B>
A cvt(B x) {
  stringstream ss;
  ss << x;
  A y;
  ss >> y;
  return y;
}
int isPrime[50001];
vector<int> primes;
void sieve(int n, bool getPrimeList) {
  long long i, f;
  primes.clear();
  isPrime[0] = 0;
  isPrime[1] = 0;
  for (i = 2; i <= n; i++) isPrime[i] = 1;
  for (i = 2; getPrimeList ? i <= n : i * i <= n; i++) {
    if (isPrime[i] == 1) {
      primes.push_back(i);
      f = i;
      while (i * f <= n) {
        isPrime[i * f] = 0;
        f++;
      }
    }
  }
}
namespace MF {
typedef struct {
  int v1;
  int v2;
  int cap;
  int orig;
  int next;
} edge;
typedef struct {
  int first;
  int last;
  int cur;
  int dist;
} node;
int n, m;
node nodes[402];
edge edges[2 * 40400];
void init(int nn) {
  n = nn;
  m = 0;
  for (int i = 0; i < n; i++) nodes[i].first = -1;
}
void addEdge(int f, int t, int c, int directed = 1) {
  node &nf = nodes[f];
  edges[m] = (edge){f, t, c, c, -1};
  if (nf.first == -1) {
    nf.first = m;
    nf.last = m;
  } else {
    edges[nf.last].next = m;
    nf.last = m;
  }
  m++;
  node &nt = nodes[t];
  edges[m] = (edge){t, f, directed ? 0 : c, directed ? 0 : c, -1};
  if (nt.first == -1) {
    nt.first = m;
    nt.last = m;
  } else {
    edges[nt.last].next = m;
    nt.last = m;
  }
  m++;
}
int q[402], head, tail;
int bfs(int source, int sink) {
  for (int i = 0; i < n; i++) nodes[i].dist = -1;
  nodes[source].dist = 0;
  q[0] = source;
  head = 0;
  tail = 1;
  while (head < tail) {
    int x = q[head++];
    for (int i = nodes[x].first; i != -1; i = edges[i].next)
      if (edges[i].cap > 0) {
        int y = edges[i].v2;
        if (nodes[y].dist == -1) {
          nodes[y].dist = nodes[x].dist + 1;
          q[tail++] = y;
        }
      }
  }
  return nodes[sink].dist != -1;
}
int dfs(int x, int sink, int flow = 1000000000) {
  if (x == sink) return flow;
  for (int &i = nodes[x].cur; i != -1; i = edges[i].next)
    if (edges[i].cap > 0) {
      int y = edges[i].v2;
      if (nodes[y].dist != nodes[x].dist + 1) continue;
      int df = dfs(y, sink, min(flow, edges[i].cap));
      if (df > 0) {
        edges[i].cap -= df;
        edges[i ^ 1].cap += df;
        return df;
      }
    }
  return 0;
}
long long maxFlow(int source, int sink) {
  long long flow = 0;
  while (bfs(source, sink)) {
    for (int i = 0; i < n; i++) nodes[i].cur = nodes[i].first;
    while (1) {
      long long df = dfs(source, sink);
      if (df == 0) break;
      flow += df;
    }
  }
  return flow;
}
}  // namespace MF
int main() {
  sieve(20005, false);
  int n;
  int a[200];
  cin >> n;
  int even = 0, odd = 0;
  for (int i = 0; i < (int)(n); i++) {
    cin >> a[i];
    if (a[i] % 2 == 0)
      even++;
    else
      odd++;
  }
  if (even != odd) {
    printf("Impossible\n");
    return 0;
  }
  int source = 2 * n, sink = source + 1;
  MF::init(sink + 1);
  for (int i = 0; i < (int)(n); i++)
    if (a[i] % 2 == 0) MF::addEdge(source, i, 2);
  for (int j = 0; j < (int)(n); j++)
    if (a[j] % 2 == 1) MF::addEdge(n + j, sink, 2);
  for (int i = 0; i < (int)(n); i++)
    if (a[i] % 2 == 0) {
      for (int j = 0; j < (int)(n); j++)
        if (a[j] % 2 == 1) {
          if (isPrime[a[i] + a[j]]) {
            MF::addEdge(i, n + j, 1);
          }
        }
    }
  int mf = MF::maxFlow(source, sink);
  if (mf != 2 * even) {
    printf("Impossible\n");
    return 0;
  }
  vector<vector<int> > tables;
  int used[400] = {};
  for (int i = 0; i < (int)(n); i++)
    if (a[i] % 2 == 0 && !used[i]) {
      vector<int> table;
      int x = i;
      while (!used[x]) {
        table.push_back(x < n ? x : x - n);
        used[x] = 1;
        for (int k = MF::nodes[x].first; k != -1; k = MF::edges[k].next) {
          MF::edge e = MF::edges[k];
          if (e.v1 < 2 * n && e.v2 < 2 * n && !used[e.v2] &&
              ((e.v1 < n && e.cap == 0) || (e.v1 >= n && e.cap == 1))) {
            x = e.v2;
            break;
          }
        }
      }
      tables.push_back(table);
    }
  printf("%d\n", tables.size());
  for (auto table : tables) {
    printf("%d", table.size());
    for (int x : table) printf(" %d", x + 1);
    printf("\n");
  }
  return 0;
}
