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;
const int INF = 0x7fffffff;
const int MAX = 205;
struct Edge {
  int from, to, cap, flow;
  Edge() {}
  Edge(int from, int to, int cap, int flow)
      : from(from), to(to), cap(cap), flow(flow) {}
};
vector<Edge> edges;
vector<int> G[MAX];
int d[MAX], cur[MAX], vis[MAX];
void addEdge(int from, int to, int cap) {
  edges.push_back(Edge(from, to, cap, 0));
  edges.push_back(Edge(to, from, 0, 0));
  int m = edges.size();
  G[from].push_back(m - 2);
  G[to].push_back(m - 1);
}
bool bfs(int st, int ed) {
  queue<int> q;
  memset(d, 0, sizeof(d));
  memset(vis, false, sizeof(vis));
  q.push(st);
  d[st] = 0;
  vis[st] = true;
  while (!q.empty()) {
    int u = q.front();
    q.pop();
    for (int i = 0; i < G[u].size(); i++) {
      Edge& e = edges[G[u][i]];
      if (!vis[e.to] && e.cap > e.flow) {
        vis[e.to] = true;
        d[e.to] = d[u] + 1;
        q.push(e.to);
      }
    }
  }
  return vis[ed];
}
int dfs(int u, int a, int ed) {
  if (u == ed || a == 0) return a;
  int flow = 0, f;
  for (int& i = cur[u]; i < G[u].size(); i++) {
    Edge& e = edges[G[u][i]];
    if (d[u] + 1 == d[e.to] &&
        (f = dfs(e.to, min(a, e.cap - e.flow), ed)) > 0) {
      e.flow += f;
      edges[G[u][i] ^ 1].flow -= f;
      flow += f;
      a -= f;
      if (a == 0) break;
    }
  }
  return flow;
}
int maxFlow(int st, int ed) {
  int flow = 0;
  while (bfs(st, ed)) {
    memset(cur, 0, sizeof(cur));
    flow += dfs(st, INF, ed);
  }
  return flow;
}
vector<vector<int> > ans;
vector<int> G2[MAX], vec;
bool vis2[MAX];
void dfs2(int u) {
  vis2[u] = true;
  vec.push_back(u);
  for (int i = 0; i < G2[u].size(); i++) {
    int v = G2[u][i];
    if (!vis2[v]) dfs2(v);
  }
}
bool isPrime(int n) {
  if (n == 1) return false;
  for (int i = 2; i * i <= n; i++)
    if (n % i == 0) return false;
  return true;
}
int num[MAX];
int main() {
  int n;
  while (scanf("%d", &n) != EOF) {
    int oddNum = 0, evenNum = 0;
    for (int i = 0; i < n; i++) {
      scanf("%d", &num[i]);
      if (num[i] & 1)
        oddNum++;
      else
        evenNum++;
    }
    if (oddNum != evenNum) {
      puts("Impossible");
      continue;
    }
    int st = n;
    int ed = n + 1;
    edges.clear();
    for (int i = 0; i < n + 2; i++) G[i].clear();
    for (int i = 0; i < n; i++) {
      if (num[i] & 1)
        addEdge(st, i, 2);
      else
        addEdge(i, ed, 2);
      for (int j = i + 1; j < n; j++) {
        if (isPrime(num[i] + num[j])) {
          if (num[i] & 1)
            addEdge(i, j, 1);
          else
            addEdge(j, i, 1);
        }
      }
    }
    int flow = maxFlow(st, ed);
    if (flow == n) {
      for (int i = 0; i < n; i++) G2[i].clear();
      for (int i = 0; i < edges.size(); i++) {
        Edge e = edges[i];
        if (e.cap == 1 && e.flow == 1) {
          G2[e.from].push_back(e.to);
          G2[e.to].push_back(e.from);
        }
      }
      ans.clear();
      memset(vis2, false, sizeof(vis2));
      for (int i = 0; i < n; i++) {
        if (!vis2[i]) {
          vec.clear();
          dfs2(i);
          ans.push_back(vec);
        }
      }
      printf("%d\n", ans.size());
      for (int i = 0; i < ans.size(); i++) {
        printf("%d", ans[i].size());
        for (int j = 0; j < ans[i].size(); j++) printf(" %d", ans[i][j] + 1);
        putchar('\n');
      }
    } else
      puts("Impossible");
  }
  return 0;
}
