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;
struct edge {
  int to, f, c;
};
vector<edge> e;
vector<int> g1[305], g2[305], g3[305];
vector<int> cycles[205];
int lvl[305], ptr[305], q[305];
int v0, v1 = 250;
int arr[205], color[205];
bool u[205];
inline void add_edge(int v, int to, int c) {
  g1[v].push_back(e.size());
  e.push_back({to, 0, c});
  g1[to].push_back(e.size());
  e.push_back({v, 0, 0});
}
inline bool exist() {
  for (int i = v0; i <= v1; ++i) {
    lvl[i] = 0;
  }
  lvl[v0] = 1;
  int l = 0, r = 0;
  q[++r] = v0;
  while (l < r) {
    int v = q[++l];
    for (int i = 0, id, to; i < g1[v].size(); ++i) {
      id = g1[v][i];
      to = e[id].to;
      if (e[id].f < e[id].c && !lvl[to]) {
        lvl[to] = lvl[v] + 1;
        q[++r] = to;
      }
    }
  }
  return lvl[v1];
}
int dinic(int v, int flow) {
  if (v == v1 || !flow) {
    return flow;
  }
  for (int id, to, f, c; ptr[v] < g1[v].size(); ++ptr[v]) {
    id = g1[v][ptr[v]];
    to = e[id].to;
    f = e[id].f;
    c = e[id].c;
    if (lvl[to] != lvl[v] + 1) {
      continue;
    }
    int pushed = dinic(to, (flow < c - f ? flow : c - f));
    if (pushed > 0) {
      e[id].f += pushed;
      e[id ^ 1].f -= pushed;
      return pushed;
    }
  }
  return 0;
}
inline int max_flow() {
  int res = 0;
  while (exist()) {
    for (int i = v0; i <= v1; ++i) {
      ptr[i] = 0;
    }
    while (int pushed = dinic(v0, 10000)) {
      res += pushed;
    }
  }
  return res;
}
inline void precalc(int n) {
  vector<char> isP(20005, 0);
  for (int i = 2; i <= 20000; ++i) {
    isP[i] = 1;
  }
  for (int i = 2; i * i <= 20000; ++i) {
    if (isP[i]) {
      for (int j = i * i; j <= 20000; j += i) {
        isP[j] = 0;
      }
    }
  }
  for (int i = 1; i <= n; ++i) {
    for (int j = i + 1; j <= n; ++j) {
      if (isP[arr[i] + arr[j]]) {
        g2[i].push_back(j);
        g2[j].push_back(i);
      }
    }
  }
}
bool pre_dfs(int v, int k) {
  color[v] = k + 1;
  for (int i = 0, to; i < g2[v].size(); ++i) {
    to = g2[v][i];
    if (!color[to]) {
      if (!pre_dfs(to, k ^ 1)) {
        return 0;
      }
    } else {
      if (color[to] != (k ^ 1) + 1) {
        return 0;
      }
    }
  }
  return 1;
}
inline void prepare(int n) {
  for (int i = 1; i <= n; ++i) {
    if (color[i] == 1) {
      add_edge(i, v1, 2);
    } else {
      add_edge(v0, i, 2);
      for (int j = 0; j < g2[i].size(); ++j) {
        add_edge(i, g2[i][j], 1);
      }
    }
  }
}
void dfs(int v, int id) {
  cycles[id].push_back(v);
  u[v] = 1;
  for (int i = 0, to; i < g3[v].size(); ++i) {
    to = g3[v][i];
    if (!u[to]) {
      dfs(to, id);
    }
  }
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 1; i <= n; ++i) {
    scanf("%d", &arr[i]);
  }
  precalc(n);
  for (int i = 1; i <= n; ++i) {
    if (!color[i]) {
      if (!pre_dfs(i, 1)) {
        printf("Impossible");
        return 0;
      }
    }
  }
  prepare(n);
  if (max_flow() != n) {
    printf("Impossible");
  } else {
    for (int i = 1; i <= n; ++i) {
      if (color[i] == 2) {
        for (int j = 0; j < g1[i].size(); ++j) {
          if (e[g1[i][j]].f == e[g1[i][j]].c) {
            g3[i].push_back(e[g1[i][j]].to);
            g3[e[g1[i][j]].to].push_back(i);
          }
        }
      }
    }
    int cnt = 0;
    for (int i = 1; i <= n; ++i) {
      if (!u[i]) {
        dfs(i, cnt++);
      }
    }
    printf("%d\n", cnt);
    for (int i = 0; i < cnt; ++i) {
      printf("%d ", cycles[i].size());
      for (int j = 0; j < cycles[i].size(); ++j) {
        printf("%d ", cycles[i][j]);
      }
      printf("\n");
    }
  }
  return 0;
}
