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;
class dinic_flow {
 public:
  struct edge {
    int to, rev, cap;
    edge(int to = 0, int rev = 0, int cap = 0) : to(to), rev(rev), cap(cap) {}
  };
  vector<vector<edge> > g;
  vector<vector<edge>::iterator> nowi;
  vector<int> dist;
  int nodes, src, dst;
  queue<int> q;
  void init(int _nodes) {
    nodes = _nodes;
    g.resize(_nodes);
    nowi.resize(_nodes);
    for (int i = 0; i < _nodes; i++) g[i].clear();
    dist.resize(_nodes);
  }
  void add_Edge(int _from, int _to, int _cap) {
    g[_from].push_back(edge(_to, g[_to].size(), _cap));
    g[_to].push_back(edge(_from, g[_from].size() - 1, 0));
  }
  bool dinic_bfs() {
    fill(dist.begin(), dist.end(), -1);
    dist[src] = 0;
    q.push(src);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (int i = 0; i < g[u].size(); i++) {
        edge e = g[u][i];
        if (e.cap) {
          int v = e.to;
          if (dist[v] < 0) dist[v] = dist[u] + 1, q.push(v);
        }
      }
    }
    return dist[dst] >= 0;
  }
  int dinic_dfs(int u, int f) {
    if (u == dst) return f;
    int ret = 0;
    for (vector<edge>::iterator &it = nowi[u]; it != g[u].end(); it++)
      if (it->cap) {
        int v = it->to;
        if (dist[v] == dist[u] + 1) {
          int tmp = dinic_dfs(v, min(f, it->cap));
          it->cap -= tmp, f -= tmp, ret += tmp, g[v][it->rev].cap += tmp;
          if (!f) return ret;
        }
      }
    return ret;
  }
  int maxFlow(int _src, int _dst) {
    src = _src, dst = _dst;
    int flow = 0;
    while (dinic_bfs()) {
      for (int i = 0; i < nodes; i++) nowi[i] = g[i].begin();
      flow += dinic_dfs(_src, 1e9);
    }
    return flow;
  }
} D;
bool p[20202];
void prepare() {
  for (int i = 2; i < 20202; i++)
    if (!p[i])
      for (int j = 2 * i; j < 20202; j += i) p[j] = 1;
}
bool vis[222];
vector<int> adj[222], v[222], e, o;
int n, a[222], ans;
void dfs(int x) {
  vis[x] = 1;
  v[ans].push_back(x);
  for (int i = 0; i < adj[x].size(); i++) {
    int y = adj[x][i];
    if (!vis[y]) dfs(y);
  }
}
int main() {
  prepare();
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", a + i);
  if (n & 1) {
    puts("Impossible");
    return 0;
  }
  for (int i = 1; i <= n; i++) {
    if (a[i] & 1)
      o.push_back(i);
    else
      e.push_back(i);
  }
  D.init(n + 4);
  int S = 0, T = n + 1;
  for (int i = 0; i < e.size(); i++) D.add_Edge(S, e[i], 2);
  for (int i = 0; i < o.size(); i++) D.add_Edge(o[i], T, 2);
  for (int i = 0; i < e.size(); i++) {
    int x = e[i];
    for (int j = 0; j < o.size(); j++) {
      int y = o[j];
      if (!p[a[x] + a[y]]) D.add_Edge(x, y, 1);
    }
  }
  int f = D.maxFlow(S, T);
  if (f != n) {
    puts("Impossible");
    return 0;
  }
  for (int i = 0; i < e.size(); i++) {
    int x = e[i];
    for (int j = 0; j < D.g[x].size(); j++) {
      int y = D.g[x][j].to, z = D.g[x][j].cap;
      if (y == S) continue;
      if (z == 0) {
        adj[x].push_back(y);
        adj[y].push_back(x);
      }
    }
  }
  for (int i = 1; i <= n; i++)
    if (!vis[i]) ans++, dfs(i);
  printf("%d\n", ans);
  for (int i = 1; i <= ans; i++) {
    int sz = v[i].size();
    printf("%d", sz);
    for (int j = 0; j < sz; j++) printf(" %d", v[i][j]);
    puts("");
  }
}