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 JAVA):

Solution:
import java.util.*;
import java.io.*;

public class Main{

    BufferedReader in;
    StringTokenizer str = null;
    PrintWriter out;

    private String next() throws Exception{
        while (str == null || !str.hasMoreElements())
            str = new StringTokenizer(in.readLine());
        return str.nextToken();
    }
    
    private int nextInt() throws Exception{
       return Integer.parseInt(next());
    }

    final static int MAXN = (int)(3 * 1e4);
    MaxFlowMinCost mfmc;
    Set<Integer> []g;
    boolean []used;
    
    public void run() throws Exception{
        in = new BufferedReader(new InputStreamReader(System.in));
        out = new PrintWriter(System.out);

        boolean prime[] = new boolean[MAXN];
        Arrays.fill(prime, true);
        for(int i = 2; i < MAXN; ++i) {
            if (prime[i]) {
                if (1L * i * i >= MAXN) continue;
                for(int j = i * i; j < MAXN; j += i) {
                    prime[j] = false;
                }
            }
        }
        // for(int i = 2; i < 100; ++i) {
        //     if (prime[i]) {
        //         System.out.println(i);
        //     }
        // }
        int n = nextInt();
        int []a = new int[n];
        for(int i = 0; i < n; ++i) a[i] = nextInt();
        int source = n, sink = n + 1;

        mfmc = new MaxFlowMinCost(n + 2, source, sink);
        for(int i = 0; i < n; ++i) {
            if (a[i] % 2 == 0) {
                mfmc.addEdge(source, i, 2);
            }else {
                mfmc.addEdge(i, sink, 2);
            }
        }

        for(int i = 0; i < n; ++i) {
            for(int j = 0; j < n; ++j) {
                if (prime[a[i] + a[j]]) {
                    if (a[i] % 2 == 0) {
                        mfmc.addEdge(i, j, 1);
                    }
                }
            }
        }

        mfmc.execute();
        if (mfmc.flow != n) {
            out.println("Impossible");
            out.close();
            return;
        }

        g = new HashSet[n];
        for(int i = 0; i < n; ++i) g[i] = new HashSet<>();
        for(Edge e : mfmc.e) {
            // System.out.println(e);
            if (e.cap != e.flow || e.back) continue;
            if (e.from == source || e.to == source) continue;
            if (e.from == sink || e.to == sink) continue;
            int v = e.from, u = e.to;
            g[v].add(u);
            g[u].add(v);
        }

        // for(int i = 0; i < n; ++i) {
        //     System.out.print(i + "-> ");
        //     for(int j : g[i]) {
        //         System.out.print(j + " ");
        //     }
        //     System.out.println();
        // }

        List<Integer> path = new ArrayList<>();
        int cmp = 0;
        used = new boolean[n];
        for(int i = 0; i < n; ++i) {
            if (!used[i]) {
                ++cmp;
                path.clear();
                euler(i, path);
                out.print(path.size() + " ");
                for(int j : path) {
                    used[j] = true;
                    out.print((j+1) + " ");
                }
                out.println();
            }
        }
        System.out.println(cmp);
        out.close();
    }

    private void euler(int x, List<Integer> path) {
        Stack<Integer> stack = new Stack<Integer>();
        stack.add(x);
        while(stack.size() > 0) {
            int v = stack.peek();
            if (g[v].size() == 0) {
                path.add(v);
                stack.pop();
            }else {
                Iterator<Integer> it = g[v].iterator();
                int u = it.next();
                g[v].remove(u);
                g[u].remove(v);
                stack.add(u);
            }
        }
        path.remove(path.size()-1);
    }

    class Edge {
        int from, to, cap, flow;
        boolean back;
        public Edge(int from, int to, int cap, int flow) {
            this.from = from;
            this.to = to;
            this.cap = cap;
            this.flow = flow;
            this.back = false;
            if (cap == flow) this.back = true;
        }

        public String toString() {
            return "[ from=" + from + ", to=" + to + ", cap=" + cap + ", flow=" + flow + " ]";
        }
    }

    final static int oo = Integer.MAX_VALUE / 2;

    class MaxFlowMinCost {
        int n, source, sink;

        List<Integer> []g;
        List<Edge> e;

        int []ptr, q, d;
        boolean []inqueue;
        int flow;

        public MaxFlowMinCost(int n, int source, int sink) {
            this.n = n;
            this.source = source;
            this.sink = sink;

            g = new ArrayList[n];
            for(int i = 0; i < n; ++i) g[i] = new ArrayList<>();
            e = new ArrayList<Edge>();

            ptr = new int[n];
            q = new int[n];
            d = new int[n];
            inqueue = new boolean[n];
        }

        public void execute() {
            while(bfs()) {
                Arrays.fill(ptr, 0);
                while(true) {
                    int pushed = dfs(source, oo);
                    if (pushed == 0) break;
                    flow += pushed;
                }
            }
        }

        private int dfs(int v, int flow) {
            if (flow == 0) return 0;
            if (v == sink) return flow;
            for(;ptr[v] < g[v].size(); ++ptr[v]) {
                int id = g[v].get(ptr[v]);
                Edge edge = e.get(id);
                if (d[edge.to] != d[v] + 1) continue;
                int pushed = dfs(edge.to, Math.min(flow, edge.cap - edge.flow));
                if (pushed > 0) {
                    e.get(id).flow += pushed;
                    e.get(id ^ 1).flow -= pushed;

                    return pushed;
                }
            }
            return 0;
        }

        private boolean bfs(){
            Arrays.fill(inqueue, false);
            Arrays.fill(d, oo);
            d[source] = 0;
            inqueue[source] = true;
            int head = 0, tail = 0;
            q[tail++] = source;

            while(head != tail && d[sink] == oo) {
                int v = q[head++];
                for(int id : g[v]) {
                    Edge edge = e.get(id);
                    if (edge.cap == edge.flow) continue;
                    if (d[edge.to] > d[v] + 1) {
                        d[edge.to] = d[v] + 1;
                        if (inqueue[edge.to]) continue;
                        inqueue[edge.to] = true;
                        q[tail++] = edge.to;
                        if (tail == n) tail = 0;
                    }
                }
                if (head == n) head = 0;
                inqueue[v] = false;
            }

            return d[sink] != oo;
        }

        public void addEdge(int from, int to, int cap) {
            g[from].add(e.size());
            e.add(new Edge(from, to, cap, 0));
            g[to].add(e.size());
            e.add(new Edge(to, from, cap, cap));
        }
    }

    public static void main(String args[]) throws Exception{
       new Main().run();
    }
}