#include <bits/stdc++.h>
using namespace std;
template <typename T>
istream& operator>>(istream& i, vector<T>& v) {
  for (int j = 0; j < (int)((int)(v).size()); j++) i >> v[j];
  return i;
}
template <typename T>
string join(const vector<T>& v) {
  stringstream s;
  for (int i = 0; i < (int)((int)(v).size()); i++) s << ' ' << v[i];
  return s.str().substr(1);
}
template <typename T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  if ((int)(v).size()) o << join(v);
  return o;
}
template <typename T1, typename T2>
istream& operator>>(istream& i, pair<T1, T2>& v) {
  return i >> v.first >> v.second;
}
template <typename T1, typename T2>
ostream& operator<<(ostream& o, const pair<T1, T2>& v) {
  return o << v.first << "," << v.second;
}
template <typename T>
bool mins(T& x, const T& y) {
  if (x > y) {
    x = y;
    return true;
  } else
    return false;
}
template <typename T>
bool maxs(T& x, const T& y) {
  if (x < y) {
    x = y;
    return true;
  } else
    return false;
}
template <typename T>
long long suma(const vector<T>& a) {
  long long res(0);
  for (auto&& x : a) res += x;
  return res;
}
template <typename T>
struct edge {
  int src, to;
  T cost;
  edge(int to, T cost) : src(-1), to(to), cost(cost) {}
  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}
  edge& operator=(const int& x) {
    to = x;
    return *this;
  }
  operator int() const { return to; }
};
template <typename T>
using Edges = vector<edge<T>>;
template <typename T>
using WeightedGraph = vector<Edges<T>>;
using UnWeightedGraph = vector<vector<int>>;
template <typename T>
using Matrix = vector<vector<T>>;
const long long LINF = 1LL << 62;
const int INF = 1001001001;
int main() {
  int n;
  cin >> n;
  vector<int> a(n);
  cin >> a;
  queue<int> q1, q2;
  vector<pair<int, int>> ans;
  int m = 1;
  for (int i = 0; i < n; i++) {
    switch (a[i]) {
      case 0:
        break;
      case 1:
        if (!q1.empty()) {
          int t = q1.front();
          q1.pop();
          ans.push_back({i + 1, t});
          break;
        } else if (!q2.empty()) {
          int t = q2.front();
          q2.pop();
          ans.push_back({i + 1, t});
        }
        ans.push_back({i + 1, m});
        m++;
        break;
      case 2:
        if (!q2.empty()) {
          int t = q2.front();
          q2.pop();
          ans.push_back({i + 1, t});
        }
        ans.push_back({i + 1, m});
        q1.push(m);
        m++;
        break;
      case 3:
        if (!q2.empty()) {
          int t = q2.front();
          q2.pop();
          ans.push_back({i + 1, t});
        }
        ans.push_back({i + 1, m});
        q2.push(m);
        m++;
        break;
    }
  }
  if (!q1.empty() || !q2.empty()) {
    cout << -1 << "\n";
    return 0;
  }
  int l = ans.size();
  cout << l << "\n";
  for (auto v : ans) printf("%d %d\n", v.second, v.first);
  return 0;
}
