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.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskE solver = new TaskE();
        solver.solve(in, out);
        out.close();
    }
}


class Edge {
    int from;
    int to;
    int capacity;
    int flow;

    public Edge(int from, int to, int capacity, int flow) {
        this.from = from;
        this.to = to;
        this.capacity = capacity;
        this.flow = flow;
    }
}

class Graph {
    private List<Integer> graph[];

    private List<Edge> edges;

    @SuppressWarnings("unchecked")
    public Graph(int n) {
        edges = new ArrayList<>();
        graph = new List[n];
        for (int i = 0; i < n; i++) {
            graph[i] = new ArrayList<>();
        }
    }

    public void addEdge(int from, int to, int capacity) {
        Edge edgeForward = new Edge(from, to, capacity, 0);
        Edge edgeBackward = new Edge(to, from, 0, 0);
        graph[from].add(edges.size());
        edges.add(edgeForward);
        graph[to].add(edges.size());
        edges.add(edgeBackward);
    }

    public List<Integer> getEdgesID(int vertex) {
        return graph[vertex];
    }

    public Edge getEdge(int edgeID) {
        return edges.get(edgeID);
    }

    public void addFlow(int edgeID, int pushed) {
        Edge edge = edges.get(edgeID);
        edge.flow += pushed;
    }

    public List<Edge> getEdges() {
        return edges;
    }
}




class TaskE {

    private final int INFINITY = Integer.MAX_VALUE;

    private int level[];

    private int begin[];

    private int MAXN = 205;

    private int tab[];
    private int weights[];

    public void solve(InputReader in, OutputWriter out) {
        int n = in.nextInt();
        int source = 200;
        int sink = 201;
        level = new int[MAXN];
        begin = new int[MAXN];
        Graph graph = new Graph(MAXN);
        List<Integer> ages = new ArrayList<>(n);
        int age;
        int evenCount = 0;
        for (int i = 0; i < n; i++) {
            age = in.nextInt();
            if((age & 1) == 0) {
                graph.addEdge(source, i, 2);
                evenCount++;
            } else {
                graph.addEdge(i, sink, 2);
            }
            ages.add(age);
        }
        for (int i = 0; i < ages.size(); i++) {
            if((ages.get(i) & 1) == 0) {
                for (int j = 0; j < ages.size(); j++) {
                    if(isPrime(ages.get(i)+ages.get(j))) {
                        graph.addEdge(i,j,1);
                    }
                }
            }
        }
        int maxFlow = dinic(graph, source, sink);
        if(maxFlow != 2*evenCount) {
            out.printLine("Impossible");
            return;
        }
        printResult(graph, n, ages,out);

    }

    private void printResult(Graph graph, int n, List<Integer> ages, OutputWriter out) {
        boolean used[] = new boolean[n];
        List<List<Integer>> result = new ArrayList<>();
        for(int i=0;i<n;i++) {
            if(!used[i]) {
                List<Integer> table = new ArrayList<>();
                dfs2(graph, used, table, i, ages);
                result.add(table);
            }
        }
        out.printLine(result.size());
        for (List<Integer> list : result) {
            out.print(list.size() + " ");
            for (int value : list) {
                out.print((value+1) + " ");
            }
            out.printLine();
        }
    }

    private void dfs2(Graph graph, boolean[] used, List<Integer> table, int vertex, List<Integer> ages) {
        if(vertex > used.length || used[vertex]) return;
        table.add(vertex);
        used[vertex] = true;
        for (int edgeID : graph.getEdgesID(vertex)) {
            Edge edge = graph.getEdge(edgeID);
            if(ages.get(vertex) % 2 == 0 && edge.flow == 1) {
                dfs2(graph, used, table, edge.to, ages);
            } else if(ages.get(vertex) % 2 == 1 && edge.flow == -1) {
                dfs2(graph, used, table, edge.to, ages);
            }
        }
    }


    private boolean isPrime(int n) {
        if(n == 2) return true;
        if ((n&1)==0) return false;
        for(int i=3;i*i<=n;i+=2) {
            if(n%i==0)
                return false;
        }
        return true;
    }

    private int dinic(Graph graph, int source, int sink) {
        int maxFlow = 0;
        int pushed = 0;
        while(bfs(graph, source, sink)) {
            for (int i = 0; i < begin.length; i++) {
                begin[i] = 0;
            }
            while((pushed = dfs(graph, source, sink, INFINITY)) > 0) {
                maxFlow += pushed;
            }
        }
        return maxFlow;
    }

    private int dfs(Graph graph, int vertex, int sink, int flow) {
        if (flow <= 0) return 0;
        if (vertex == sink) return flow;
        List<Edge> edges = graph.getEdges();
        List<Integer> edgesID = graph.getEdgesID(vertex);
        for (;begin[vertex] < edgesID.size(); ++begin[vertex]) {
            int edgeID = edgesID.get(begin[vertex]);
            Edge edge = edges.get(edgeID);
            if (level[vertex] + 1 != level[edge.to]) continue;
            int pushed = dfs(graph, edge.to, sink, Math.min(flow, edge.capacity - edge.flow));
            if (pushed > 0) {
                graph.addFlow(edgeID, pushed);
                graph.addFlow(edgeID ^ 1, -pushed);
                return pushed;
            }
        }
        return 0;
    }

    private boolean bfs(Graph graph, int source, int sink) {
        for (int i = 0; i < level.length; i++) {
            level[i] = -1;
        }
        level[source] = 0;
        Queue<Integer> queue = new ArrayDeque<>();
        queue.add(source);
        int vertex;
        while (!queue.isEmpty()) {
            vertex = queue.remove();
            for (int edgeID : graph.getEdgesID(vertex)) {
                Edge edge = graph.getEdge(edgeID);
                if(level[edge.to] == -1 && edge.flow < edge.capacity) {
                    queue.add(edge.to);
                    level[edge.to] = level[vertex] + 1;
                }
            }
        }
        return level[sink] != -1;
    }
}




class InputReader {
    public BufferedReader reader;
    public StringTokenizer tokenizer;
    public InputReader(InputStream stream) {
        reader = new BufferedReader(new InputStreamReader(stream), 32768);
        tokenizer = null;
    }
    public String next() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                tokenizer = new StringTokenizer(reader.readLine());
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return tokenizer.nextToken();
    }
    public boolean hasNext() {
        while (tokenizer == null || !tokenizer.hasMoreTokens()) {
            try {
                String line = reader.readLine();
                if ( line == null ) {
                    return false;
                }
                tokenizer = new StringTokenizer(line);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
    public int nextInt() {
        return Integer.parseInt(next());
    }
    public long nextLong() {
        return Long.parseLong(next());
    }
    public double nextDouble() { return Double.parseDouble(next());}
}
class OutputWriter {
    private final PrintWriter writer;
    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }
    public OutputWriter(Writer writer) {
        this.writer = new PrintWriter(writer);
    }
    public void print(Object... objects) {
        for (int i = 0; i < objects.length; i++) {
            if ( i != 0 ) {
                writer.print(' ');
            }
            writer.print(objects[i]);
        }
    }
    public void printLine(Object... objects) {
        print(objects);
        writer.println();
    }
    public void close() {
        writer.close();
    }
}