#include<bits/stdc++.h>
#define int long long
#define pb push_back
#define INF 0x3f3f3f3f
#define f first
#define s second
#define pii pair<int, int>
#define mod 1000000007
#define all(x) x.begin(), x.end()
#define mem(x, a) memset(x, a, sizeof(x))
#define loli ios_base::sync_with_stdio(0), cin.tie(0)
using namespace std;
const int maxn = 1e6 + 50;
int a[maxn];
vector<pii> vc;

signed main(){
	loli;
	int n, last = 0;
	cin >> n;
	for(int i = 1; i <= n; i ++){
		cin >> a[i];
		if(a[i]) last = a[i];
	}
	if(last != 1){
		if(!last){
			cout << 0 << "\n";
			return 0;
		}
		cout << -1 << "\n";
		return 0;
	}
	int top = n;
	queue<int> q2;
	queue<pii> q;
	for(int i = n; i >= 1; i --){
		if(a[i] == 1){
			q.push({top, i});
			vc.pb({top --, i});
		}
		else if(a[i] == 2){
			if(q.empty()){
				cout << -1 << "\n";
				return 0;
			}
			vc.pb({q.front().f, i});
			q.pop();
			q2.push(i);
		}
		else if(a[i] == 3){
			if(q2.empty()){
				if(q.empty()){
					cout << -1 << "\n";
					return 0;
				}
				vc.pb({top, i});
				vc.pb({top --, q.front().s});
				q.pop();
				q2.push(i);
			}
			else{
				vc.pb({top, i});
				vc.pb({top --, q2.front()});
				q2.pop();
				q2.push(i);
			}
		}
	}
	cout << vc.size() << "\n";
	for(auto i : vc) cout << i.f << " " << i.s << "\n";
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	int r[n] = {} , c[n] = {} ;
	vpi ans ;

	int row = 0 ;

	for(int i = 0, j=n-1; i < n ; ++i ) {
		if(a[i] and row >=n ) {
			cout << -1 ;
			return ;
		}
		if(a[i] == 1) {
			bool f= 0 ;
			if(c[i]) {
				continue ;
			}
			for(; row<n ; ++row) {
				if(r[row]==0) {
					f= 1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 1 ;
			c[i] = 1 ;
			ans.eb(row++, i) ;
		}
		else if(a[i] == 2) {

			if(r[row] == 1 ) {
				ans.eb(row++, i) ;
				continue ;
			}

			if(c[i] >= 1) {
				cout << -1 ;
				return ;
			}

			bool f = 0 ;
			for(; j > i ; --j) {
				if(a[j] and c[j] == 0) {
					f= 1;
					break ;
				}
			}
			if(not f) {
				cout << -1 ; return ;
			}
			r[row] = 2 ;
			c[i] = 1 , c[j] = 1 ;
			ans.eb(row, i) ;
			ans.eb(row++, j--) ;
		}
		else if(a[i] == 3) {
			bool f = 0 ;

			if(c[i] >= 1)
				{cout << -1 ; return ; }

			for(; j > i ; --j) {
				if((a[j] and c[j] == 0) ) {
					f =1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 2 ;
			r[row+1] = 1;
			c[i] = 1, c[j] = 2 ;
			ans.eb(row,i) ;
			ans.eb(row++, j);
			ans.eb(row++, j--) ;
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	vpi one, two, thr;
	set<int> r;
	rep(i,0,n) r.ins(i) ;
	vpi ans;

	rep(i,n,0) {
		if(a[i] == 1 ) {
			ans.eb(*r.rbegin(), i) ;
			one.eb(*r.rbegin(), i) ;
			r.erase(prev(r.end())) ;
		}
		else if(a[i] == 2) {
			if(one.empty()) {
				cout << -1 ;
				return ;
			}
			ans.eb(one.back().ff, i) ;
			two.eb(one.back().ff, i) ;
			one.pop_back() ;
		}
		else if(a[i] == 3) {
			if(not one.empty()) {
				ans.eb(one.back().ff-1, i) ;
				ans.eb(one.back().ff-1, one.back().ss) ;
				r.erase(one.back().ff-1) ;
				thr.eb(one.back().ff-1, i) ;
				one.pop_back() ;
			}
			else if(not two.empty()) {
				ans.eb(two.back().ff-1, i) ;
				ans.eb(two.back().ff-1, two.back().ss) ;
				r.erase(two.back().ff-1) ;
				thr.eb(two.back().ff-1, i) ;
				two.pop_back() ;
			}
			else if(not thr.empty()) {
				ans.eb(thr.back().ff-1, i) ;
				ans.eb(thr.back().ff-1, thr.back().ss) ;
				r.erase(thr.back().ff-1) ;
				thr.pop_back() ;
				thr.eb(ans.back().ff, i) ;
			}
			else {
				cout << -1 ;
				return ;
			}
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n+1]; rep(i,1,n+1) cin >> a[i] ;
	vii one, two, thr;
	int col[n+1] = {} , twom[n+1] = {} , thrm[n+1] = {} ;

	vpi ans;

	for(int i = n ; i > 0 ; --i) {
		if(a[i] == 1 ) one.eb(i) ;
		else if(a[i] == 2 ) {
			if(one.empty()) {
				cout << -1 ;
				return ;
			}
			twom[i] = one.back() ;
			one.pop_back() ;
			two.eb(i) ;
		}
		else if(a[i] ==3 ) {
			if(not thr.empty()) {
				thrm[i] = thr.back() ;
				thr.pop_back() ;
			}
			else if(not two.empty()) {
				thrm[i] = two.back() ;
				two.pop_back() ;
			}
			else if(not one.empty()) {
				thrm[i] = one.back() ;
				one.pop_back() ;
			}
			else {
				cout << -1 ;
				return ;
			}
			thr.eb(i) ;
		}
	}

	int cur_row = 1 ;

	for(int i = 1 ; i <= n ; ++i ) {
		if(a[i] == 0 or col[i] ) continue ;
		int cur_col = i ;
		while(cur_col) {
			col[cur_col] = 1 ;
			if(a[cur_col] == 1) {
				ans.eb(cur_row++, cur_col) ;
				cur_col = 0 ;
			}
			else if(a[cur_col] == 2) {
				ans.eb(cur_row, cur_col) ;
				cur_col = twom[cur_col] ;
			}
			else if(a[cur_col] == 3) {
				ans.eb(cur_row, cur_col) ;
				cur_col = thrm[cur_col] ;
				ans.eb(cur_row++ , cur_col);
			}
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff << " " << i.ss << nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

int n;

void func(int c[], int row, vpi &ans, int col, int i) {
	if(c[i] == -1) ans.eb(row,i) ;

	ans.eb(row++,col) ;

	if(row >= n ) {
		cout << -1 ;
		exit(0) ;
	}

	ans.eb(row++, col);

	if(c[i] == -1) c[col] = row -1;
	else c[col] = c[i] ;
	if(c[i] == -1) c[i] = row -1;
}

void solve() {

	cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;
	set<int> ones, two, thr ;

	rep(i,0,n) {
		if(a[i] == 1) {
			ones.ins(i) ;
		}
		if(a[i] == 2) {
			two.ins(i) ;
		}
		if(a[i] == 3) {
			thr.ins(i) ;
		}
	}
	vpi ans ;
	int row = 0 ;

	int c[n] = {} ;
	fl(c,-1) ;

	rep(i,0,n) {
		if(a[i] == 0 ) continue ;
		if(a[i] == 1) {
			if(c[i] !=-1) continue ;
			if(row >= n) {
				cout << - 1; return ;
			}
			ans.eb(row++, i) ;
			ones.erase(i) ;
		}
		else if(a[i] == 2) {

			auto x = ones.lb(i) ;
			if(c[i] == -1 and row >= n) {
				cout << -1 ;
				return ;
			}
			int t = row ;
			if(c[i] != -1) row = c[i] ;
			if(c[i] == -1) {
				if(x == ones.end()) {
					cout << -1 ;
					return ;
				}
				ans.eb(row,i) ;
			}
			ans.eb(row++,*x) ;
			ones.erase(x) ;

			row = t + 1;

			if(c[i] == -1) c[*x] = row -1;
			else c[*x] = c[i] ;
			if(c[i] == -1) c[i] = row -1;
		}
		else {

			if(row >= n and c[i] == -1) {
				cout << -1 ;
				return ;
			}

			int t = row ;
			if(c[i] != -1) row = c[i] ;

			int x  = INF ;
			auto it = ones.lb(i) ;
			if(it != ones.end()) x = *it ;
			it = two.lb(i) ;
			if(it != two.end()) x = min(x, *it) ;
			it = thr.ub(i) ;
			if(it != thr.end()) x = min(x, *it) ;

			if(x == INF) {
				cout << -1 ;
				return ;
			}

			func(c, row, ans, x, i);

			row = t + 2;
		}

		// for(auto i : ans) {
		// 	cout << i.ff + 1 << " " << i.ss + 1<< nl ;
		// }
		// cout << nl ;
		// rep(j,0,n) cout << c[j] << " ";
		// cout << nl << nl ;
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

int n;

void func(int c[], int row, vpi &ans, int col, int i) {
	if(c[i] == -1) ans.eb(row,i) ;

	ans.eb(row++,col) ;

	if(row >= n ) {
		cout << -1 ;
		exit(0) ;
	}

	ans.eb(row++, col);

	if(c[i] == -1) c[col] = row -1;
	else c[col] = c[i] ;
	if(c[i] == -1) c[i] = row -1;
}

void solve() {

	cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;
	set<int> ones, two, thr ;

	rep(i,0,n) {
		if(a[i] == 1) {
			ones.ins(i) ;
		}
		if(a[i] == 2) {
			two.ins(i) ;
		}
		if(a[i] == 3) {
			thr.ins(i) ;
		}
	}
	vpi ans ;
	int row = 0 ;

	int c[n] = {} ;
	fl(c,-1) ;

	rep(i,0,n) {
		if(a[i] == 0 ) continue ;
		if(a[i] == 1) {
			if(c[i] !=-1) continue ;
			if(row >= n) {
				cout << - 1; return ;
			}
			ans.eb(row++, i) ;
			ones.erase(i) ;
		}
		else if(a[i] == 2) {

			auto x = ones.lb(i) ;
			if(c[i] == -1 and row >= n) {
				cout << -1 ;
				return ;
			}
			int t = row ;
			if(c[i] != -1) row = c[i] ;
			if(c[i] == -1) {
				if(x == ones.end()) {
					cout << -1 ;
					return ;
				}
				ans.eb(row,i) ;
			}
			ans.eb(row++,*x) ;
			ones.erase(x) ;

			row = t + 1;

			if(c[i] == -1) c[*x] = row -1;
			else c[*x] = c[i] ;
			if(c[i] == -1) c[i] = row -1;
		}
		else {

			if(row >= n and c[i] == -1) {
				cout << -1 ;
				return ;
			}

			int t = row ;
			if(c[i] != -1) row = c[i] ;

			int x  = INF ;
			int f = 0 ;
			int j ;
			auto it = ones.lb(i) ;
			if(it != ones.end()) x = *it, f=1;
			it = two.lb(i) ;
			if(it != two.end()) *it < x ? x = min(x, *it), f = 2 : j =1;
			it = thr.ub(i) ;
			if(it != thr.end()) *it < x ? x = min(x, *it), f = 3 : j=1;

			if(x == INF) {
				cout << -1 ;
				return ;
			}

			ones.erase(x) ;
			two.erase(x) ;
			thr.erase(x) ;

			func(c, row, ans, x, i);

			row = t + 2;
		}

		// for(auto i : ans) {
		// 	cout << i.ff + 1 << " " << i.ss + 1<< nl ;
		// }
		// cout << nl ;
		// rep(j,0,n) cout << c[j] << " ";
		// cout << nl << nl ;
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;
	set<int> ones;

	rep(i,0,n) {
		if(a[i] == 1) {
			ones.ins(i) ;
		}
	}
	vpi ans ;
	int row = 0 ;

	int c[n] = {} ;

	rep(i,0,n) {
		if(a[i] == 0 ) continue ;
		if(a[i] == 1) {
			if(row >= n) {
				cout << - 1; return ;
			}
			if(c[i] == 1) continue ;
			ans.eb(row++, i) ;
			ones.erase(i) ;
		}
		else if(a[i] == 2) {
			auto x = ones.lb(i) ;
			if(x == ones.end()) {
				cout << -1 ;
				return ;
			}
			if(row >= n) {
				cout << -1 ;
				return ;
			}
			c[i] = c[*x] = 1 ;
			ans.eb(row,i) ;
			ans.eb(row++,*x) ;
			ones.erase(x) ;
		}
		else {
			auto x = ones.lb(i) ;
			if(x == ones.end()) {
				cout << -1 ;
				return ;
			}
			if(row >= n) {
				cout << -1 ;
				return ;
			}
			c[i] = c[*x] = 1;
			ans.eb(row,i) ;
			ans.eb(row++,*x) ;
			if(row >= n) {
				cout << -1 ;
				return ;
			}
			ans.eb(row++, *x) ;
			ones.erase(x) ;
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	int r[n] = {} , c[n] = {} ;
	vpi ans ;

	int row = 0 ;

	for(int i = 0, j=n-1; i < n ; ++i ) {
		if(a[i] and row >=n ) {
			cout << -1 ;
			return ;
		}
		if(a[i] == 1) {
			bool f= 0 ;
			if(c[i]) {
				continue ;
			}
			for(; row<n ; ++row) {
				if(r[row]==0) {
					f= 1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 1 ;
			c[i] = 1 ;
			ans.eb(row++, i) ;
		}
		else if(a[i] == 2) {

			if(r[row] == 1 ) {
				ans.eb(row++, i) ;
				continue ;
			}

			if(c[i] == 1) {
				cout << -1 ;
				return ;
			}

			bool f = 0 ;
			for(; j > i ; --j) {
				if(a[j] and c[j] == 0) {
					f= 1;
					break ;
				}
			}
			if(not f) {
				cout << -1 ; return ;
			}
			r[row] = 2 ;
			c[i] = 1 , c[j] = 1 ;
			ans.eb(row, i) ;
			ans.eb(row++, j) ;
		}
		else if(a[i] == 3) {
			bool f = 0 ;

			if(c[i] == 1)
				{cout << -1 ; return ; }

			for(; j > i ; --j) {
				if((a[j] and c[j] == 0) ) {
					f =1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 2 ;
			r[row+1] = 1;
			c[i] = 1, c[j] = 2 ;
			ans.eb(row,i) ;
			ans.eb(row++, j);
			ans.eb(row, j) ;
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

int n;

void func(int c[], int row, vpi &ans, int col, int i) {

	if(row >= n ) {
		cout << -1 ;
		exit(0) ;
	}

	if(c[i] == -1) ans.eb(row,i) ;

	ans.eb(row++,col) ;

	if(row >= n ) {
		cout << -1 ;
		exit(0) ;
	}

	ans.eb(row++, col);

	if(c[i] == -1) c[col] = row -1;
	else c[col] = c[i] ;
	if(c[i] == -1) c[i] = row -1;
}

void solve() {

	cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;
	set<int> ones, two, thr ;

	rep(i,0,n) {
		if(a[i] == 1) {
			ones.ins(i) ;
		}
		if(a[i] == 2) {
			two.ins(i) ;
		}
		if(a[i] == 3) {
			thr.ins(i) ;
		}
	}
	vpi ans ;
	int row = 0 ;

	int c[n] = {} ;
	fl(c,-1) ;

	rep(i,0,n) {
		if(a[i] == 0 ) continue ;
		if(a[i] == 1) {
			if(c[i] !=-1) continue ;
			if(row >= n) {
				cout << - 1; return ;
			}
			ans.eb(row++, i) ;
			ones.erase(i) ;
		}
		else if(a[i] == 2) {

			auto x = ones.lb(i) ;

			int t = row ;
			if(c[i] != -1) row = c[i] ;
			if(c[i] == -1) {
				if(x == ones.end()) {
					cout << -1 ;
					return ;
				}
				ans.eb(row,i) ;
			}
			if(c[i] == -1 and row >= n) {
				cout << -1 ;
				return ;
			}
			ans.eb(row++,*x) ;
			ones.erase(x) ;

			row = t + 1;

			if(c[i] == -1) c[*x] = row -1;
			else c[*x] = c[i] ;
			if(c[i] == -1) c[i] = row -1;
		}
		else {

			int t = row ;
			if(c[i] != -1) row = c[i] ;

			int x  = INF ;
			int f = 0 ;
			int j ;
			auto it = ones.lb(i) ;
			if(it != ones.end()) x = *it, f=1;
			it = two.lb(i) ;
			if(it != two.end()) *it < x ? x = min(x, *it), f = 2 : j =1;
			it = thr.ub(i) ;
			if(it != thr.end()) *it < x ? x = min(x, *it), f = 3 : j=1;

			if(x == INF) {
				cout << -1 ;
				return ;
			}

			ones.erase(x) ;
			two.erase(x) ;
			thr.erase(x) ;

			func(c, row, ans, x, i);

			row = t + 2;
		}

		// for(auto i : ans) {
		// 	cout << i.ff + 1 << " " << i.ss + 1<< nl ;
		// }
		// cout << nl ;
		// rep(j,0,n) cout << c[j] << " ";
		// cout << nl << nl ;
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	vpi one, two, thr;
	set<int> r;
	rep(i,0,n) r.ins(i) ;
	vpi ans;

	rep(i,n,0) {
		if(a[i] == 1 ) {
			ans.eb(*r.rbegin(), i) ;
			one.eb(*r.rbegin(), i) ;
			r.erase(prev(r.end())) ;
		}
		else if(a[i] == 2) {
			if(one.empty()) {
				cout << -1 ;
				return ;
			}
			ans.eb(one.back().ff, i) ;
			two.eb(one.back().ff, i) ;
			one.pop_back() ;
		}
		else if(a[i] == 3) {
			if(not one.empty()) {
				ans.eb(one.back().ff-1, i) ;
				ans.eb(one.back().ff-1, one.back().ss) ;
				r.erase(one.back().ff-1) ;
				thr.eb(one.back().ff-1, i) ;
				one.pop_back() ;
			}
			else if(not two.empty()) {
				ans.eb(two.back().ff-1, i) ;
				ans.eb(two.back().ff-1, two.back().ss) ;
				r.erase(two.back().ff-1) ;
				thr.eb(two.back().ff-1, i) ;
				two.pop_back() ;
			}
			else if(not thr.empty()) {
				ans.eb(thr.back().ff-1, i) ;
				ans.eb(thr.back().ff-1, thr.back().ss) ;
				r.erase(thr.back().ff-1) ;
				thr.eb(thr.back().ff-1, i) ;
				thr.pop_back() ;
			}
			else {
				cout << -1 ;
				return ;
			}
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;
	set<int> ones, two, thr ;

	rep(i,0,n) {
		if(a[i] == 1) {
			ones.ins(i) ;
		}
		if(a[i] == 2) {
			two.ins(i) ;
		}
		if(a[i] == 3) {
			thr.ins(i) ;
		}
	}
	vpi ans ;
	int row = 0 ;

	int c[n] = {} ;
	fl(c,-1) ;

	rep(i,0,n) {
		if(a[i] == 0 ) continue ;
		if(a[i] == 1) {
			if(row >= n) {
				cout << - 1; return ;
			}
			if(c[i] !=-1) continue ;
			ans.eb(row++, i) ;
			ones.erase(i) ;
		}
		else if(a[i] == 2) {

			auto x = ones.lb(i) ;
			if(c[i] == -1 and x == ones.end()) {
				cout << -1 ;
				return ;
			}
			if(c[i] ==-1 and row >= n) {
				cout << -1 ;
				return ;
			}
			int t = row ;
			if(c[i] != -1) row = c[i] ;
			if(c[i] == -1) ans.eb(row,i) ;
			ans.eb(row++,*x) ;
			ones.erase(x) ;

			row = t + 1;

			if(c[i] == -1) c[*x] = row -1;
			else c[*x] = c[i] ;
			if(c[i] == -1) c[i] = row -1;
		}
		else {

			auto x = ones.lb(i) ;
			if(x == ones.end() and c[i] ==-1) {
				x = two.lb(i) ;
				if(x == two.end()) {
					x = thr.ub(i) ;
					if(x == thr.end()) {
						cout << -1 ;
						return ;
					}
				}
			}

			if(row >= n and c[i] == -1) {
				cout << -1 ;
				return ;
			}

			int t = row ;
			if(c[i] != -1) row = c[i] ;
			if(c[i] == -1) ans.eb(row,i) ;
			ans.eb(row++,*x) ;

			if(row >= n ) {
				cout << -1 ;
				return ;
			}

			ans.eb(row++, *x);

			row = t + 2;

			if(c[i] == -1) c[*x] = row -1;
			else c[*x] = c[i] ;
			if(c[i] == -1) c[i] = row -1;
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	int r[n] = {} , c[n] = {} ;
	vpi ans ;

	int row = 0 ;

	for(int i = 0, j=n-1; i < n ; ++i ) {
		if(a[i] and row >=n ) {
			cout << -1 ;
			return ;
		}
		if(a[i] == 1) {
			bool f= 0 ;
			if(c[i]) {
				continue ;
			}
			for(; row<n ; ++row) {
				if(r[row]==0) {
					f= 1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 1 ;
			c[i] = 1 ;
			ans.eb(row++, i) ;
		}
		else if(a[i] == 2) {

			if(r[row] == 1 ) {
				ans.eb(row++, i) ;
				continue ;
			}

			if(c[i] >= 1) {
				cout << -1 ;
				return ;
			}

			bool f = 0 ;
			for(; j > i ; --j) {
				if(a[j] and c[j] < 2) {
					f= 1;
					break ;
				}
			}
			if(not f) {
				cout << -1 ; return ;
			}
			r[row] = 2 ;
			c[i] = 1 , c[j] = 1 ;
			ans.eb(row, i) ;
			ans.eb(row++, j) ;
		}
		else if(a[i] == 3) {
			bool f = 0 ;

			if(c[i] >= 1)
				{cout << -1 ; return ; }

			for(; j > i ; --j) {
				if(a[j] and c[j] < 2 ) {
					f =1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 2 ;
			r[row+1] = 1;
			c[i] = 1, c[j] = 2 ;
			ans.eb(row,i) ;
			ans.eb(row++, j);
			ans.eb(row++, j--) ;
		}
		// for(auto i : ans) {
		// 	cout << i.ff + 1 << " " << i.ss + 1<< nl ;
		// }
		// cout << nl ;
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	vpi one, two, thr;
	set<int> r;
	rep(i,0,n) r.ins(i) ;
	vpi ans;

	rep(i,n,0) {
		if(a[i] == 1 ) {
			ans.eb(*r.rbegin(), i) ;
			one.eb(*r.rbegin(), i) ;
			r.erase(prev(r.end())) ;
		}
		else if(a[i] == 2) {
			if(one.empty()) {
				cout << -1 ;
				return ;
			}
			ans.eb(one.back().ff, i) ;
			two.eb(one.back().ff, i) ;
			r.erase(one.back().ff) ;
			one.pop_back() ;
		}
		else if(a[i] == 3) {
			if(not one.empty()) {
				ans.eb(one.back().ff-1, i) ;
				ans.eb(one.back().ff-1, one.back().ss) ;
				r.erase(one.back().ff-1) ;
				thr.eb(one.back().ff-1, i) ;
				one.pop_back() ;
				r.erase(ans.back().ff);
			}
			else if(not two.empty()) {
				ans.eb(two.back().ff-1, i) ;
				ans.eb(two.back().ff-1, two.back().ss) ;
				r.erase(two.back().ff-1) ;
				thr.eb(two.back().ff-1, i) ;
				two.pop_back() ;
				r.erase(ans.back().ff);
			}
			else if(not thr.empty()) {
				ans.eb(thr.back().ff-1, i) ;
				ans.eb(thr.back().ff-1, thr.back().ss) ;
				r.erase(thr.back().ff-1) ;
				thr.pop_back() ;
				thr.eb(ans.back().ff, i) ;
				r.erase(ans.back().ff);
			}
			else {
				cout << -1 ;
				return ;
			}
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")

#include<bits/stdc++.h>

using namespace std;
#define ll long long
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define ins insert
#define ull unsigned long long
#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))
#define ff first
#define ss second
#define fast ios::sync_with_stdio(0) , cin.tie(0) , cout.tie(0);
#define nl "\n"
#define sz(a) (int)(a).size()
#define all(a) (a).begin(),(a).end()
#define fl(a,x) memset(a,x,sizeof(a));
#define pt(a,x) cout << get<x>(a) << " " ;
#define mt make_tuple
#define vec vector
#define ld long double
#define eps 1e-9

#define int long long

const int mod = (int) 1e9 + 7 ;
const int MOD = (int) 998244353 ;
const int INF = (int) 1e18 ;

typedef vector<int> vii;
typedef pair<int,int> pii;
typedef vector<pii> vpi;
typedef vector<vector<int> > vv;

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }

void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << endl;
	err(++it, args...);
}

void solve() {

	int n; cin >> n ;
	int a[n]; rep(i,0,n) cin >> a[i] ;

	int r[n] = {} , c[n] = {} ;
	vpi ans ;

	int row = 0 ;

	for(int i = 0, j=n-1; i < n ; ++i ) {
		if(a[i] and row >=n ) {
			cout << -1 ;
			return ;
		}
		if(a[i] == 1) {
			bool f= 0 ;
			if(c[i]) {
				continue ;
			}
			for(; row<n ; ++row) {
				if(r[row]==0) {
					f= 1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 1 ;
			c[i] = 1 ;
			ans.eb(row++, i) ;
		}
		else if(a[i] == 2) {

			if(r[row] == 1 ) {
				ans.eb(row++, i) ;
				continue ;
			}

			if(c[i] == 1) {
				cout << -1 ;
				return ;
			}

			bool f = 0 ;
			for(; j > i ; --j) {
				if(a[j] and c[j] == 0) {
					f= 1;
					break ;
				}
			}
			if(not f) {
				cout << -1 ; return ;
			}
			r[row] = 2 ;
			c[i] = 1 , c[j] = 1 ;
			ans.eb(row, i) ;
			ans.eb(row++, j) ;
		}
		else if(a[i] == 3) {
			bool f = 0 ;

			if(c[i] == 1)
				{cout << -1 ; return ; }

			for(; j > i ; --j) {
				if((a[j] and c[j] == 0) ) {
					f =1 ;
					break ;
				}
			}

			if(not f) {
				cout << -1 ;
				return ;
			}

			r[row] = 2 ;
			r[row+1] = 1;
			c[i] = 1, c[j] = 2 ;
			ans.eb(row,i) ;
			ans.eb(row++, j);
			ans.eb(row++, j) ;
		}
	}

	cout << sz(ans) << nl ;

	for(auto i : ans) {
		cout << i.ff + 1 << " " << i.ss + 1<< nl ;
	}
}

int32_t main() {

#ifdef LOCAL
    freopen("error.txt", "w", stderr);
#endif

    fast;

	// int t; cin >> t; while(t--)
		solve() ;

	// cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
	return 0;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = n; i; i--)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	int u = n, d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			if (v[3].size())
				vv.push_back({ i,u }), vv.push_back({ v[3].back(),u-- }), b[v[3].back()] = 1, v[3].pop_back();
		}
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = n; i; i--)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	int u = n, d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size())
				vv.push_back({ i,u }), vv.push_back({ v[3].back(),u-- }), b[v[3].back()] = 1, v[3].pop_back();
		}
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i<=n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	int  d = 1;
	for (int i = n; i; i--)
	{

		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size()&&v[3].size()==0||v[2].size()&&v[3].size()&&v[2].back()>v[3].back())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size()&&v[2].size()==0 || v[2].size() && v[3].size() && v[2].back() < v[3].back())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size() && v[3].size() == 0 || v[2].size() && v[3].size() && v[2].back() > v[3].back())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size() && v[2].size() == 0 || v[2].size() && v[3].size() && v[2].back() < v[3].back())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			v[1].pop_back();
			if (v[2].size() &&(!v[3].size()||v[3].size() && v[3].back() < v[1].back()))
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		cout << i;
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size()  )
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		//cout << i;
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size()  )
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			v[1].pop_back();
			if (v[2].size() && (!v[3].size() || v[3].size() && (v[3].back() < v[1].back() || v[3].back() < v[2].back())))
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size() && v[3].size() == 0 || v[2].size() && v[3].size() && v[2].back() > v[3].back())
			{
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
				if (v[3].size())
					vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
			}
			else if (v[3].size() && v[2].size() == 0 || v[2].size() && v[3].size() && v[2].back() < v[3].back())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		//cout << i;
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
 if (v[3].size()  )
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
 else if (v[2].size())
	 vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();

		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i<=n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	int  d = 1;
	for (int i = n; i; i--)
	{

		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = n; i; i--)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	int u = n, d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size())
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size())
				vv.push_back({ i,u }), vv.push_back({ v[3].back(),u-- }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i] == 2)
		{
			if (v[3].size())
				vv.push_back({ i,u }), vv.push_back({ v[3].back(),u-- }), b[v[3].back()] = 1, v[3].pop_back();
		}
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
#define ll long long
#define db double
using namespace std;
const int maxn = 100001, inf = 2147483647;
const ll mod = 1 ? 998244353 : 1000000007, linf = 9223372036854775807;
const double pi = acos(-1);
inline ll mi(ll a, ll b) { a %= mod; ll u = 1; while (b) { if (b & 1)u = u * a % mod; a = a * a % mod, b >>= 1; }return u; }
inline ll gcd(ll a, ll b) { ll c = a % b; while (c)a = b, b = c, c = a % b; return b; }
inline void mem(int* a, int p = 0, int len = maxn) { for (register int i = 0; i < len; i++)a[i] = p; }
int a[100001], b[100001], c[100001], f;
vector<int>v[4];
int main()
{
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = 1; i <= n; i++)
		v[a[i]].push_back(i);
	vector<pair<int, int>>vv;
	vector<int>vvv = v[1];
	int  d = 1;
	for (int i = n; i; i--)
	{
		if ((a[i] == 2 || a[i] == 3) && !b[i])
		{
			cout << -1;
			return 0;
		}
		if (a[i] == 1)
		{
			vv.push_back({ i,d++ });
			if (v[2].size() && v[3].size() == 0)
				vv.push_back({ v[2].back(),d - 1 }), b[v[2].back()] = 1, v[2].pop_back();
			else if (v[3].size() && v[2].size() == 0 )
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
		}
		else if (a[i])
			if (v[3].size())
				vv.push_back({ i,d }), vv.push_back({ v[3].back(),d++ }), b[v[3].back()] = 1, v[3].pop_back();
	}
	cout << vv.size() << endl;
	for (auto i : vv)
		cout << n + 1 - i.second << ' ' << i.first << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll INF = 1e9+7;
ll MOD = 998244353;
typedef pair<ll,ll> ii;
#define iiii pair<ii,ii>
#define f(i,a,b) for(ll i = a;i < b;i++)
#define rf(i,a,b) for(long long i=a;i>=b;i--)
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define w(t) while(t--)
#define c(n); cin>>n;
#define p(n) cout<<n;
#define pl(n) cout<<n<<"\n";
#define ps(n); cout<<n<<" ";
#define F first
#define S second
#define pb(a) push_back(a)
#define all(x) (x).begin(), (x).end()
#define ull unsigned long long
#define vll vector<ll>
#define vii vector<ii>
#define mkp make_pair
#define ld long double
#define arrin(a,n) f(i,0,n){cin>>a[i];}
#define arrout(a,n) f(i,0,n){cout<<a[i]<<" ";}
#define printclock cerr<<"Time : "<<*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
#define PI (2*acos(0))
#define EPS 1e-18
const long long N = 1e5+5;
const long long M = 1e6+5;
vll visit,dist,taken;
vector<vll> adj;
vector<vii> adj2;
priority_queue<ii,vector<ii>, greater<ii> > pq;
ll bit[N]={0};
ll par[N]={0};
ll an[N][35];
ll depth[N]={0};
ll siz;
ll res = 0;
ll mycbrt(ll num){ll l = 1,r = 1000000;ll ans = 0;while(l <= r){ll mid = (l+r)/2;if(mid * mid * mid <= num){l = mid + 1;ans = max(ans,mid);}else{r = mid - 1;}}return ans;}
ll lcm(ll a,ll b){return (a * b) / __gcd(a,b);}
ll gcd(ll a,ll b){return __gcd(a,b);}
ll power(ll a,ll b,ll MOD){if(b == 0)return 1;if(b == 1)return a;ll ans = power(a,b/2,MOD) % MOD;ans *= ans;ans %= MOD;if(b % 2 == 1)ans *= a;return ans%MOD;}
ll inverse(ll x){x%=MOD;return power(x,MOD-2,MOD);}
void BITup(ll k, ll x){while(k <= siz){bit[k]+=x;k += k & -k;}}
ll BITq(ll k){ll s=0;while(k>=1){s+=bit[k];k -= k &-k;}return s;}
struct point{ll x,y,idx;};
void dfs(ll v){visit[v] = 1;for(auto x:adj[v]){if(!visit[x]){depth[x] = depth[v] + 1;dfs(x);}}}
void bfs(ll s){visit[s] = 1;queue<ll>q;q.push(s);while(!q.empty()){ll u = q.front();ps(u);q.pop();for(auto x:adj[u]){if(!visit[x]){visit[x] = 1;q.push(x);}}}}
void dijkstra(ll s){pq.push(ii(0,s));dist[s] = 0;while(!pq.empty()){ii f = pq.top();pq.pop();ll w = f.F;ll u = f.S;if(w > dist[u]){continue;}for(auto v:adj2[u]){if(dist[u] + v.S < dist[v.F]){dist[v.F] = dist[u] + v.S;pq.push(ii(dist[v.F],v.F));}}}}
void prim(ll edge) {taken[edge] = 1;for(auto v:adj2[edge]) {if (taken[v.first]==0)pq.push(ii(v.second, v.first));}}
ll mst(ll s){taken.assign(N, 0);prim(s);ll cost = 0;while(!pq.empty()){ii front = pq.top();pq.pop();ll w = front.first;ll u = front.second;if(taken[u]==0)cost += w;prim(u);}return cost;}
void bfs01(ll s){deque<ll>q;dist[s] = 0;q.push_back(s);while(!q.empty()){ll v = q.front();q.pop_front();for(auto x:adj2[v]){if(dist[x.F] > dist[v] + x.S){dist[x.F] = dist[v] + x.S;if(x.S == 0){q.push_front(x.F);}else{q.push_back(x.F);}}}}}
void build(ll s,ll p){an[s][0] = p;f(i,1,35){an[s][i] = an[an[s][i-1]][i-1];}for(auto x:adj[s]){if(x != p){depth[x] = depth[s] + 1;build(x,s);}}}
ll kth(ll x,ll k){ll ans = x;if(depth[x] < k){return -1;}ll pos = 0;while(k > 0){if(k % 2){ans = an[ans][pos];}pos++;k /= 2;}return ans;}
ll lca(ll a,ll b){if(depth[a] > depth[b]){swap(a,b);}b = kth(b,abs(depth[a] - depth[b]));if(a == b){return a;}for(ll i = 34;i >= 0;i--){if(an[a][i] == an[b][i]){continue;}a = an[a][i];b = an[b][i];}return an[a][0];}
ll find_dsu(ll x){if(par[x] == x){return x;}par[x] = find_dsu(par[x]);return par[x];}
void union_dsu(ll x,ll y){ll pos1 = find_dsu(x);ll pos2 = find_dsu(y);par[pos2] = pos1;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<ll> distr;
ll rnd(ll a, ll b){return distr(rng)%(b-a+1)+a;}
void YESNO(ll a){if(!!a){pl("Yes");}else{pl("No");}}
void filesin(void){freopen("amusing.in","r",stdin);}
void filesout(void){freopen("amusing.out","w",stdout);}
///I hope I will get uprating and don't make mistakes
///I will never stop programming
///sqrt(-1) Love C++
///Please don't hack me
///@TheofanisOrfanou Theo830
///Codeforces Raif Round 1 (Div. 1 + Div. 2)
int main(void){
    fastio;
    ll n;
    cin>>n;
    ll arr[n];
    arrin(arr,n);
    set<ll>rows;
    set<ll>ro1;
    f(i,0,n){
        rows.insert(i+1);
    }
    vii ar,ans;
    bool ok = 1;
    f(i,0,n){
        if(arr[i] == 0){
            continue;
        }
        else if(arr[i] == 1){
            if(ar.empty()){
                if(0){
                    auto it = ro1.begin();
                    ro1.erase(it);
                    ans.pb(ii(i+1,*(it)));
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                    }
                }
            }
            else{
                ii x = ar.back();
                ar.pop_back();
                if(x.F == 2){
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                        ro1.insert((*it));
                    }
                }
            }
        }
        else{
            ar.pb(ii(arr[i],i+1));
        }
    }
    if(!ar.empty()){
        ok = 0;
    }
    if(!ok){
        pl(-1);
    }
    else{
        cout<<ans.size()<<endl;
        for(auto x:ans){
            cout<<x.S<<" "<<x.F<<endl;
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll INF = 1e9+7;
ll MOD = 998244353;
typedef pair<ll,ll> ii;
#define iiii pair<ii,ii>
#define f(i,a,b) for(ll i = a;i < b;i++)
#define rf(i,a,b) for(long long i=a;i>=b;i--)
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define w(t) while(t--)
#define c(n); cin>>n;
#define p(n) cout<<n;
#define pl(n) cout<<n<<"\n";
#define ps(n); cout<<n<<" ";
#define F first
#define S second
#define pb(a) push_back(a)
#define all(x) (x).begin(), (x).end()
#define ull unsigned long long
#define vll vector<ll>
#define vii vector<ii>
#define mkp make_pair
#define ld long double
#define arrin(a,n) f(i,0,n){cin>>a[i];}
#define arrout(a,n) f(i,0,n){cout<<a[i]<<" ";}
#define printclock cerr<<"Time : "<<*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
#define PI (2*acos(0))
#define EPS 1e-18
const long long N = 1e5+5;
const long long M = 1e6+5;
vll visit,dist,taken;
vector<vll> adj;
vector<vii> adj2;
priority_queue<ii,vector<ii>, greater<ii> > pq;
ll bit[N]={0};
ll par[N]={0};
ll an[N][35];
ll depth[N]={0};
ll siz;
ll res = 0;
ll mycbrt(ll num){ll l = 1,r = 1000000;ll ans = 0;while(l <= r){ll mid = (l+r)/2;if(mid * mid * mid <= num){l = mid + 1;ans = max(ans,mid);}else{r = mid - 1;}}return ans;}
ll lcm(ll a,ll b){return (a * b) / __gcd(a,b);}
ll gcd(ll a,ll b){return __gcd(a,b);}
ll power(ll a,ll b,ll MOD){if(b == 0)return 1;if(b == 1)return a;ll ans = power(a,b/2,MOD) % MOD;ans *= ans;ans %= MOD;if(b % 2 == 1)ans *= a;return ans%MOD;}
ll inverse(ll x){x%=MOD;return power(x,MOD-2,MOD);}
void BITup(ll k, ll x){while(k <= siz){bit[k]+=x;k += k & -k;}}
ll BITq(ll k){ll s=0;while(k>=1){s+=bit[k];k -= k &-k;}return s;}
struct point{ll x,y,idx;};
void dfs(ll v){visit[v] = 1;for(auto x:adj[v]){if(!visit[x]){depth[x] = depth[v] + 1;dfs(x);}}}
void bfs(ll s){visit[s] = 1;queue<ll>q;q.push(s);while(!q.empty()){ll u = q.front();ps(u);q.pop();for(auto x:adj[u]){if(!visit[x]){visit[x] = 1;q.push(x);}}}}
void dijkstra(ll s){pq.push(ii(0,s));dist[s] = 0;while(!pq.empty()){ii f = pq.top();pq.pop();ll w = f.F;ll u = f.S;if(w > dist[u]){continue;}for(auto v:adj2[u]){if(dist[u] + v.S < dist[v.F]){dist[v.F] = dist[u] + v.S;pq.push(ii(dist[v.F],v.F));}}}}
void prim(ll edge) {taken[edge] = 1;for(auto v:adj2[edge]) {if (taken[v.first]==0)pq.push(ii(v.second, v.first));}}
ll mst(ll s){taken.assign(N, 0);prim(s);ll cost = 0;while(!pq.empty()){ii front = pq.top();pq.pop();ll w = front.first;ll u = front.second;if(taken[u]==0)cost += w;prim(u);}return cost;}
void bfs01(ll s){deque<ll>q;dist[s] = 0;q.push_back(s);while(!q.empty()){ll v = q.front();q.pop_front();for(auto x:adj2[v]){if(dist[x.F] > dist[v] + x.S){dist[x.F] = dist[v] + x.S;if(x.S == 0){q.push_front(x.F);}else{q.push_back(x.F);}}}}}
void build(ll s,ll p){an[s][0] = p;f(i,1,35){an[s][i] = an[an[s][i-1]][i-1];}for(auto x:adj[s]){if(x != p){depth[x] = depth[s] + 1;build(x,s);}}}
ll kth(ll x,ll k){ll ans = x;if(depth[x] < k){return -1;}ll pos = 0;while(k > 0){if(k % 2){ans = an[ans][pos];}pos++;k /= 2;}return ans;}
ll lca(ll a,ll b){if(depth[a] > depth[b]){swap(a,b);}b = kth(b,abs(depth[a] - depth[b]));if(a == b){return a;}for(ll i = 34;i >= 0;i--){if(an[a][i] == an[b][i]){continue;}a = an[a][i];b = an[b][i];}return an[a][0];}
ll find_dsu(ll x){if(par[x] == x){return x;}par[x] = find_dsu(par[x]);return par[x];}
void union_dsu(ll x,ll y){ll pos1 = find_dsu(x);ll pos2 = find_dsu(y);par[pos2] = pos1;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<ll> distr;
ll rnd(ll a, ll b){return distr(rng)%(b-a+1)+a;}
void YESNO(ll a){if(!!a){pl("Yes");}else{pl("No");}}
void filesin(void){freopen("amusing.in","r",stdin);}
void filesout(void){freopen("amusing.out","w",stdout);}
///I hope I will get uprating and don't make mistakes
///I will never stop programming
///sqrt(-1) Love C++
///Please don't hack me
///@TheofanisOrfanou Theo830
///Codeforces Raif Round 1 (Div. 1 + Div. 2)
int main(void){
    fastio;
    ll n;
    cin>>n;
    ll arr[n];
    arrin(arr,n);
    set<ll>rows;
    set<ll>ro1;
    f(i,0,n){
        rows.insert(i+1);
    }
    vii ar,ans,ar2;
    vii pos;
    bool ok = 1;
    f(i,0,n){
        if(arr[i] == 0){
            continue;
        }
        else if(arr[i] == 1){
            if(ar.empty() && ar2.empty()){
                if(rows.empty()){
                    ok = 0;
                    break;
                }
                else{
                    auto it = rows.begin();
                    ans.pb(ii(i+1,*(it)));
                    rows.erase(it);
                }
            }
            else{
                ii x;
                if(ar.empty()){
                    x = ar2.back();
                    ar2.pop_back();
                }
                else{
                    x = ar.back();
                    ar.pop_back();
                }
                if(rows.empty()){
                    ok = 0;
                    break;
                }
                else{
                    auto it = rows.begin();
                    ans.pb(ii(i+1,*(it)));
                    ans.pb(ii(x.S,*(it)));
                    if(x.F == 2){
                        pos.pb(ii(x.S,*(it)));
                    }
                    rows.erase(it);
                }
            }
        }
        else{
            if(arr[i] == 2){
                ar.pb(ii(arr[i],i+1));
            }
            else{
                if(!ar2.empty()){
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(ar2.back().S,*(it)));
                        ar2.pop_back();
                        rows.erase(it);
                    }
                }
                ar2.pb(ii(arr[i],i+1));
            }
        }
    }
    if(!ar.empty() || pos.size() < ar2.size()){
        ok = 0;
    }
    ll swapp[n+1];
    memset(swapp,-1,sizeof swapp);
    if(ok){
        ll p = 0;
        for(auto x:ar2){
            while(p < pos.size() && pos[p].F < x.S){
                p++;
            }
            if(p == pos.size()){
                ok = 0;
                break;
            }
            if(rows.empty()){
                ok = 0;
                break;
            }
            else{
                auto it = rows.begin();
                ans.pb(ii(pos[p].F,*(it)));
                ans.pb(ii(x.S,(*it)));
                swapp[*(it)] = pos[p].S;
                swapp[pos[p].S] = *(it);
                rows.erase(it);
            }
            p++;
        }
    }
    if(!ok){
        pl(-1);
    }
    else{
        cout<<ans.size()<<endl;
        for(auto x:ans){
            if(swapp[x.S] != -1){
                x.S = swapp[x.S];
            }
            cout<<x.S<<" "<<x.F<<endl;
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll INF = 1e9+7;
ll MOD = 998244353;
typedef pair<ll,ll> ii;
#define iiii pair<ii,ii>
#define f(i,a,b) for(ll i = a;i < b;i++)
#define rf(i,a,b) for(long long i=a;i>=b;i--)
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define w(t) while(t--)
#define c(n); cin>>n;
#define p(n) cout<<n;
#define pl(n) cout<<n<<"\n";
#define ps(n); cout<<n<<" ";
#define F first
#define S second
#define pb(a) push_back(a)
#define all(x) (x).begin(), (x).end()
#define ull unsigned long long
#define vll vector<ll>
#define vii vector<ii>
#define mkp make_pair
#define ld long double
#define arrin(a,n) f(i,0,n){cin>>a[i];}
#define arrout(a,n) f(i,0,n){cout<<a[i]<<" ";}
#define printclock cerr<<"Time : "<<*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
#define PI (2*acos(0))
#define EPS 1e-18
const long long N = 1e5+5;
const long long M = 1e6+5;
vll visit,dist,taken;
vector<vll> adj;
vector<vii> adj2;
priority_queue<ii,vector<ii>, greater<ii> > pq;
ll bit[N]={0};
ll par[N]={0};
ll an[N][35];
ll depth[N]={0};
ll siz;
ll res = 0;
ll mycbrt(ll num){ll l = 1,r = 1000000;ll ans = 0;while(l <= r){ll mid = (l+r)/2;if(mid * mid * mid <= num){l = mid + 1;ans = max(ans,mid);}else{r = mid - 1;}}return ans;}
ll lcm(ll a,ll b){return (a * b) / __gcd(a,b);}
ll gcd(ll a,ll b){return __gcd(a,b);}
ll power(ll a,ll b,ll MOD){if(b == 0)return 1;if(b == 1)return a;ll ans = power(a,b/2,MOD) % MOD;ans *= ans;ans %= MOD;if(b % 2 == 1)ans *= a;return ans%MOD;}
ll inverse(ll x){x%=MOD;return power(x,MOD-2,MOD);}
void BITup(ll k, ll x){while(k <= siz){bit[k]+=x;k += k & -k;}}
ll BITq(ll k){ll s=0;while(k>=1){s+=bit[k];k -= k &-k;}return s;}
struct point{ll x,y,idx;};
void dfs(ll v){visit[v] = 1;for(auto x:adj[v]){if(!visit[x]){depth[x] = depth[v] + 1;dfs(x);}}}
void bfs(ll s){visit[s] = 1;queue<ll>q;q.push(s);while(!q.empty()){ll u = q.front();ps(u);q.pop();for(auto x:adj[u]){if(!visit[x]){visit[x] = 1;q.push(x);}}}}
void dijkstra(ll s){pq.push(ii(0,s));dist[s] = 0;while(!pq.empty()){ii f = pq.top();pq.pop();ll w = f.F;ll u = f.S;if(w > dist[u]){continue;}for(auto v:adj2[u]){if(dist[u] + v.S < dist[v.F]){dist[v.F] = dist[u] + v.S;pq.push(ii(dist[v.F],v.F));}}}}
void prim(ll edge) {taken[edge] = 1;for(auto v:adj2[edge]) {if (taken[v.first]==0)pq.push(ii(v.second, v.first));}}
ll mst(ll s){taken.assign(N, 0);prim(s);ll cost = 0;while(!pq.empty()){ii front = pq.top();pq.pop();ll w = front.first;ll u = front.second;if(taken[u]==0)cost += w;prim(u);}return cost;}
void bfs01(ll s){deque<ll>q;dist[s] = 0;q.push_back(s);while(!q.empty()){ll v = q.front();q.pop_front();for(auto x:adj2[v]){if(dist[x.F] > dist[v] + x.S){dist[x.F] = dist[v] + x.S;if(x.S == 0){q.push_front(x.F);}else{q.push_back(x.F);}}}}}
void build(ll s,ll p){an[s][0] = p;f(i,1,35){an[s][i] = an[an[s][i-1]][i-1];}for(auto x:adj[s]){if(x != p){depth[x] = depth[s] + 1;build(x,s);}}}
ll kth(ll x,ll k){ll ans = x;if(depth[x] < k){return -1;}ll pos = 0;while(k > 0){if(k % 2){ans = an[ans][pos];}pos++;k /= 2;}return ans;}
ll lca(ll a,ll b){if(depth[a] > depth[b]){swap(a,b);}b = kth(b,abs(depth[a] - depth[b]));if(a == b){return a;}for(ll i = 34;i >= 0;i--){if(an[a][i] == an[b][i]){continue;}a = an[a][i];b = an[b][i];}return an[a][0];}
ll find_dsu(ll x){if(par[x] == x){return x;}par[x] = find_dsu(par[x]);return par[x];}
void union_dsu(ll x,ll y){ll pos1 = find_dsu(x);ll pos2 = find_dsu(y);par[pos2] = pos1;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<ll> distr;
ll rnd(ll a, ll b){return distr(rng)%(b-a+1)+a;}
void YESNO(ll a){if(!!a){pl("Yes");}else{pl("No");}}
void filesin(void){freopen("amusing.in","r",stdin);}
void filesout(void){freopen("amusing.out","w",stdout);}
///I hope I will get uprating and don't make mistakes
///I will never stop programming
///sqrt(-1) Love C++
///Please don't hack me
///@TheofanisOrfanou Theo830
///Codeforces Raif Round 1 (Div. 1 + Div. 2)
int main(void){
    fastio;
    ll n;
    cin>>n;
    ll arr[n];
    arrin(arr,n);
    set<ll>rows;
    set<ll>ro1;
    f(i,0,n){
        rows.insert(i+1);
    }
    vii ar,ans,ar2;
    vll pos;
    bool ok = 1;
    f(i,0,n){
        if(arr[i] == 0){
            continue;
        }
        else if(arr[i] == 1){
            if(ar.empty() && ar2.empty()){
                if(0){
                    auto it = ro1.begin();
                    ro1.erase(it);
                    ans.pb(ii(i+1,*(it)));
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                    }
                }
            }
            else{
                ii x;
                if(ar.empty()){
                    x = ar2.back();
                    ar2.pop_back();
                }
                else{
                    x = ar.back();
                    ar.pop_back();
                }
                if(x.F == 2){
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        pos.pb(i+1);
                        rows.erase(it);
                    }
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                        ro1.insert((*it));
                    }
                }
            }
        }
        else{
            if(arr[i] == 2){
                ar.pb(ii(arr[i],i+1));
            }
            else{
                ar2.pb(ii(arr[i],i+1));
            }
        }
    }
    if(!ar.empty() || pos.size() < ar2.size()){
        ok = 0;
    }
    if(ok){
        ll p = 0;
        for(auto x:ar2){
            while(p < pos.size() && pos[p] < x.S){
                p++;
            }
            if(p == pos.size()){
                ok = 0;
                break;
            }
            if(rows.empty()){
                ok = 0;
                break;
            }
            else{
                auto it = rows.begin();
                ans.pb(ii(pos[p],*(it)));
                ans.pb(ii(x.S,(*it)));
                rows.erase(it);
            }
            p++;
        }
    }
    if(!ok){
        pl(-1);
    }
    else{
        cout<<ans.size()<<endl;
        for(auto x:ans){
            cout<<x.S<<" "<<x.F<<endl;
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll INF = 1e9+7;
ll MOD = 998244353;
typedef pair<ll,ll> ii;
#define iiii pair<ii,ii>
#define f(i,a,b) for(ll i = a;i < b;i++)
#define rf(i,a,b) for(long long i=a;i>=b;i--)
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define w(t) while(t--)
#define c(n); cin>>n;
#define p(n) cout<<n;
#define pl(n) cout<<n<<"\n";
#define ps(n); cout<<n<<" ";
#define F first
#define S second
#define pb(a) push_back(a)
#define all(x) (x).begin(), (x).end()
#define ull unsigned long long
#define vll vector<ll>
#define vii vector<ii>
#define mkp make_pair
#define ld long double
#define arrin(a,n) f(i,0,n){cin>>a[i];}
#define arrout(a,n) f(i,0,n){cout<<a[i]<<" ";}
#define printclock cerr<<"Time : "<<*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
#define PI (2*acos(0))
#define EPS 1e-18
const long long N = 1e5+5;
const long long M = 1e6+5;
vll visit,dist,taken;
vector<vll> adj;
vector<vii> adj2;
priority_queue<ii,vector<ii>, greater<ii> > pq;
ll bit[N]={0};
ll par[N]={0};
ll an[N][35];
ll depth[N]={0};
ll siz;
ll res = 0;
ll mycbrt(ll num){ll l = 1,r = 1000000;ll ans = 0;while(l <= r){ll mid = (l+r)/2;if(mid * mid * mid <= num){l = mid + 1;ans = max(ans,mid);}else{r = mid - 1;}}return ans;}
ll lcm(ll a,ll b){return (a * b) / __gcd(a,b);}
ll gcd(ll a,ll b){return __gcd(a,b);}
ll power(ll a,ll b,ll MOD){if(b == 0)return 1;if(b == 1)return a;ll ans = power(a,b/2,MOD) % MOD;ans *= ans;ans %= MOD;if(b % 2 == 1)ans *= a;return ans%MOD;}
ll inverse(ll x){x%=MOD;return power(x,MOD-2,MOD);}
void BITup(ll k, ll x){while(k <= siz){bit[k]+=x;k += k & -k;}}
ll BITq(ll k){ll s=0;while(k>=1){s+=bit[k];k -= k &-k;}return s;}
struct point{ll x,y,idx;};
void dfs(ll v){visit[v] = 1;for(auto x:adj[v]){if(!visit[x]){depth[x] = depth[v] + 1;dfs(x);}}}
void bfs(ll s){visit[s] = 1;queue<ll>q;q.push(s);while(!q.empty()){ll u = q.front();ps(u);q.pop();for(auto x:adj[u]){if(!visit[x]){visit[x] = 1;q.push(x);}}}}
void dijkstra(ll s){pq.push(ii(0,s));dist[s] = 0;while(!pq.empty()){ii f = pq.top();pq.pop();ll w = f.F;ll u = f.S;if(w > dist[u]){continue;}for(auto v:adj2[u]){if(dist[u] + v.S < dist[v.F]){dist[v.F] = dist[u] + v.S;pq.push(ii(dist[v.F],v.F));}}}}
void prim(ll edge) {taken[edge] = 1;for(auto v:adj2[edge]) {if (taken[v.first]==0)pq.push(ii(v.second, v.first));}}
ll mst(ll s){taken.assign(N, 0);prim(s);ll cost = 0;while(!pq.empty()){ii front = pq.top();pq.pop();ll w = front.first;ll u = front.second;if(taken[u]==0)cost += w;prim(u);}return cost;}
void bfs01(ll s){deque<ll>q;dist[s] = 0;q.push_back(s);while(!q.empty()){ll v = q.front();q.pop_front();for(auto x:adj2[v]){if(dist[x.F] > dist[v] + x.S){dist[x.F] = dist[v] + x.S;if(x.S == 0){q.push_front(x.F);}else{q.push_back(x.F);}}}}}
void build(ll s,ll p){an[s][0] = p;f(i,1,35){an[s][i] = an[an[s][i-1]][i-1];}for(auto x:adj[s]){if(x != p){depth[x] = depth[s] + 1;build(x,s);}}}
ll kth(ll x,ll k){ll ans = x;if(depth[x] < k){return -1;}ll pos = 0;while(k > 0){if(k % 2){ans = an[ans][pos];}pos++;k /= 2;}return ans;}
ll lca(ll a,ll b){if(depth[a] > depth[b]){swap(a,b);}b = kth(b,abs(depth[a] - depth[b]));if(a == b){return a;}for(ll i = 34;i >= 0;i--){if(an[a][i] == an[b][i]){continue;}a = an[a][i];b = an[b][i];}return an[a][0];}
ll find_dsu(ll x){if(par[x] == x){return x;}par[x] = find_dsu(par[x]);return par[x];}
void union_dsu(ll x,ll y){ll pos1 = find_dsu(x);ll pos2 = find_dsu(y);par[pos2] = pos1;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<ll> distr;
ll rnd(ll a, ll b){return distr(rng)%(b-a+1)+a;}
void YESNO(ll a){if(!!a){pl("Yes");}else{pl("No");}}
void filesin(void){freopen("amusing.in","r",stdin);}
void filesout(void){freopen("amusing.out","w",stdout);}
///I hope I will get uprating and don't make mistakes
///I will never stop programming
///sqrt(-1) Love C++
///Please don't hack me
///@TheofanisOrfanou Theo830
///Codeforces Raif Round 1 (Div. 1 + Div. 2)
int main(void){
    fastio;
    ll n;
    cin>>n;
    ll arr[n];
    arrin(arr,n);
    set<ll>rows;
    set<ll>ro1;
    f(i,0,n){
        rows.insert(i+1);
    }
    vii ar,ans;
    bool ok = 1;
    f(i,0,n){
        if(arr[i] == 0){
            continue;
        }
        else if(arr[i] == 1){
            if(ar.empty()){
                if(!ro1.empty()){
                    auto it = ro1.begin();
                    ro1.erase(it);
                    ans.pb(ii(i+1,*(it)));
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                    }
                }
            }
            else{
                ii x = ar.back();
                ar.pop_back();
                if(x.F == 2){
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                        ro1.insert((*it));
                    }
                }
            }
        }
        else{
            cout<<i+1<<endl;
            ar.pb(ii(arr[i],i+1));
        }
    }
    if(!ar.empty()){
        ok = 0;
    }
    if(!ok){
        pl(-1);
    }
    else{
        cout<<ans.size()<<endl;
        for(auto x:ans){
            cout<<x.S<<" "<<x.F<<endl;
        }
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll INF = 1e9+7;
ll MOD = 998244353;
typedef pair<ll,ll> ii;
#define iiii pair<ii,ii>
#define f(i,a,b) for(ll i = a;i < b;i++)
#define rf(i,a,b) for(long long i=a;i>=b;i--)
#define fastio ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define w(t) while(t--)
#define c(n); cin>>n;
#define p(n) cout<<n;
#define pl(n) cout<<n<<"\n";
#define ps(n); cout<<n<<" ";
#define F first
#define S second
#define pb(a) push_back(a)
#define all(x) (x).begin(), (x).end()
#define ull unsigned long long
#define vll vector<ll>
#define vii vector<ii>
#define mkp make_pair
#define ld long double
#define arrin(a,n) f(i,0,n){cin>>a[i];}
#define arrout(a,n) f(i,0,n){cout<<a[i]<<" ";}
#define printclock cerr<<"Time : "<<*(ld)clock()/(ld)CLOCKS_PER_SEC<<"ms\n";
#define PI (2*acos(0))
#define EPS 1e-18
const long long N = 1e6+5;
const long long M = 1e6+5;
vll visit,dist,taken;
vector<vll> adj;
vector<vii> adj2;
priority_queue<ii,vector<ii>, greater<ii> > pq;
ll bit[N]={0};
ll par[N]={0};
ll an[N][35];
ll depth[N]={0};
ll siz;
ll res = 0;
ll mycbrt(ll num){ll l = 1,r = 1000000;ll ans = 0;while(l <= r){ll mid = (l+r)/2;if(mid * mid * mid <= num){l = mid + 1;ans = max(ans,mid);}else{r = mid - 1;}}return ans;}
ll lcm(ll a,ll b){return (a * b) / __gcd(a,b);}
ll gcd(ll a,ll b){return __gcd(a,b);}
ll power(ll a,ll b,ll MOD){if(b == 0)return 1;if(b == 1)return a;ll ans = power(a,b/2,MOD) % MOD;ans *= ans;ans %= MOD;if(b % 2 == 1)ans *= a;return ans%MOD;}
ll inverse(ll x){x%=MOD;return power(x,MOD-2,MOD);}
void BITup(ll k, ll x){while(k <= siz){bit[k]+=x;k += k & -k;}}
ll BITq(ll k){ll s=0;while(k>=1){s+=bit[k];k -= k &-k;}return s;}
struct point{ll x,y,idx;};
void dfs(ll v){visit[v] = 1;for(auto x:adj[v]){if(!visit[x]){depth[x] = depth[v] + 1;dfs(x);}}}
void bfs(ll s){visit[s] = 1;queue<ll>q;q.push(s);while(!q.empty()){ll u = q.front();ps(u);q.pop();for(auto x:adj[u]){if(!visit[x]){visit[x] = 1;q.push(x);}}}}
void dijkstra(ll s){pq.push(ii(0,s));dist[s] = 0;while(!pq.empty()){ii f = pq.top();pq.pop();ll w = f.F;ll u = f.S;if(w > dist[u]){continue;}for(auto v:adj2[u]){if(dist[u] + v.S < dist[v.F]){dist[v.F] = dist[u] + v.S;pq.push(ii(dist[v.F],v.F));}}}}
void prim(ll edge) {taken[edge] = 1;for(auto v:adj2[edge]) {if (taken[v.first]==0)pq.push(ii(v.second, v.first));}}
ll mst(ll s){taken.assign(N, 0);prim(s);ll cost = 0;while(!pq.empty()){ii front = pq.top();pq.pop();ll w = front.first;ll u = front.second;if(taken[u]==0)cost += w;prim(u);}return cost;}
void bfs01(ll s){deque<ll>q;dist[s] = 0;q.push_back(s);while(!q.empty()){ll v = q.front();q.pop_front();for(auto x:adj2[v]){if(dist[x.F] > dist[v] + x.S){dist[x.F] = dist[v] + x.S;if(x.S == 0){q.push_front(x.F);}else{q.push_back(x.F);}}}}}
void build(ll s,ll p){an[s][0] = p;f(i,1,35){an[s][i] = an[an[s][i-1]][i-1];}for(auto x:adj[s]){if(x != p){depth[x] = depth[s] + 1;build(x,s);}}}
ll kth(ll x,ll k){ll ans = x;if(depth[x] < k){return -1;}ll pos = 0;while(k > 0){if(k % 2){ans = an[ans][pos];}pos++;k /= 2;}return ans;}
ll lca(ll a,ll b){if(depth[a] > depth[b]){swap(a,b);}b = kth(b,abs(depth[a] - depth[b]));if(a == b){return a;}for(ll i = 34;i >= 0;i--){if(an[a][i] == an[b][i]){continue;}a = an[a][i];b = an[b][i];}return an[a][0];}
ll find_dsu(ll x){if(par[x] == x){return x;}par[x] = find_dsu(par[x]);return par[x];}
void union_dsu(ll x,ll y){ll pos1 = find_dsu(x);ll pos2 = find_dsu(y);par[pos2] = pos1;}
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_int_distribution<ll> distr;
ll rnd(ll a, ll b){return distr(rng)%(b-a+1)+a;}
void YESNO(ll a){if(!!a){pl("Yes");}else{pl("No");}}
void filesin(void){freopen("amusing.in","r",stdin);}
void filesout(void){freopen("amusing.out","w",stdout);}
///I hope I will get uprating and don't make mistakes
///I will never stop programming
///sqrt(-1) Love C++
///Please don't hack me
///@TheofanisOrfanou Theo830
///Codeforces Raif Round 1 (Div. 1 + Div. 2)
int main(void){
    fastio;
    ll n;
    cin>>n;
    ll arr[n];
    arrin(arr,n);
    set<ll>rows;
    set<ll>ro1;
    f(i,0,n){
        rows.insert(i+1);
    }
    vii ar,ans;
    bool ok = 1;
    f(i,0,n){
        if(arr[i] == 0){
            continue;
        }
        else if(arr[i] == 1){
            if(ar.empty()){
                if(!ro1.empty()){
                    auto it = ro1.begin();
                    ro1.erase(it);
                    ans.pb(ii(i+1,*(it)));
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                    }
                }
            }
            else{
                ii x = ar.back();
                ar.pop_back();
                if(x.F == 2){
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                }
                else{
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        ans.pb(ii(x.S,*(it)));
                        rows.erase(it);
                    }
                    if(rows.empty()){
                        ok = 0;
                        break;
                    }
                    else{
                        auto it = rows.begin();
                        ans.pb(ii(i+1,*(it)));
                        rows.erase(it);
                        ro1.insert((*it));
                    }
                }
            }
        }
        else{
            ar.pb(ii(arr[i],i+1));
        }
    }
    if(!ar.empty()){
        ok = 0;
    }
    if(!ok){
        pl(-1);
    }
    else{
        cout<<ans.size()<<endl;
        for(auto x:ans){
            ps(x.F);pl(x.S);
        }
    }
}