package main
import (
"bufio"
"io"
"os"
"strconv"
"strings"
)
type Pair struct {
r int
c int
}
func main() {
data, _ := io.ReadAll(os.Stdin)
idx := 0
nextInt := func() int {
for idx < len(data) && (data[idx] < '0' || data[idx] > '9') && data[idx] != '-' {
idx++
}
sign := 1
if idx < len(data) && data[idx] == '-' {
sign = -1
idx++
}
val := 0
for idx < len(data) && data[idx] >= '0' && data[idx] <= '9' {
val = val*10 + int(data[idx]-'0')
idx++
}
return sign * val
}
n := nextInt()
a := make([]int, n+1)
for i := 1; i <= n; i++ {
a[i] = nextInt()
}
row := make([]int, n+1)
ones := make([]int, 0, n)
chains := make([]int, 0, n)
ans := make([]Pair, 0, 2*n)
cur := n
ok := true
for i := n; i >= 1 && ok; i-- {
switch a[i] {
case 0:
case 1:
if cur == 0 {
ok = false
break
}
row[i] = cur
cur--
ans = append(ans, Pair{row[i], i})
ones = append(ones, i)
case 2:
if len(ones) == 0 {
ok = false
break
}
j := ones[len(ones)-1]
ones = ones[:len(ones)-1]
row[i] = row[j]
ans = append(ans, Pair{row[i], i})
chains = append(chains, i)
case 3:
var j int
if len(chains) > 0 {
j = chains[len(chains)-1]
chains = chains[:len(chains)-1]
} else if len(ones) > 0 {
j = ones[len(ones)-1]
ones = ones[:len(ones)-1]
} else {
ok = false
break
}
if cur == 0 {
ok = false
break
}
row[i] = cur
cur--
ans = append(ans, Pair{row[i], i}, Pair{row[i], j})
chains = append(chains, i)
}
}
w := bufio.NewWriterSize(os.Stdout, 1<<20)
defer w.Flush()
if !ok {
w.WriteString("-1\n")
return
}
var b strings.Builder
b.Grow(len(ans)*16 + 16)
b.WriteString(strconv.Itoa(len(ans)))
b.WriteByte('\n')
for _, p := range ans {
b.WriteString(strconv.Itoa(p.r))
b.WriteByte(' ')
b.WriteString(strconv.Itoa(p.c))
b.WriteByte('\n')
}
w.WriteString(b.String())
}