← Home
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())
}