#include <algorithm>  
#include <iostream>  
#include <sstream>  
#include <string>  
#include <vector>  
#include <queue>  
#include <set>  
#include <map>  
#include <cstdio>  
#include <cstdlib>  
#include <cctype>  
#include <cmath>  
#include <cstring>
#include <list>  
#include <cassert>
#include <climits>
#include <bitset>
#include <chrono>
#include <random>
using namespace std;

#define PB push_back  
#define MP make_pair  
#define SZ(v) ((int)(v).size())  
#define FOR(i,a,b) for(int i=(a);i<(b);++i)  
#define REP(i,n) FOR(i,0,n)  
#define FORE(i,a,b) for(int i=(a);i<=(b);++i)  
#define REPE(i,n) FORE(i,0,n)  
#define FORSZ(i,a,v) FOR(i,a,SZ(v))  
#define REPSZ(i,v) REP(i,SZ(v))  
std::mt19937 rnd((int)std::chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
ll gcd(ll a,ll b) { return b==0?a:gcd(b,a%b); }

const int MAXN = 8;
struct P { int x, y; P() {} P(int x, int y) :x(x), y(y) {} };

int n;
char s[(1 << MAXN) + 1];
vector<P> ans;

bool solve() {
	if (s[0] == '0') return false;
	vector<int> todo;
	REP(mask, 1 << n) {
		bool anysub = false;
		for (int sub = 0; sub < mask; sub = (sub + (1 << n) - 1 - mask + 1)&mask) if (s[sub] == '0') anysub = true;
		if (s[mask] == '1' && anysub) return false;
		if (s[mask] == '0' && !anysub) todo.PB(mask);
	}
	ans.clear();
	//printf("TODO:"); REPSZ(i, todo) printf(" %x", todo[i]); puts("");
	REPSZ(i, todo) {
		int mask = todo[i];
		vector<int> cur; REP(j, n) if (mask&(1 << j)) cur.PB(j);
		vector<P> path;
		for (int j = SZ(cur) - 1; j >= 0; --j) {
			int x = cur[j];
			if (SZ(path) == 0) {
				path.PB(P(x, 1)); path.PB(P(x + 1, 1)); path.PB(P(x + 1, 0)); path.PB(P(x, 0));
			} else {
				vector<P> oldpath = path; path.clear();
				FOR(xx, x, oldpath[0].x) path.PB(P(xx, 1));
				REPSZ(k, oldpath) path.PB(oldpath[k]);
				for (int xx = oldpath[0].x; xx >= x; --xx) path.PB(P(xx, 1));
				path.PB(P(x, 0));
				path.PB(P(x + 1, 0));
				FORE(xx, x + 1, oldpath[0].x) path.PB(P(xx, 1));
				for (int k = SZ(oldpath) - 1; k >= 0; --k) path.PB(oldpath[k]);
				for (int xx = oldpath[0].x - 1; xx >= x + 1; --xx) path.PB(P(xx, 1));
				path.PB(P(x + 1, 0));
				path.PB(P(x, 0));
			}
		}
		REP(xx, path[0].x) ans.PB(P(xx, 1));
		REPSZ(k, path) ans.PB(path[k]);
		for (int xx = path[0].x; xx >= 1; --xx) ans.PB(P(xx, 1));
	}
	ans.PB(P(0, 1));
	return true;
}

void run() {
	scanf("%d", &n);
	scanf("%s", s); assert(strlen(s) == (1 << n));
	if (!solve()) { printf("Impossible\n"); return; }
	printf("Possible\n");
	printf("%d\n", SZ(ans) - 1);
	REPSZ(i, ans) printf("%d %d\n", ans[i].x, ans[i].y);
}

void verify() {
	int len = SZ(ans) - 1;
	REP(i, len) {
		P a = ans[i], b = ans[i + 1];
		int dx = b.x - a.x, dy = b.y - a.y;
		assert(abs(dx) + abs(dy) == 1);
	}
	assert(ans[0].x == ans[len].x&&ans[0].y == ans[len].y);
	vector<int> seq;
	REP(i, len) {
		P a = ans[i], b = ans[i + 1];
		int dx = b.x - a.x, dy = b.y - a.y, lx = min(a.x, b.x), ly = min(a.y, b.y);
		if (abs(dx) == 1) seq.PB(2 * lx + ly);
	}
	//printf("seq:"); REPSZ(i, seq) printf(" %d", seq[i]); puts("");
	REP(mask, 1 << n) {
		vector<int> nseq;
		REPSZ(i, seq) { int x = seq[i] / 2; if (mask&(1 << x)) nseq.PB(seq[i]); }
		//printf("\tnseq:"); REPSZ(i, nseq) printf(" %d", nseq[i]); puts("");
		vector<int> rem;
		REPSZ(i, nseq) {
			if (SZ(rem) > 0 && nseq[i] == rem.back()) rem.pop_back(); else rem.PB(nseq[i]);
		}
		bool have = SZ(rem) == 0;
		bool want = s[mask] == '1';
		assert(have == want);
	}
}

void stress() {
	REP(rep, 100000) {
		n = 4; // rnd() % 3 + 1;
		REP(i, 1 << n) s[i] = '0' + rnd() % 2; s[1 << n] = '\0';
		bool have = solve();
		if (have) {
			printf("done %d: %s (%s)\n", n, s, have ? "POSSIBLE" : "IMPOSSIBLE");
			//printf("%d\n", SZ(ans) - 1); REPSZ(i, ans) printf("%d %d\n", ans[i].x, ans[i].y);
			verify();
		}
	}
}


int main() {
	run();
	//stress();
	return 0;
}


Measured memory_bytes: 512