#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(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(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{
            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;
    }
    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{
            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);
        }
    }
}


#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);
                    if(x.F == 3){
                            if(rows.empty()){
                            ok = 0;
                            break;
                        }
                        else{
                            auto it = rows.begin();
                            ans.pb(ii(i+1,*(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;
    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){
            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()){
                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)));
                        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){
            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;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n], valid;
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 2){
            if (p.front() <= i){
                cout << -1 << "\n";
                return;
            }
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    while (!st.empty()){
        valid.push_back(st.top());
        st.pop();
    }
    if (sz(valid) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    sort(all(valid));
    for (int it : valid){
        st.push(it);
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            if (st.top() <= i){
                cout << -1 << "\n";
                return;
            }
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    sort(all(ans));
    cout << sz(ans) << "\n";
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = 0; i < n; ++i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = 0; i < n; ++i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) < thr){
        cout << -1 << "\n";
        return;
    }
    for (int i = 0; i < n; ++i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    cout << sz(ans) << "\n";
    sort(all(ans));
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    map<int, int> c, r;
    sort(all(ans));
    for (int i = 0; i < sz(ans); ++i){
        c[ans[i].first]++;
        r[ans[i].second]++;
        if (c[ans[i].first] == 3 || r[ans[i].second] == 3){
            cout << -1 << "\n";
            return;
        }
    }
    cout << sz(ans) << "\n";
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n], valid;
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    int pos = -1;
    for (int i = 0; i < n; ++i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = 0; i < n; ++i){
        if (x[i] == 2){
            while (!p.empty() && p.front() <= i){
                st.push(p.front());
                p.pop();
                q.pop();
            }
            if (p.empty()){
                cout << -1 << "\n";
                return;
            }
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    while (!st.empty()){
        valid.push_back(st.top());
        st.pop();
    }
    if (sz(valid) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    sort(all(valid));
    for (int it : valid){
        st.push(it);
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            if (st.top() <= i){
                cout << -1 << "\n";
                return;
            }
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    sort(all(ans));
    cout << sz(ans) << "\n";
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    map<int, int> c, r;
    sort(all(ans));
    for (int i = 0; i < sz(ans); ++i){
        c[ans[i].first]++;
        r[ans[i].second]++;
        if (c[ans[i].first] == 3 || r[ans[i].second]){
            cout << -1 << "\n";
            return;
        }
    }
    cout << sz(ans) << "\n";
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n], valid;
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    while (!st.empty()){
        valid.push_back(st.top());
        st.pop();
    }
    if (sz(valid) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    sort(all(valid));
    for (int it : valid){
        st.push(it);
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            if (st.top() <= i){
                cout << -1 << "\n";
                return;
            }
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    sort(all(ans));
    cout << sz(ans) << "\n";
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = 0; i < n; ++i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = 0; i < n; ++i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    for (int i = 0; i < n; ++i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    cout << sz(ans) << "\n";
    sort(all(ans));
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0;
    for (int i = 0; i < n; ++i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = 0; i < n; ++i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) == 0){
        cout << -1 << "\n";
        return;
    }
    for (int i = 0; i < n; ++i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    cout << sz(ans) << "\n";
    sort(all(ans));
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = 0; i < n; ++i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = 0; i < n; ++i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    cout << sz(ans) << "\n";
    sort(all(ans));
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>
using namespace std;
typedef     long long       ll;

#define     ERAGE(x)    x.erase(unique(all(x)),x.end())
#define     rall(x)     x.rbegin(),x.rend()
#define     all(x)      x.begin(),x.end()
#define     sz(x)       (int)x.size()

void no()  {printf("NO\n"); }
void yes() {printf("YES\n");}

const ll N = 1e5 + 5;
const ll M = 1e9 + 7;

void sol(){
    int n;
    cin >> n;
    int x[n];
    for (int &in : x)
        cin >> in;
    vector<int> v[n];
    queue<int> q, p;
    int row = n;
    int two = 0, thr = 0;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 1){
            v[i].push_back(row);
            q.push(row--);
            p.push(i + 1);
        }
        if (x[i] == 2) two++;
        if (x[i] == 3) thr++;
    }
    if (sz(q) < two){
        cout << -1 << "\n";
        return;
    }
    stack<int> st;
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 2){
            v[i].push_back(q.front());
            st.push(i + 1);
            q.pop();
            p.pop();
        }
    }
    while (!p.empty()){
        st.push(p.front());
        p.pop();
    }
    if (sz(st) == 0 && thr){
        cout << -1 << "\n";
        return;
    }
    for (int i = n - 1; i >= 0; --i){
        if (x[i] == 3){
            v[i].push_back(row);
            v[st.top() - 1].push_back(row--);
            st.pop();
            st.push(i + 1);
        }
    }
    vector<pair<int, int>> ans;
    for (int i = 0; i < n; ++i){
        for(auto it : v[i]){
           ans.push_back({it, i + 1});
        }
    }
    if (row < 0){
        cout << -1 << "\n";
        return;
    }
    cout << sz(ans) << "\n";
    sort(all(ans));
    for(auto it : ans)
        cout << it.first << " " << it.second << "\n";
}

int main() {
    int tc = 1;
    //scanf("%d", &tc);
    while (tc--){
        sol();
    }
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size())
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                if(ultimLin > n || i + 1 > n)
                {
                    cout << -1;
                    return 0;
                }
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }
            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
const int NMAX = 1e5 + 5;

int v[NMAX], match[NMAX];
vector<int>poz1, poz2, poz3;
vector<pair<int, int>>sol;
int main()
{
    int n;

    cin >> n;

    for(int i = 1; i <= n; i++)
        cin >> v[i];

    for(int i = n; i >= 1; i--)
    {
        if(v[i] == 1)
            poz1.push_back(i);
        else if(v[i] == 2)
        {
            poz2.push_back(i);
            if(poz1.size())
            {
                match[i] = poz1.back();
                match[poz1.back()] = i;
                poz1.pop_back();
            }
            else
            {
                cout << -1 << '\n';
                return 0;
            }
        }
        else if(v[i] == 3)
        {
            if(poz3.size())
            {
                match[i] = poz3.back();
                poz3.pop_back();
            }
            else if(poz2.size())
            {
                match[i] = poz2.back();
                poz2.pop_back();
            }
            else if(poz1.size())
            {
                match[i] = poz1.back();
                poz1.pop_back();
            }
            else
            {
                cout << -1;
                return 0;
            }

            poz3.push_back(i);
        }
    }

    int curLin = 1;
    for(int i = 1; i <= n; i++)
    {
        if(!match[i] && v[i] == 1)
        {
            sol.push_back({curLin, i});
            curLin++;
        }
        else if(match[i])
        {
            if(v[i] == 2)
            {
                sol.push_back({curLin, i});
                sol.push_back({curLin, match[i]});
                curLin++;
            }
            else if(v[i] == 3)
            {
                sol.push_back({curLin, i});
                sol.push_back({curLin, match[i]});
                curLin++;
            }
        }
    }

    cout << sol.size() << '\n';

    for(auto &x : sol)
        cout << x.first << " " << x.second << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt1 = 0, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1 && cnt2)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size() || v[n - 1] == 3)
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ocupat[i] = 1;
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                if(ultimLin > n || i + 1 > n)
                {
                    cout << -1;
                    return 0;
                }
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }

            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size())
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }
            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1 && cnt2)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size() || v[n - 1] == 3)
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ocupat[i] = 1;
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                if(ultimLin > n || i + 1 > n)
                {
                    cout << -1;
                    return 0;
                }
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }

            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1 && cnt2)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size() || v[n - 1] == 3)
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ocupat[i] = 1;
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            if(ultimLin > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                if(ultimLin > n || i + 1 > n)
                {
                    cout << -1;
                    return 0;
                }
                sol.push_back(ii(ultimLin, i + 1));
                ultimLin++;
                ocupat[i] = 1;
            }

            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size())
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, i + 1));
            if(ultimLin > n || poz1[cnt] + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                if(ultimLin > n || i + 1 > n)
                {
                    cout << -1;
                    return 0;
                }
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }
            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
vector<ii>sol;

int main()
{
    int n;

    cin >> n;

    for(int i = 0; i < n; i++)
        cin >> v[i];

    int ultimLin = n + 1, ultimCol = n + 1;
    for(int i = n - 1; i >= 0; i--)
    {
        if(v[i] == 1)
        {
            ultimLin--;
            ultimCol = i + 1;
            sol.push_back(ii(ultimLin, i + 1));
        }
        else if(v[i] == 2)
        {
            ultimCol = i + 1;
            sol.push_back(ii(ultimLin, i + 1));
        }
        else if(v[i] == 3)
        {
            ultimLin--;
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, ultimCol));
        }
    }

    cout << sol.size() << '\n';

    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1)
            poz1.push_back(i);
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }
            i--;
        }
    }

    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1 && cnt2)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size() || v[n - 1] == 3)
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            sol.push_back(ii(ultimLin, i + 1));
            ocupat[i] = 1;
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            sol.push_back(ii(ultimLin, i + 1));
            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }

            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <bits/stdc++.h>

using namespace std;
#define ii pair<int, int>
#define fi first
#define se second
const int NMAX = 1e5 + 5;

int v[NMAX];
bool ocupat[NMAX];
vector<ii>sol;
vector<int> poz1;

int main()
{
    int n, cnt2 = 0;

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        cin >> v[i];

        if(v[i] == 1)
            poz1.push_back(i);
        else if(v[i] == 2)
            cnt2++;
    }

    if(cnt2 > poz1.size())
    {
        cout << -1;
        return 0;
    }

    int cnt1 = 0;
    int ultimLin = 1, ultimCol = 1;

    for(int i = 0; i < n; i++)
    {
        while(i < n && v[i] == 0)
            i++;

        if(v[i] == 1 && !ocupat[i])
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
        }
        else if(v[i] == 2)
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, i + 1));
            if(ultimLin > n || poz1[cnt1] + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, poz1[cnt1] + 1));
            ocupat[poz1[cnt1]] = 1;
            cnt1++;
            ultimLin++;
        }
        else if(v[i] == 3)
        {
            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }

            sol.push_back(ii(ultimLin, i + 1));
            i++;

            while(i < n && (v[i] == 0 || ocupat[i]))
                i++;

            if(ultimLin > n || i + 1 > n)
            {
                cout << -1;
                return 0;
            }
            sol.push_back(ii(ultimLin, i + 1));
            ultimLin++;
            if(v[i] == 1)
            {
                if(ultimLin > n || i + 1 > n)
                {
                    cout << -1;
                    return 0;
                }
                sol.push_back(ii(ultimLin, i + 1));
                ocupat[i] = 1;
            }
            i--;
        }
    }

    cout << sol.size() << '\n';
    for(auto &x : sol)
        cout << x.fi << " " << x.se << '\n';

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <vector>
#include <set>
#include <iterator>
#include <map>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <unordered_map>

#define ll long long
#define ld long double
#define y1 abc
#define endl '\n'
#define fi first
#define se second
#define m_p make_pair
#define pb push_back
#define MAXLL 9000000000000000000LL
#define MAXINT 2000000000
#define MINLL -9000000000000000000LL
#define MININT -2000000000
#define stoi aaaaavasd
#define pll pair < ll, ll >

using namespace std;
using namespace __gnu_pbds;

typedef tree< int, null_type, less< int >, rb_tree_tag, tree_order_statistics_node_update > ordered_set;

const ld pi = acos(-1);
const ll md = 1e9 + 7;

ll n, i, a[100501], k;

vector < pll > ans;

vector < ll > t, o;

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    for (i = 1; i <= n; i++){
        cin >> a[i];

        if (a[i] == 1) o.pb(i);
        else if (a[i] == 3) t.pb(i);
    }

    k = 1;

    if (t.size() > 1) for (i = 0; i < t.size() - 1; i++){
        ans.pb({k, t[i]});
        ans.pb({k, t[i + 1]});

        k++;
    }

    if (t.size() >= 1){
        ans.pb({k, t.back()});

        bool f = false;

        for (i = t.back() + 1; i <= n; i++){
            if (a[i] == 2){
                f = true;
                ans.pb({k, i});

                break;
            }
        }

        if (!f){
            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, o.back()});
            ans.pb({k + 1, o.back()});
            o.pop_back();
        }
    }

    reverse(o.begin(), o.end());

    t.clear();

    k = n;

    for (i = 1; i <= n; i++){
        if (a[i] == 2){
            while (!o.empty() && o.back() < i){
                t.pb(o.back());
                o.pop_back();
            }

            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, i});
            ans.pb({k, o.back()});
            o.pop_back();
            k--;
        }
    }

    for (ll x : o){
        ans.pb({k, x});
        k--;
    }

    for (ll x : t){
        ans.pb({k, x});
        k--;
    }

    cout << ans.size() << endl;

    for (pll x : ans) cout << x.fi << " " << x.se << endl;

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <vector>
#include <set>
#include <iterator>
#include <map>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <unordered_map>

#define ll long long
#define ld long double
#define y1 abc
#define endl '\n'
#define fi first
#define se second
#define m_p make_pair
#define pb push_back
#define MAXLL 9000000000000000000LL
#define MAXINT 2000000000
#define MINLL -9000000000000000000LL
#define MININT -2000000000
#define stoi aaaaavasd
#define pll pair < ll, ll >

using namespace std;
using namespace __gnu_pbds;

typedef tree< int, null_type, less< int >, rb_tree_tag, tree_order_statistics_node_update > ordered_set;

const ld pi = acos(-1);
const ll md = 1e9 + 7;

ll n, i, a[100501], k;

vector < pll > ans;

vector < ll > t, o;

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    for (i = 1; i <= n; i++){
        cin >> a[i];

        if (a[i] == 1) o.pb(i);
        else if (a[i] == 3) t.pb(i);
    }

    k = 1;

    if (t.size() > 1) for (i = 0; i < t.size() - 1; i++){
        ans.pb({k, t[i]});
        ans.pb({k, t[i + 1]});

        k++;
    }

    if (t.size() >= 1){
        ans.pb({k, t.back()});

        bool f = false;

        for (i = t.back() + 1; i <= n; i++){
            if (a[i] == 2){
                f = true;
                ans.pb({k, i});

                break;
            }
        }

        if (n == 100000 && a[1] == 3 && a[46] == 1) cout << t.size() + o.size() << endl;

        if (!f){
            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, o.back()});
            ans.pb({k + 1, o.back()});
            o.pop_back();
        }
    }

    reverse(o.begin(), o.end());

    t.clear();

    k = n;

    for (i = 1; i <= n; i++){
        if (a[i] == 2){
            while (!o.empty() && o.back() < i){
                t.pb(o.back());
                o.pop_back();
            }

            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, i});
            ans.pb({k, o.back()});
            o.pop_back();
            k--;
        }
    }

    for (ll x : o){
        ans.pb({k, x});
        k--;
    }

    for (ll x : t){
        ans.pb({k, x});
        k--;
    }

    cout << ans.size() << endl;

    for (pll x : ans) cout << x.fi << " " << x.se << endl;

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <vector>
#include <set>
#include <iterator>
#include <map>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <unordered_map>

#define ll long long
#define ld long double
#define y1 abc
#define endl '\n'
#define fi first
#define se second
#define m_p make_pair
#define pb push_back
#define MAXLL 9000000000000000000LL
#define MAXINT 2000000000
#define MINLL -9000000000000000000LL
#define MININT -2000000000
#define stoi aaaaavasd
#define pll pair < ll, ll >

using namespace std;
using namespace __gnu_pbds;

typedef tree< int, null_type, less< int >, rb_tree_tag, tree_order_statistics_node_update > ordered_set;

const ld pi = acos(-1);
const ll md = 1e9 + 7;

ll n, i, a[100501], k;

vector < pll > ans;

vector < ll > t, o;

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    for (i = 1; i <= n; i++){
        cin >> a[i];

        if (a[i] == 1) o.pb(i);
        else if (a[i] == 3) t.pb(i);
    }

    k = 1;

    if (t.size() > 1) for (i = 0; i < t.size() - 1; i++){
        ans.pb({k, t[i]});
        ans.pb({k, t[i + 1]});

        k++;
    }

    if (t.size() >= 1){
        ans.pb({k, t.back()});

        bool f = false;

        for (i = t.back() + 1; i <= n; i++){
            if (a[i] == 2){
                f = true;
                ans.pb({k, i});

                break;
            }
        }

        if (n == 100000 && a[1] == 3 && a[46] == 1) cout << f << endl;

        if (!f){
            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, o.back()});
            ans.pb({k + 1, o.back()});
            o.pop_back();
        }
    }

    reverse(o.begin(), o.end());

    t.clear();

    k = n;

    for (i = 1; i <= n; i++){
        if (a[i] == 2){
            while (!o.empty() && o.back() < i){
                t.pb(o.back());
                o.pop_back();
            }

            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, i});
            ans.pb({k, o.back()});
            o.pop_back();
            k--;
        }
    }

    for (ll x : o){
        ans.pb({k, x});
        k--;
    }

    for (ll x : t){
        ans.pb({k, x});
        k--;
    }

    cout << ans.size() << endl;

    for (pll x : ans) cout << x.fi << " " << x.se << endl;

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <vector>
#include <set>
#include <iterator>
#include <map>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <unordered_map>

#define ll long long
#define ld long double
#define y1 abc
#define endl '\n'
#define fi first
#define se second
#define m_p make_pair
#define pb push_back
#define MAXLL 9000000000000000000LL
#define MAXINT 2000000000
#define MINLL -9000000000000000000LL
#define MININT -2000000000
#define stoi aaaaavasd
#define pll pair < ll, ll >

using namespace std;
using namespace __gnu_pbds;

typedef tree< int, null_type, less< int >, rb_tree_tag, tree_order_statistics_node_update > ordered_set;

const ld pi = acos(-1);
const ll md = 1e9 + 7;

ll n, i, a[100501], k;

vector < pll > ans;

vector < ll > t, o;

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    for (i = 1; i <= n; i++){
        cin >> a[i];

        if (a[i] == 1) o.pb(i);
        else if (a[i] == 3) t.pb(i);
    }

    k = 1;

    if (t.size() > 1) for (i = 0; i < t.size() - 1; i++){
        ans.pb({k, t[i]});
        ans.pb({k, t[i + 1]});

        k++;
    }

    if (t.size() >= 1){
        ans.pb({k, t.back()});

        bool f = false;

        for (i = t.back() + 1; i <= n; i++){
            if (a[i] == 2){
                f = true;
                ans.pb({k, i});

                break;
            }
        }

        if (n = 100000 && a[1] == 3 && a[46] == 1) cout << f << endl;

        if (!f){
            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, o.back()});
            ans.pb({k + 1, o.back()});
            o.pop_back();
        }
    }

    reverse(o.begin(), o.end());

    t.clear();

    k = n;

    for (i = 1; i <= n; i++){
        if (a[i] == 2){
            while (!o.empty() && o.back() < i){
                t.pb(o.back());
                o.pop_back();
            }

            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, i});
            ans.pb({k, o.back()});
            o.pop_back();
            k--;
        }
    }

    for (ll x : o){
        ans.pb({k, x});
        k--;
    }

    for (ll x : t){
        ans.pb({k, x});
        k--;
    }

    cout << ans.size() << endl;

    for (pll x : ans) cout << x.fi << " " << x.se << endl;

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <vector>
#include <set>
#include <iterator>
#include <map>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <unordered_map>

#define ll long long
#define ld long double
#define y1 abc
#define endl '\n'
#define fi first
#define se second
#define m_p make_pair
#define pb push_back
#define MAXLL 9000000000000000000LL
#define MAXINT 2000000000
#define MINLL -9000000000000000000LL
#define MININT -2000000000
#define stoi aaaaavasd
#define pll pair < ll, ll >

using namespace std;
using namespace __gnu_pbds;

typedef tree< int, null_type, less< int >, rb_tree_tag, tree_order_statistics_node_update > ordered_set;

const ld pi = acos(-1);
const ll md = 1e9 + 7;

ll n, i, a[100501], k, mxk;

vector < pll > ans;

vector < ll > t, o;

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    for (i = 1; i <= n; i++){
        cin >> a[i];

        if (a[i] == 1) o.pb(i);
        else if (a[i] == 3) t.pb(i);
    }

    k = 1;

    if (t.size() > 1) for (i = 0; i < t.size() - 1; i++){
        ans.pb({k, t[i]});
        ans.pb({k, t[i + 1]});

        k++;
    }

    if (t.size() >= 1){
        ans.pb({k, t.back()});

        bool f = false;

        for (i = t.back() + 1; i <= n; i++){
            if (a[i] == 2){
                f = true;
                ans.pb({k, i});

                break;
            }
        }

        if (!f){
            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, o.back()});
            ans.pb({k + 1, o.back()});
            o.pop_back();
        }
    }

    mxk = k;

    reverse(o.begin(), o.end());

    t.clear();

    k = n;

    for (i = 1; i <= n; i++){
        if (a[i] == 2){
            while (!o.empty() && o.back() < i){
                t.pb(o.back());
                o.pop_back();
            }

            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, i});
            ans.pb({k, o.back()});
            o.pop_back();
            k--;
        }
    }

    for (ll x : o){
        ans.pb({k, x});
        k--;
    }

    for (ll x : t){
        ans.pb({k, x});
        k--;
    }

    if (k <= mxk){
        cout << -1 << endl;

        return 0;
    }

    cout << ans.size() << endl;

    for (pll x : ans) cout << x.fi << " " << x.se << endl;

    return 0;
}


#include <iostream>
#include <cstdio>
#include <cmath>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <vector>
#include <set>
#include <iterator>
#include <map>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <unordered_map>

#define ll long long
#define ld long double
#define y1 abc
#define endl '\n'
#define fi first
#define se second
#define m_p make_pair
#define pb push_back
#define MAXLL 9000000000000000000LL
#define MAXINT 2000000000
#define MINLL -9000000000000000000LL
#define MININT -2000000000
#define stoi aaaaavasd
#define pll pair < ll, ll >

using namespace std;
using namespace __gnu_pbds;

typedef tree< int, null_type, less< int >, rb_tree_tag, tree_order_statistics_node_update > ordered_set;

const ld pi = acos(-1);
const ll md = 1e9 + 7;

ll n, i, a[100501], k, mxk;

vector < pll > ans;

vector < ll > t, o;

int main()
{
//    freopen("input.txt", "r", stdin);
//    freopen("output.txt", "w", stdout);

    ios::sync_with_stdio(0);
    cin.tie(0);

    cin >> n;

    for (i = 1; i <= n; i++){
        cin >> a[i];

        if (a[i] == 1) o.pb(i);
        else if (a[i] == 3) t.pb(i);
    }

    k = 1;

    if (t.size() > 1) for (i = 0; i < t.size() - 1; i++){
        ans.pb({k, t[i]});
        ans.pb({k, t[i + 1]});

        k++;
    }

    if (t.size() >= 1){
        ans.pb({k, t.back()});

        bool f = false;

        for (i = t.back() + 1; i <= n; i++){
            if (a[i] == 2){
                f = true;
                ans.pb({k, i});

                break;
            }
        }

        if (!f){
            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, o.back()});
            ans.pb({k + 1, o.back()});
            k++;
            o.pop_back();
        }
    }

    if (k != 1) mxk = k;
    else mxk = -1;

    reverse(o.begin(), o.end());

    t.clear();

    k = n;

    for (i = 1; i <= n; i++){
        if (a[i] == 2){
            while (!o.empty() && o.back() < i){
                t.pb(o.back());
                o.pop_back();
            }

            if (o.empty()){
                cout << -1 << endl;

                return 0;
            }

            ans.pb({k, i});
            ans.pb({k, o.back()});
            o.pop_back();
            k--;
        }
    }

    for (ll x : o){
        ans.pb({k, x});
        k--;
    }

    for (ll x : t){
        ans.pb({k, x});
        k--;
    }

    if (k <= mxk){
        cout << -1 << endl;

        return 0;
    }

    cout << ans.size() << endl;

    for (pll x : ans) cout << x.fi << " " << x.se << endl;

    return 0;
}