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;
mt19937 rnd(chrono::high_resolution_clock::now().time_since_epoch().count());
const int inf = 0x3f3f3f3f;
const long long mod = 2007;
const int maxn = 1e5 + 5;
const int maxm = 30;
const double eps = 1e-8;
const double pi = acos(-1.0);
struct Link {
  int num, head[maxn];
  struct Edge {
    int v, w, next;
  } edge[maxn << 1];
  void init() {
    num = 0;
    memset(head, -1, sizeof(head));
  }
  void add_edge(int u, int v, int w) {
    edge[num].v = v;
    edge[num].w = w;
    edge[num].next = head[u];
    head[u] = num++;
  }
} link;
struct ISAP {
  int n, m, s, t;
  int dep[maxn], pre[maxn];
  int cnt[maxn], cur[maxn];
  int maxflow;
  void init() {
    maxflow = 0;
    memset(dep, 0, sizeof(dep));
    memset(pre, 0, sizeof(pre));
    memset(cnt, 0, sizeof(cnt));
    memset(cur, 0, sizeof(cur));
  }
  void auto_add(int u, int v, int w) {
    link.add_edge(u, v, w);
    link.add_edge(v, u, 0);
  }
  void bfs(int t) {
    queue<int> q;
    for (int i = 1; i <= n; i++) cur[i] = link.head[i];
    for (int i = 1; i <= n; i++) dep[i] = n;
    dep[t] = 0, q.push(t);
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      for (int i = link.head[u]; i != -1; i = link.edge[i].next)
        if (dep[link.edge[i].v] == n && link.edge[i ^ 1].w) {
          dep[link.edge[i].v] = dep[u] + 1;
          q.push(link.edge[i].v);
        }
    }
  }
  int add_flow(int s, int t) {
    int ans = inf, u = t;
    while (u != s) {
      ans = min(ans, link.edge[pre[u]].w);
      u = link.edge[pre[u] ^ 1].v;
    }
    u = t;
    while (u != s) {
      link.edge[pre[u]].w -= ans;
      link.edge[pre[u] ^ 1].w += ans;
      u = link.edge[pre[u] ^ 1].v;
    }
    return ans;
  }
  int cal_maxflow(int s, int t) {
    int u = s;
    bfs(t);
    for (int i = 1; i <= n; i++) cnt[dep[i]]++;
    while (dep[s] < n) {
      if (u == t) maxflow += add_flow(s, t), u = s;
      bool flag = 0;
      for (int &i = cur[u]; i != -1; i = link.edge[i].next)
        if (dep[u] == dep[link.edge[i].v] + 1 && link.edge[i].w) {
          flag = 1;
          u = link.edge[i].v;
          pre[link.edge[i].v] = i;
          break;
        }
      if (!flag) {
        int min1 = n - 1;
        for (int i = link.head[u]; i != -1; i = link.edge[i].next)
          if (link.edge[i].w) min1 = min(min1, dep[link.edge[i].v]);
        if ((--cnt[dep[u]]) == 0) break;
        cnt[dep[u] = min1 + 1]++;
        cur[u] = link.head[u];
        if (u != s) u = link.edge[pre[u] ^ 1].v;
      }
    }
    return maxflow;
  }
} isap;
int n, a[205];
int num0 = 0, num1 = 0;
bool vis[20005];
int prime[20005];
void get_prime() {
  int up = 2e4;
  int cnt = 0;
  memset(vis, 0, sizeof(vis));
  vis[1] = 1;
  for (int i = 2; i <= up; i++) {
    if (!vis[i]) prime[++cnt] = i;
    for (int j = 1; j <= cnt && i * prime[j] <= up; j++) {
      vis[i * prime[j]] = 1;
      if (i % prime[j] == 0) break;
    }
  }
}
int now = 0;
vector<int> v[205];
bool used[205];
int find(int x, int y) {
  for (int i = link.head[y]; i != -1; i = link.edge[i].next) {
    int nxt = link.edge[i].v;
    int w = link.edge[i].w;
    if (i % 2 == 1 && nxt <= n && w == 1 && nxt != x) return nxt;
  }
  return 0;
}
void dfs(int x) {
  used[x] = 1;
  v[now].push_back(x);
  for (int i = link.head[x]; i != -1; i = link.edge[i].next) {
    int nxt = link.edge[i].v;
    int w = link.edge[i].w;
    if (i % 2 == 0 && w == 0 && nxt <= n && !used[nxt]) {
      used[nxt] = 1;
      v[now].push_back(nxt);
      nxt = find(x, nxt);
      if (!used[nxt]) dfs(nxt);
      break;
    }
  }
}
int main() {
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
  for (int i = 1; i <= n; i++)
    if (a[i] % 2 == 0)
      num0++;
    else
      num1++;
  if (num0 != num1) {
    puts("Impossible");
    return 0;
  }
  get_prime();
  link.init();
  isap.init();
  isap.n = n + 2;
  isap.s = n + 1;
  isap.t = n + 2;
  for (int i = 1; i <= n; i++)
    for (int j = 1; j <= n; j++)
      if (i != j && !vis[a[i] + a[j]] && a[i] % 2 == 1 && a[j] % 2 == 0)
        isap.auto_add(i, j, 1);
  for (int i = 1; i <= n; i++)
    if (a[i] % 2 == 1)
      isap.auto_add(isap.s, i, 2);
    else
      isap.auto_add(i, isap.t, 2);
  int ans = isap.cal_maxflow(isap.s, isap.t);
  if (ans != n) {
    puts("Impossible");
    return 0;
  }
  memset(used, 0, sizeof(used));
  for (int i = 1; i <= n; i++)
    if (a[i] % 2 == 1 && !used[i]) now++, dfs(i);
  printf("%d\n", now);
  for (int i = 1; i <= now; i++) {
    printf("%d", v[i].size()), printf(" ");
    for (auto x : v[i]) printf("%d", x), printf(" ");
    puts("");
  }
  return 0;
}