#include <bits/stdc++.h>
using namespace std;
const int M = 20480;
bool c[M];
int n;
const int MAXN = 222, MAXM = 30000;
struct Dinic {
  struct edge {
    int x, y;
    int c;
    int f;
    edge *next, *back;
    edge(int x, int y, int c, edge* next)
        : x(x), y(y), c(c), f(0), next(next), back(0) {}
    void* operator new(size_t, void* p) { return p; }
  } * E[MAXN], *data;
  char storage[2 * MAXM * sizeof(edge)];
  int S, T;
  int Q[MAXN];
  int D[MAXN];
  vector<edge*> ee;
  void DFS() {
    memset(D, -1, sizeof(D));
    int head = 0, tail = 0;
    Q[tail++] = S;
    D[S] = 0;
    for (;;) {
      int i = Q[head++];
      for (edge* e = E[i]; e; e = e->next) {
        if (e->c == 0) continue;
        int j = e->y;
        if (D[j] == -1) {
          D[j] = D[i] + 1;
          Q[tail++] = j;
          if (j == T) return;
        }
      }
      if (head == tail) break;
    }
  }
  edge* cur[MAXN];
  edge* path[MAXN];
  int flow() {
    int res = 0;
    int path_n;
    for (;;) {
      DFS();
      if (D[T] == -1) break;
      memcpy(cur, E, sizeof(E));
      path_n = 0;
      int i = S;
      for (;;) {
        if (i == T) {
          int mink = 0;
          int delta = INT_MAX;
          for (int k = 0; k < path_n; ++k) {
            if (path[k]->c < delta) {
              delta = path[k]->c;
              mink = k;
            }
          }
          for (int k = 0; k < path_n; ++k) {
            path[k]->c -= delta;
            path[k]->back->c += delta;
          }
          path_n = mink;
          i = path[path_n]->x;
          res += delta;
        }
        edge* e;
        for (e = cur[i]; e; e = e->next) {
          if (e->c == 0) continue;
          int j = e->y;
          if (D[i] + 1 == D[j]) break;
        }
        cur[i] = e;
        if (e) {
          path[path_n++] = e;
          i = e->y;
        } else {
          D[i] = -1;
          if (path_n == 0) break;
          path_n--;
          i = path[path_n]->x;
        }
      }
    }
    return res;
  }
  void init(int _S, int _T) {
    S = _S, T = _T;
    data = (edge*)storage;
    memset(E, 0, sizeof(E));
  }
  void add_edge(int x, int y, int w) {
    E[x] = new ((void*)data++) edge(x, y, w, E[x]);
    E[y] = new ((void*)data++) edge(y, x, 0, E[y]);
    ee.push_back(E[y]);
    E[x]->back = E[y];
    E[y]->back = E[x];
  }
} dd;
bool ok[256];
vector<int> e[256];
vector<vector<int>> ans;
int main() {
  for (int i = 2; i < M; ++i)
    if (!c[i])
      for (int j = i * i; j < M; j += i) c[j] = true;
  cin >> n;
  c[2] = true;
  int a[256];
  for (int i = 1; i <= n; ++i) cin >> a[i];
  dd.init(0, n + 1);
  for (int i = 1; i <= n; ++i)
    if (a[i] & 1)
      dd.add_edge(0, i, 2);
    else
      dd.add_edge(i, n + 1, 2);
  for (int i = 1; i <= n; ++i)
    if (a[i] & 1)
      for (int j = 1; j <= n; ++j)
        if (!c[a[i] + a[j]]) {
          dd.add_edge(i, j, 1);
        }
  if (dd.flow() != n) return puts("Impossible") & 0;
  for (auto e : dd.ee)
    if (e->c == 1) {
      ::e[e->x].push_back(e->y);
      ::e[e->y].push_back(e->x);
    }
  for (int i = 1; i <= n; ++i)
    if (!ok[i]) {
      ans.push_back({i});
      ok[i] = true;
      vector<int>& v = ans.back();
      for (int j = e[i][0], l = i; j != i;) {
        v.push_back(j);
        ok[j] = true;
        assert(e[j].size() == 2);
        int t = e[j][0] == l ? e[j][1] : e[j][0];
        l = j;
        j = t;
      }
    }
  printf("%d\n", ans.size());
  for (auto v : ans) {
    printf("%d", v.size());
    for (int t : v) printf(" %d", t);
    puts("");
  }
}
