using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Math;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Library;

namespace Program
{
    public static class ProblemD
    {
        static bool SAIKI = false;
        static public int numberOfRandomCases = 0;
        static public void MakeTestCase(List<string> _input, List<string> _output, ref Func<string[], bool> _outputChecker)
        {
        }
        static public void Solve()
        {
            var n = NN;
            var aList = NNList(n);
            var pos1 = new Queue<long>();
            var pos2 = new Queue<long>();
            var pos3 = new Queue<long>();
            var taiouList = new long[n];
            taiouList.Fill(-1);
            for (var i = n - 1; i >= 0; i--)
            {
                if (aList[i] == 1) pos1.Enqueue(i);
                else if (aList[i] == 2)
                {
                    pos2.Enqueue(i);
                    if (pos1.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }
                    taiouList[i] = pos1.Dequeue();
                }
                else if (aList[i] == 3)
                {
                    if (pos3.Count == 0)
                    {
                        if (pos2.Count == 0)
                        {
                            if (pos1.Count == 0)
                            {
                                Console.WriteLine(-1);
                                return;
                            }
                            else
                            {
                                taiouList[i] = pos1.Dequeue();
                            }
                        }
                        else
                        {
                            taiouList[i] = pos2.Dequeue();
                        }
                    }
                    else
                    {
                        taiouList[i] = pos3.Dequeue();
                    }
                    pos3.Enqueue(i);
                }
            }
            var ansList = new List<(long, long)>();
            for (var i = 0; i < n; i++)
            {
                if (aList[i] == 1)
                {
                    ansList.Add((i + 1, i + 1));
                }
                else if (aList[i] == 2)
                {
                    ansList.Add((i + 1, taiouList[i] + 1));
                }
                else if (aList[i] == 3)
                {
                    ansList.Add((i + 1, i + 1));
                    ansList.Add((taiouList[i] + 1, i + 1));
                }
            }
            Console.WriteLine(ansList.Count);
            foreach (var item in ansList)
            {
                Console.WriteLine($"{item.Item2} {item.Item1}");
            }
        }
        class Printer : StreamWriter
        {
            public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
            public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { base.AutoFlush = false; }
            public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { base.AutoFlush = false; }
        }
        static LIB_FastIO fastio = new LIB_FastIODebug();
        static public void Main(string[] args) { if (args.Length == 0) { fastio = new LIB_FastIO(); Console.SetOut(new Printer(Console.OpenStandardOutput())); } if (SAIKI) { var t = new Thread(Solve, 134217728); t.Start(); t.Join(); } else Solve(); Console.Out.Flush(); }
        static long NN => fastio.Long();
        static double ND => fastio.Double();
        static string NS => fastio.Scan();
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        static long Count<T>(this IEnumerable<T> x, Func<T, bool> pred) => Enumerable.Count(x, pred);
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        static IOrderedEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x, _ => xorshift);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderBy<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderBy(x.OrderByRand(), selector);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x) => Enumerable.OrderByDescending(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderByDescending<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderByDescending(x.OrderByRand(), selector);
        static IOrderedEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderByRand().OrderBy(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderBy(selector, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByRand().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderByDescending(selector, StringComparer.OrdinalIgnoreCase);
        static string Join<T>(this IEnumerable<T> x, string separator = "") => string.Join(separator, x);
        static uint xorshift { get { _xsi.MoveNext(); return _xsi.Current; } }
        static IEnumerator<uint> _xsi = _xsc();
        static IEnumerator<uint> _xsc() { uint x = 123456789, y = 362436069, z = 521288629, w = (uint)(DateTime.Now.Ticks & 0xffffffff); while (true) { var t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); yield return w; } }
        static bool Chmax<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) < 0) { lhs = rhs; return true; } return false; }
        static bool Chmin<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) > 0) { lhs = rhs; return true; } return false; }
        static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);
        static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);
        static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);
        static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);
    }
}
namespace Library {
    class LIB_FastIO
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIO() { str = Console.OpenStandardInput(); }
        readonly Stream str;
        readonly byte[] buf = new byte[2048];
        int len, ptr;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        byte read()
        {
            if (ptr >= len)
            {
                ptr = 0;
                if ((len = str.Read(buf, 0, 2048)) <= 0)
                {
                    return 0;
                }
            }
            return buf[ptr++];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        char Char()
        {
            byte b = 0;
            do b = read();
            while (b < 33 || 126 < b);
            return (char)b;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public long Long()
        {
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = (ret << 3) + (ret << 1) + b - '0';
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
    class LIB_FastIODebug : LIB_FastIO
    {
        Queue<string> param = new Queue<string>();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIODebug() { }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string Scan() => NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override long Long() => long.Parse(NextString());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override double Double() => double.Parse(NextString());
    }
}


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static System.Math;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Library;

namespace Program
{
    public static class ProblemD
    {
        static bool SAIKI = false;
        static public int numberOfRandomCases = 0;
        static public void MakeTestCase(List<string> _input, List<string> _output, ref Func<string[], bool> _outputChecker)
        {
        }
        static public void Solve()
        {
            var n = NN;
            var aList = NNList(n);
            var pos1 = new Queue<long>();
            var pos2 = new Queue<long>();
            var taiouList = new long[n];
            taiouList.Fill(-1);
            for (var i = n - 1; i >= 0; i--)
            {
                if (aList[i] == 1) pos1.Enqueue(i);
                else if (aList[i] == 2)
                {
                    pos2.Enqueue(i);
                    if (pos1.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }
                    taiouList[i] = pos1.Dequeue();
                }
                else if (aList[i] == 3)
                {
                    if (pos2.Count == 0)
                    {
                        if (pos1.Count == 0)
                        {
                            Console.WriteLine(-1);
                            return;
                        }
                        else
                        {
                            taiouList[i] = pos1.Dequeue();
                        }
                    }
                    else
                    {
                        taiouList[i] = pos2.Dequeue();
                    }
                }
            }
            var ansList = new List<(long, long)>();
            for (var i = 0; i < n; i++)
            {
                if (aList[i] == 1)
                {
                    ansList.Add((i + 1, i + 1));
                }
                else if (aList[i] == 2)
                {
                    ansList.Add((i + 1, taiouList[i] + 1));
                }
                else if (aList[i] == 3)
                {
                    ansList.Add((i + 1, i + 1));
                    ansList.Add((taiouList[i] + 1, i + 1));
                }
            }
            Console.WriteLine(ansList.Count);
            foreach (var item in ansList)
            {
                Console.WriteLine($"{item.Item2} {item.Item1}");
            }
        }
        class Printer : StreamWriter
        {
            public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
            public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { base.AutoFlush = false; }
            public Printer(Stream stream, Encoding encoding) : base(stream, encoding) { base.AutoFlush = false; }
        }
        static LIB_FastIO fastio = new LIB_FastIODebug();
        static public void Main(string[] args) { if (args.Length == 0) { fastio = new LIB_FastIO(); Console.SetOut(new Printer(Console.OpenStandardOutput())); } if (SAIKI) { var t = new Thread(Solve, 134217728); t.Start(); t.Join(); } else Solve(); Console.Out.Flush(); }
        static long NN => fastio.Long();
        static double ND => fastio.Double();
        static string NS => fastio.Scan();
        static long[] NNList(long N) => Repeat(0, N).Select(_ => NN).ToArray();
        static double[] NDList(long N) => Repeat(0, N).Select(_ => ND).ToArray();
        static string[] NSList(long N) => Repeat(0, N).Select(_ => NS).ToArray();
        static long Count<T>(this IEnumerable<T> x, Func<T, bool> pred) => Enumerable.Count(x, pred);
        static IEnumerable<T> Repeat<T>(T v, long n) => Enumerable.Repeat<T>(v, (int)n);
        static IEnumerable<int> Range(long s, long c) => Enumerable.Range((int)s, (int)c);
        static IOrderedEnumerable<T> OrderByRand<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x, _ => xorshift);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x) => Enumerable.OrderBy(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderBy<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderBy(x.OrderByRand(), selector);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x) => Enumerable.OrderByDescending(x.OrderByRand(), e => e);
        static IOrderedEnumerable<T1> OrderByDescending<T1, T2>(this IEnumerable<T1> x, Func<T1, T2> selector) => Enumerable.OrderByDescending(x.OrderByRand(), selector);
        static IOrderedEnumerable<string> OrderBy(this IEnumerable<string> x) => x.OrderByRand().OrderBy(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderBy<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderBy(selector, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<string> OrderByDescending(this IEnumerable<string> x) => x.OrderByRand().OrderByDescending(e => e, StringComparer.OrdinalIgnoreCase);
        static IOrderedEnumerable<T> OrderByDescending<T>(this IEnumerable<T> x, Func<T, string> selector) => x.OrderByRand().OrderByDescending(selector, StringComparer.OrdinalIgnoreCase);
        static string Join<T>(this IEnumerable<T> x, string separator = "") => string.Join(separator, x);
        static uint xorshift { get { _xsi.MoveNext(); return _xsi.Current; } }
        static IEnumerator<uint> _xsi = _xsc();
        static IEnumerator<uint> _xsc() { uint x = 123456789, y = 362436069, z = 521288629, w = (uint)(DateTime.Now.Ticks & 0xffffffff); while (true) { var t = x ^ (x << 11); x = y; y = z; z = w; w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); yield return w; } }
        static bool Chmax<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) < 0) { lhs = rhs; return true; } return false; }
        static bool Chmin<T>(this ref T lhs, T rhs) where T : struct, IComparable<T> { if (lhs.CompareTo(rhs) > 0) { lhs = rhs; return true; } return false; }
        static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);
        static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);
        static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);
        static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);
    }
}
namespace Library {
    class LIB_FastIO
    {
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIO() { str = Console.OpenStandardInput(); }
        readonly Stream str;
        readonly byte[] buf = new byte[2048];
        int len, ptr;
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        byte read()
        {
            if (ptr >= len)
            {
                ptr = 0;
                if ((len = str.Read(buf, 0, 2048)) <= 0)
                {
                    return 0;
                }
            }
            return buf[ptr++];
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        char Char()
        {
            byte b = 0;
            do b = read();
            while (b < 33 || 126 < b);
            return (char)b;
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public string Scan()
        {
            var sb = new StringBuilder();
            for (var b = Char(); b >= 33 && b <= 126; b = (char)read())
                sb.Append(b);
            return sb.ToString();
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public long Long()
        {
            long ret = 0; byte b = 0; var ng = false;
            do b = read();
            while (b != '-' && (b < '0' || '9' < b));
            if (b == '-') { ng = true; b = read(); }
            for (; true; b = read())
            {
                if (b < '0' || '9' < b)
                    return ng ? -ret : ret;
                else ret = (ret << 3) + (ret << 1) + b - '0';
            }
        }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        virtual public double Double() { return double.Parse(Scan(), CultureInfo.InvariantCulture); }
    }
    class LIB_FastIODebug : LIB_FastIO
    {
        Queue<string> param = new Queue<string>();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        string NextString() { if (param.Count == 0) foreach (var item in Console.ReadLine().Split(' ')) param.Enqueue(item); return param.Dequeue(); }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public LIB_FastIODebug() { }
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override string Scan() => NextString();
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override long Long() => long.Parse(NextString());
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public override double Double() => double.Parse(NextString());
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace Mycop
{
    class Program
    {
        static void Main()
        {
            var n = int.Parse(Console.ReadLine());
            var throws = Console.ReadLine().Split().Select(int.Parse).ToArray();

            var onesL = new Stack<int>();
            var onesC = new Stack<int>();
            var twosC = new Stack<int>();
            var threesC = new Stack<int>();
            var maxLine = n;

            var targets = new List<(int, int)>();
            for (var i = n - 1; i >= 0; i--)
            {
                if (throws[i] == 1)
                {
                    onesL.Push(maxLine);
                    onesC.Push(i);
                    targets.Add((i, maxLine));
                    maxLine--;
                }
                else if (throws[i] == 2)
                {
                    if (onesL.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    var one = onesL.Pop();
                    twosC.Push(i);
                    targets.Add((i, one));
                }
                else if (throws[i] == 3)
                {
                    if (threesC.Count > 0)
                    {
                        var three = threesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((three, maxLine));
                    }
                    else if (twosC.Count > 0)
                    {
                        var two = twosC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((two, maxLine));
                    }
                    else if (onesC.Count > 0)
                    {
                        onesL.Pop();
                        var one = onesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((one, maxLine));
                    }
                    else
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    maxLine--;
                    threesC.Push(i);
                }

                if (maxLine <= 0)
                {
                    Console.WriteLine(-1);
                    return;
                }
            }

            Console.WriteLine(targets.Count);
            foreach (var t in targets)
            {
                Console.WriteLine($"{t.Item2} {t.Item1 + 1}");
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Mycop
{
    class Program
    {
        static void Main()
        {
            var n = int.Parse(Console.ReadLine());
            var throws = Console.ReadLine().Split().Select(int.Parse).ToArray();

            var onesL = new Stack<int>();
            var onesC = new Stack<int>();
            var twosC = new Stack<int>();
            var threesC = new Stack<int>();
            var maxLine = n;

            var targets = new List<(int, int)>();
            for (var i = n - 1; i >= 0; i--)
            {
                if (throws[i] == 1)
                {
                    onesL.Push(maxLine);
                    onesC.Push(i);
                    targets.Add((i, maxLine));
                    maxLine--;
                }
                else if (throws[i] == 2)
                {
                    if (onesL.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    var one = onesL.Pop();
                    twosC.Push(i);
                    targets.Add((i, one));
                }
                else if (throws[i] == 3)
                {
                    if (threesC.Count > 0)
                    {
                        var three = threesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((three, maxLine));
                    }
                    else if (twosC.Count > 0)
                    {
                        var two = twosC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((two, maxLine));
                    }
                    else if (onesC.Count > 0)
                    {
                        var one = onesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((one, maxLine));
                    }
                    else
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    maxLine--;
                    threesC.Push(i);
                }

                if (maxLine <= 0)
                {
                    Console.WriteLine(-1);
                    return;
                }
            }

            Console.WriteLine(targets.Count);
            foreach (var t in targets)
            {
                Console.WriteLine($"{t.Item2} {t.Item1 + 1}");
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Mycop
{
    class Program
    {
        static void Main()
        {
            var n = int.Parse(Console.ReadLine());
            var throws = Console.ReadLine().Split().Select(int.Parse).ToArray();

            var onesL = new Stack<int>();
            var onesC = new Stack<int>();
            var twosC = new Stack<int>();
            var threesC = new Stack<int>();
            var maxLine = n;

            var targets = new List<(int, int)>();
            for (var i = n - 1; i >= 0; i--)
            {
                if (throws[i] == 1)
                {
                    onesL.Push(maxLine);
                    onesC.Push(i);
                    targets.Add((i, maxLine));
                    maxLine--;
                }
                else if (throws[i] == 2)
                {
                    if (onesL.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    onesC.Pop();
                    var one = onesL.Pop();
                    twosC.Push(i);
                    targets.Add((i, one));
                }
                else if (throws[i] == 3)
                {
                    if (threesC.Count > 0)
                    {
                        var three = threesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((three, maxLine));
                    }
                    else if (twosC.Count > 0)
                    {
                        var two = twosC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((two, maxLine));
                    }
                    else if (onesC.Count > 0)
                    {
                        onesL.Pop();
                        var one = onesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((one, maxLine));
                    }
                    else
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    maxLine--;
                    threesC.Push(i);
                }

                if (maxLine <= 0)
                {
                    Console.WriteLine(-1);
                    return;
                }
            }

            Console.WriteLine(targets.Count);
            foreach (var t in targets)
            {
                Console.WriteLine($"{t.Item2} {t.Item1 + 1}");
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace Mycop
{
    class Program
    {
        static void Main()
        {
            var n = int.Parse(Console.ReadLine());
            var throws = Console.ReadLine().Split().Select(int.Parse).ToArray();

            var onesL = new Stack<int>();
            var onesC = new Stack<int>();
            var twosC = new Stack<int>();
            var threesC = new Stack<int>();
            var maxLine = n;

            var targets = new List<(int, int)>();
            for (var i = n - 1; i >= 0; i--)
            {
                if (throws[i] == 1)
                {
                    onesL.Push(maxLine);
                    onesC.Push(i);
                    targets.Add((i, maxLine));
                    maxLine--;
                }
                else if (throws[i] == 2)
                {
                    if (onesL.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    onesC.Pop();
                    var one = onesL.Pop();
                    twosC.Push(i);
                    targets.Add((i, one));
                }
                else if (throws[i] == 3)
                {
                    if (threesC.Count > 0)
                    {
                        var three = threesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((three, maxLine));
                    }
                    else if (twosC.Count > 0)
                    {
                        var two = twosC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((two, maxLine));
                    }
                    else if (onesC.Count > 0)
                    {
                        onesL.Pop();
                        var one = onesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((one, maxLine));
                    }
                    else
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    maxLine--;
                    threesC.Push(i);
                }
            }

            Console.WriteLine(targets.Count);
            foreach (var t in targets)
            {
                Console.WriteLine($"{t.Item2} {t.Item1 + 1}");
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;

namespace Mycop
{
    class Program
    {
        static void Main()
        {
            var n = int.Parse(Console.ReadLine());
            var throws = Console.ReadLine().Split().Select(int.Parse).ToArray();

            var onesL = new Stack<int>();
            var onesC = new Stack<int>();
            var twosC = new Stack<int>();
            var threesC = new Stack<int>();
            var maxLine = n;

            var targets = new List<(int, int)>();
            for (var i = n - 1; i >= 0; i--)
            {
                if (throws[i] == 1)
                {
                    onesL.Push(maxLine);
                    onesC.Push(i);
                    targets.Add((i, maxLine));
                    maxLine--;
                }
                else if (throws[i] == 2)
                {
                    if (onesL.Count == 0)
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    onesC.Pop();
                    var one = onesL.Pop();
                    twosC.Push(i);
                    targets.Add((i, one));
                }
                else if (throws[i] == 3)
                {
                    if (threesC.Count > 0)
                    {
                        var three = threesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((three, maxLine));
                    }
                    else if (twosC.Count > 0)
                    {
                        var two = twosC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((two, maxLine));
                    }
                    else if (onesC.Count > 0)
                    {
                        onesL.Pop();
                        var one = onesC.Pop();
                        targets.Add((i, maxLine));
                        targets.Add((one, maxLine));
                    }
                    else
                    {
                        Console.WriteLine(-1);
                        return;
                    }

                    maxLine--;
                    threesC.Push(i);
                }

                if (maxLine <= 0)
                {
                    Console.WriteLine(-1);
                    return;
                }
            }

            Console.WriteLine(targets.Count);
            foreach (var t in targets)
            {
                Console.WriteLine($"{t.Item1 + 1} {t.Item2}");
            }
        }
    }
}


using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using CodeforcesRaifRound1.Questions;

namespace CodeforcesRaifRound1.Questions
{
    public class QuestionD : AtCoderQuestionBase
    {
        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
        public override void Solve(IOManager io)
        {
            var n = io.ReadInt();

            var results = new Queue<Coordinate>();
            var doubleQueue = new Queue<Coordinate>();
            var tripleQueue = new Queue<Coordinate>();

            var row = 0;
            for (int column = 0; column < n; column++)
            {
                var ai = io.ReadInt();

                if (ai == 1)
                {
                    if (doubleQueue.Count > 0)
                    {
                        var last = doubleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                    }
                    else if (tripleQueue.Count > 0)
                    {
                        var last = tripleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                    else
                    {
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                }
                else if (ai >= 2)
                {
                    if (tripleQueue.Count > 0)
                    {
                        var last = tripleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                    }

                    if (ai == 2)
                    {
                        doubleQueue.Enqueue(new Coordinate(row, column));
                    }
                    else
                    {
                        tripleQueue.Enqueue(new Coordinate(row, column));
                    }

                    row++;
                }
            }

            if (row >= n || doubleQueue.Count > 0 || tripleQueue.Count > 0)
            {
                io.WriteLine(-1);
                return;
            }
            else
            {
                io.WriteLine(results.Count);

                while (results.Count > 0)
                {
                    io.WriteLine(results.Dequeue());
                }
            }
        }

        [StructLayout(LayoutKind.Auto)]
        readonly struct Coordinate
        {
            public readonly int Row;
            public readonly int Column;

            public Coordinate(int row, int column)
            {
                Row = row;
                Column = column;
            }

            public void Deconstruct(out int row, out int column) => (row, column) = (Row, Column);
            public override string ToString() => $"{Row + 1} {Column + 1}";
        }
    }
}

namespace CodeforcesRaifRound1
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionD();
            using var io = new IOManager(Console.OpenStandardInput(), Console.OpenStandardOutput());
            question.Solve(io);
        }
    }
}

#region Base Class

namespace CodeforcesRaifRound1.Questions
{
    public interface IAtCoderQuestion
    {
        string Solve(string input);
        void Solve(IOManager io);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public string Solve(string input)
        {
            var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(input));
            var outputStream = new MemoryStream();
            using var manager = new IOManager(inputStream, outputStream);

            Solve(manager);
            manager.Flush();

            outputStream.Seek(0, SeekOrigin.Begin);
            var reader = new StreamReader(outputStream);
            return reader.ReadToEnd();
        }

        public abstract void Solve(IOManager io);
    }
}

#endregion

#region Utils

namespace CodeforcesRaifRound1
{
    public class IOManager : IDisposable
    {
        private readonly BinaryReader _reader;
        private readonly StreamWriter _writer;
        private bool _disposedValue;
        private byte[] _buffer = new byte[1024];
        private int _length;
        private int _cursor;
        private bool _eof;

        const char ValidFirstChar = '!';
        const char ValidLastChar = '~';

        public IOManager(Stream input, Stream output)
        {
            _reader = new BinaryReader(input);
            _writer = new StreamWriter(output) { AutoFlush = false };
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private char ReadAscii()
        {
            if (_cursor == _length)
            {
                _cursor = 0;
                _length = _reader.Read(_buffer);

                if (_length == 0)
                {
                    if (!_eof)
                    {
                        _eof = true;
                        return char.MinValue;
                    }
                    else
                    {
                        ThrowEndOfStreamException();
                    }
                }
            }

            return (char)_buffer[_cursor++];
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public char ReadChar()
        {
            char c;
            while (!IsValidChar(c = ReadAscii())) { }
            return c;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public string ReadString()
        {
            var builder = new StringBuilder();
            char c;
            while (!IsValidChar(c = ReadAscii())) { }

            do
            {
                builder.Append(c);
            } while (IsValidChar(c = ReadAscii()));

            return builder.ToString();
        }

        public int ReadInt() => (int)ReadLong();

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public long ReadLong()
        {
            long result = 0;
            bool isPositive = true;
            char c;

            while (!IsNumericChar(c = ReadAscii())) { }

            if (c == '-')
            {
                isPositive = false;
                c = ReadAscii();
            }

            do
            {
                result *= 10;
                result += c - '0';
            } while (IsNumericChar(c = ReadAscii()));

            return isPositive ? result : -result;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private Span<char> ReadChunk(Span<char> span)
        {
            var i = 0;
            char c;
            while (!IsValidChar(c = ReadAscii())) { }

            do
            {
                span[i++] = c;
            } while (IsValidChar(c = ReadAscii()));

            return span.Slice(0, i);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double ReadDouble() => double.Parse(ReadChunk(stackalloc char[32]));

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public decimal ReadDecimal() => decimal.Parse(ReadChunk(stackalloc char[32]));

        public int[] ReadIntArray(int n)
        {
            var a = new int[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadInt();
            }
            return a;
        }

        public long[] ReadLongArray(int n)
        {
            var a = new long[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadLong();
            }
            return a;
        }

        public double[] ReadDoubleArray(int n)
        {
            var a = new double[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadDouble();
            }
            return a;
        }

        public decimal[] ReadDecimalArray(int n)
        {
            var a = new decimal[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadDecimal();
            }
            return a;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void WriteLine<T>(T value) => _writer.WriteLine(value.ToString());

        public void WriteLine<T>(IEnumerable<T> values, char separator)
        {
            var e = values.GetEnumerator();
            if (e.MoveNext())
            {
                _writer.Write(e.Current.ToString());

                while (e.MoveNext())
                {
                    _writer.Write(separator);
                    _writer.Write(e.Current.ToString());
                }
            }

            _writer.WriteLine();
        }

        public void WriteLine<T>(Span<T> values, char separator) => WriteLine((ReadOnlySpan<T>)values, separator);

        public void WriteLine<T>(ReadOnlySpan<T> values, char separator)
        {
            for (int i = 0; i < values.Length - 1; i++)
            {
                _writer.Write(values[i]);
                _writer.Write(separator);
            }

            if (values.Length > 0)
            {
                _writer.Write(values[^1]);
            }

            _writer.WriteLine();
        }

        public void Flush() => _writer.Flush();

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool IsValidChar(char c) => ValidFirstChar <= c && c <= ValidLastChar;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool IsNumericChar(char c) => ('0' <= c && c <= '9') || c == '-';

        private void ThrowEndOfStreamException() => throw new EndOfStreamException();

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposedValue)
            {
                if (disposing)
                {
                    _reader.Dispose();
                    _writer.Flush();
                    _writer.Dispose();
                }

                _disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }

    public static class UtilExtensions
    {
        public static bool ChangeMax<T>(ref this T value, T other) where T : struct, IComparable<T>
        {
            if (value.CompareTo(other) < 0)
            {
                value = other;
                return true;
            }
            return false;
        }

        public static bool ChangeMin<T>(ref this T value, T other) where T : struct, IComparable<T>
        {
            if (value.CompareTo(other) > 0)
            {
                value = other;
                return true;
            }
            return false;
        }

        public static void SwapIfLargerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>
        {
            if (a.CompareTo(b) > 0)
            {
                (a, b) = (b, a);
            }
        }

        public static void SwapIfSmallerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>
        {
            if (a.CompareTo(b) < 0)
            {
                (a, b) = (b, a);
            }
        }

        public static void Sort<T>(this T[] array) where T : IComparable<T> => Array.Sort(array);
        public static void Sort<T>(this T[] array, Comparison<T> comparison) => Array.Sort(array, comparison);
    }

    public static class CollectionExtensions
    {
        private class ArrayWrapper<T>
        {
            public T[] Array;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Span<T> AsSpan<T>(this List<T> list)
        {
            return Unsafe.As<ArrayWrapper<T>>(list).Array.AsSpan(0, list.Count);
        }

        public static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);
        public static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);
        public static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);
        public static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);
    }
}

#endregion


using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using CodeforcesRaifRound1.Questions;

namespace CodeforcesRaifRound1.Questions
{
    public class QuestionD : AtCoderQuestionBase
    {
        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
        public override void Solve(IOManager io)
        {
            var n = io.ReadInt();

            var results = new Queue<Coordinate>();
            var doubleQueue = new Queue<Coordinate>();
            var tripleQueue = new Queue<Coordinate>();

            var row = 0;
            for (int column = 0; column < n; column++)
            {
                var ai = io.ReadInt();

                if (ai == 1)
                {
                    if (doubleQueue.Count > 0)
                    {
                        var last = doubleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                    }
                    else if (tripleQueue.Count > 0)
                    {
                        var last = tripleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                    else
                    {
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                }
                else if (ai >= 2)
                {
                    if (tripleQueue.Count > 0)
                    {
                        var last = tripleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                    }

                    if (ai == 2)
                    {
                        doubleQueue.Enqueue(new Coordinate(row, column));
                    }
                    else
                    {
                        tripleQueue.Enqueue(new Coordinate(row, column));
                    }

                    row++;
                }
            }

            if (row > n || doubleQueue.Count > 0 || tripleQueue.Count > 0)
            {
                io.WriteLine(-1);
                return;
            }
            else
            {
                io.WriteLine(results.Count);

                while (results.Count > 0)
                {
                    io.WriteLine(results.Dequeue());
                }
            }
        }

        [StructLayout(LayoutKind.Auto)]
        readonly struct Coordinate
        {
            public readonly int Row;
            public readonly int Column;

            public Coordinate(int row, int column)
            {
                Row = row;
                Column = column;
            }

            public void Deconstruct(out int row, out int column) => (row, column) = (Row, Column);
            public override string ToString() => $"{Row + 1} {Column + 1}";
        }
    }
}

namespace CodeforcesRaifRound1
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionD();
            using var io = new IOManager(Console.OpenStandardInput(), Console.OpenStandardOutput());
            question.Solve(io);
        }
    }
}

#region Base Class

namespace CodeforcesRaifRound1.Questions
{
    public interface IAtCoderQuestion
    {
        string Solve(string input);
        void Solve(IOManager io);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public string Solve(string input)
        {
            var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(input));
            var outputStream = new MemoryStream();
            using var manager = new IOManager(inputStream, outputStream);

            Solve(manager);
            manager.Flush();

            outputStream.Seek(0, SeekOrigin.Begin);
            var reader = new StreamReader(outputStream);
            return reader.ReadToEnd();
        }

        public abstract void Solve(IOManager io);
    }
}

#endregion

#region Utils

namespace CodeforcesRaifRound1
{
    public class IOManager : IDisposable
    {
        private readonly BinaryReader _reader;
        private readonly StreamWriter _writer;
        private bool _disposedValue;
        private byte[] _buffer = new byte[1024];
        private int _length;
        private int _cursor;
        private bool _eof;

        const char ValidFirstChar = '!';
        const char ValidLastChar = '~';

        public IOManager(Stream input, Stream output)
        {
            _reader = new BinaryReader(input);
            _writer = new StreamWriter(output) { AutoFlush = false };
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private char ReadAscii()
        {
            if (_cursor == _length)
            {
                _cursor = 0;
                _length = _reader.Read(_buffer);

                if (_length == 0)
                {
                    if (!_eof)
                    {
                        _eof = true;
                        return char.MinValue;
                    }
                    else
                    {
                        ThrowEndOfStreamException();
                    }
                }
            }

            return (char)_buffer[_cursor++];
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public char ReadChar()
        {
            char c;
            while (!IsValidChar(c = ReadAscii())) { }
            return c;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public string ReadString()
        {
            var builder = new StringBuilder();
            char c;
            while (!IsValidChar(c = ReadAscii())) { }

            do
            {
                builder.Append(c);
            } while (IsValidChar(c = ReadAscii()));

            return builder.ToString();
        }

        public int ReadInt() => (int)ReadLong();

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public long ReadLong()
        {
            long result = 0;
            bool isPositive = true;
            char c;

            while (!IsNumericChar(c = ReadAscii())) { }

            if (c == '-')
            {
                isPositive = false;
                c = ReadAscii();
            }

            do
            {
                result *= 10;
                result += c - '0';
            } while (IsNumericChar(c = ReadAscii()));

            return isPositive ? result : -result;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private Span<char> ReadChunk(Span<char> span)
        {
            var i = 0;
            char c;
            while (!IsValidChar(c = ReadAscii())) { }

            do
            {
                span[i++] = c;
            } while (IsValidChar(c = ReadAscii()));

            return span.Slice(0, i);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double ReadDouble() => double.Parse(ReadChunk(stackalloc char[32]));

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public decimal ReadDecimal() => decimal.Parse(ReadChunk(stackalloc char[32]));

        public int[] ReadIntArray(int n)
        {
            var a = new int[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadInt();
            }
            return a;
        }

        public long[] ReadLongArray(int n)
        {
            var a = new long[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadLong();
            }
            return a;
        }

        public double[] ReadDoubleArray(int n)
        {
            var a = new double[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadDouble();
            }
            return a;
        }

        public decimal[] ReadDecimalArray(int n)
        {
            var a = new decimal[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadDecimal();
            }
            return a;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void WriteLine<T>(T value) => _writer.WriteLine(value.ToString());

        public void WriteLine<T>(IEnumerable<T> values, char separator)
        {
            var e = values.GetEnumerator();
            if (e.MoveNext())
            {
                _writer.Write(e.Current.ToString());

                while (e.MoveNext())
                {
                    _writer.Write(separator);
                    _writer.Write(e.Current.ToString());
                }
            }

            _writer.WriteLine();
        }

        public void WriteLine<T>(Span<T> values, char separator) => WriteLine((ReadOnlySpan<T>)values, separator);

        public void WriteLine<T>(ReadOnlySpan<T> values, char separator)
        {
            for (int i = 0; i < values.Length - 1; i++)
            {
                _writer.Write(values[i]);
                _writer.Write(separator);
            }

            if (values.Length > 0)
            {
                _writer.Write(values[^1]);
            }

            _writer.WriteLine();
        }

        public void Flush() => _writer.Flush();

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool IsValidChar(char c) => ValidFirstChar <= c && c <= ValidLastChar;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool IsNumericChar(char c) => ('0' <= c && c <= '9') || c == '-';

        private void ThrowEndOfStreamException() => throw new EndOfStreamException();

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposedValue)
            {
                if (disposing)
                {
                    _reader.Dispose();
                    _writer.Flush();
                    _writer.Dispose();
                }

                _disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }

    public static class UtilExtensions
    {
        public static bool ChangeMax<T>(ref this T value, T other) where T : struct, IComparable<T>
        {
            if (value.CompareTo(other) < 0)
            {
                value = other;
                return true;
            }
            return false;
        }

        public static bool ChangeMin<T>(ref this T value, T other) where T : struct, IComparable<T>
        {
            if (value.CompareTo(other) > 0)
            {
                value = other;
                return true;
            }
            return false;
        }

        public static void SwapIfLargerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>
        {
            if (a.CompareTo(b) > 0)
            {
                (a, b) = (b, a);
            }
        }

        public static void SwapIfSmallerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>
        {
            if (a.CompareTo(b) < 0)
            {
                (a, b) = (b, a);
            }
        }

        public static void Sort<T>(this T[] array) where T : IComparable<T> => Array.Sort(array);
        public static void Sort<T>(this T[] array, Comparison<T> comparison) => Array.Sort(array, comparison);
    }

    public static class CollectionExtensions
    {
        private class ArrayWrapper<T>
        {
            public T[] Array;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Span<T> AsSpan<T>(this List<T> list)
        {
            return Unsafe.As<ArrayWrapper<T>>(list).Array.AsSpan(0, list.Count);
        }

        public static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);
        public static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);
        public static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);
        public static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);
    }
}

#endregion


using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using CodeforcesRaifRound1.Questions;

namespace CodeforcesRaifRound1.Questions
{
    public class QuestionD : AtCoderQuestionBase
    {
        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
        public override void Solve(IOManager io)
        {
            var n = io.ReadInt();

            var results = new Queue<Coordinate>();
            var doubleQueue = new Queue<Coordinate>();
            var tripleQueue = new Queue<Coordinate>();

            var row = 0;
            for (int column = 0; column < n; column++)
            {
                var ai = io.ReadInt();

                if (ai == 1)
                {
                    if (doubleQueue.Count > 0)
                    {
                        var last = doubleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                    }
                    else if (tripleQueue.Count > 0)
                    {
                        var last = tripleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                    else
                    {
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                }
                else if (ai >= 2)
                {
                    if (tripleQueue.Count > 0)
                    {
                        var last = tripleQueue.Dequeue();
                        results.Enqueue(last);
                        results.Enqueue(new Coordinate(last.Row, column));
                        results.Enqueue(new Coordinate(row, column));
                        row++;
                    }
                    if (ai == 2)
                    {
                        doubleQueue.Enqueue(new Coordinate(row, column));
                    }
                    else
                    {
                        tripleQueue.Enqueue(new Coordinate(row, column));
                    }

                    row++;
                }
            }

            if (row >= n || doubleQueue.Count > 0 || tripleQueue.Count > 0)
            {
                io.WriteLine(-1);
                return;
            }
            else
            {
                io.WriteLine(results.Count);

                while (results.Count > 0)
                {
                    io.WriteLine(results.Dequeue());
                }
            }
        }

        [StructLayout(LayoutKind.Auto)]
        readonly struct Coordinate
        {
            public readonly int Row;
            public readonly int Column;

            public Coordinate(int row, int column)
            {
                Row = row;
                Column = column;
            }

            public void Deconstruct(out int row, out int column) => (row, column) = (Row, Column);
            public override string ToString() => $"{Row + 1} {Column + 1}";
        }
    }
}

namespace CodeforcesRaifRound1
{
    class Program
    {
        static void Main(string[] args)
        {
            IAtCoderQuestion question = new QuestionD();
            using var io = new IOManager(Console.OpenStandardInput(), Console.OpenStandardOutput());
            question.Solve(io);
        }
    }
}

#region Base Class

namespace CodeforcesRaifRound1.Questions
{
    public interface IAtCoderQuestion
    {
        string Solve(string input);
        void Solve(IOManager io);
    }

    public abstract class AtCoderQuestionBase : IAtCoderQuestion
    {
        public string Solve(string input)
        {
            var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(input));
            var outputStream = new MemoryStream();
            using var manager = new IOManager(inputStream, outputStream);

            Solve(manager);
            manager.Flush();

            outputStream.Seek(0, SeekOrigin.Begin);
            var reader = new StreamReader(outputStream);
            return reader.ReadToEnd();
        }

        public abstract void Solve(IOManager io);
    }
}

#endregion

#region Utils

namespace CodeforcesRaifRound1
{
    public class IOManager : IDisposable
    {
        private readonly BinaryReader _reader;
        private readonly StreamWriter _writer;
        private bool _disposedValue;
        private byte[] _buffer = new byte[1024];
        private int _length;
        private int _cursor;
        private bool _eof;

        const char ValidFirstChar = '!';
        const char ValidLastChar = '~';

        public IOManager(Stream input, Stream output)
        {
            _reader = new BinaryReader(input);
            _writer = new StreamWriter(output) { AutoFlush = false };
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private char ReadAscii()
        {
            if (_cursor == _length)
            {
                _cursor = 0;
                _length = _reader.Read(_buffer);

                if (_length == 0)
                {
                    if (!_eof)
                    {
                        _eof = true;
                        return char.MinValue;
                    }
                    else
                    {
                        ThrowEndOfStreamException();
                    }
                }
            }

            return (char)_buffer[_cursor++];
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public char ReadChar()
        {
            char c;
            while (!IsValidChar(c = ReadAscii())) { }
            return c;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public string ReadString()
        {
            var builder = new StringBuilder();
            char c;
            while (!IsValidChar(c = ReadAscii())) { }

            do
            {
                builder.Append(c);
            } while (IsValidChar(c = ReadAscii()));

            return builder.ToString();
        }

        public int ReadInt() => (int)ReadLong();

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public long ReadLong()
        {
            long result = 0;
            bool isPositive = true;
            char c;

            while (!IsNumericChar(c = ReadAscii())) { }

            if (c == '-')
            {
                isPositive = false;
                c = ReadAscii();
            }

            do
            {
                result *= 10;
                result += c - '0';
            } while (IsNumericChar(c = ReadAscii()));

            return isPositive ? result : -result;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private Span<char> ReadChunk(Span<char> span)
        {
            var i = 0;
            char c;
            while (!IsValidChar(c = ReadAscii())) { }

            do
            {
                span[i++] = c;
            } while (IsValidChar(c = ReadAscii()));

            return span.Slice(0, i);
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public double ReadDouble() => double.Parse(ReadChunk(stackalloc char[32]));

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public decimal ReadDecimal() => decimal.Parse(ReadChunk(stackalloc char[32]));

        public int[] ReadIntArray(int n)
        {
            var a = new int[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadInt();
            }
            return a;
        }

        public long[] ReadLongArray(int n)
        {
            var a = new long[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadLong();
            }
            return a;
        }

        public double[] ReadDoubleArray(int n)
        {
            var a = new double[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadDouble();
            }
            return a;
        }

        public decimal[] ReadDecimalArray(int n)
        {
            var a = new decimal[n];
            for (int i = 0; i < a.Length; i++)
            {
                a[i] = ReadDecimal();
            }
            return a;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void WriteLine<T>(T value) => _writer.WriteLine(value.ToString());

        public void WriteLine<T>(IEnumerable<T> values, char separator)
        {
            var e = values.GetEnumerator();
            if (e.MoveNext())
            {
                _writer.Write(e.Current.ToString());

                while (e.MoveNext())
                {
                    _writer.Write(separator);
                    _writer.Write(e.Current.ToString());
                }
            }

            _writer.WriteLine();
        }

        public void WriteLine<T>(Span<T> values, char separator) => WriteLine((ReadOnlySpan<T>)values, separator);

        public void WriteLine<T>(ReadOnlySpan<T> values, char separator)
        {
            for (int i = 0; i < values.Length - 1; i++)
            {
                _writer.Write(values[i]);
                _writer.Write(separator);
            }

            if (values.Length > 0)
            {
                _writer.Write(values[^1]);
            }

            _writer.WriteLine();
        }

        public void Flush() => _writer.Flush();

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool IsValidChar(char c) => ValidFirstChar <= c && c <= ValidLastChar;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private static bool IsNumericChar(char c) => ('0' <= c && c <= '9') || c == '-';

        private void ThrowEndOfStreamException() => throw new EndOfStreamException();

        protected virtual void Dispose(bool disposing)
        {
            if (!_disposedValue)
            {
                if (disposing)
                {
                    _reader.Dispose();
                    _writer.Flush();
                    _writer.Dispose();
                }

                _disposedValue = true;
            }
        }

        public void Dispose()
        {
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }

    public static class UtilExtensions
    {
        public static bool ChangeMax<T>(ref this T value, T other) where T : struct, IComparable<T>
        {
            if (value.CompareTo(other) < 0)
            {
                value = other;
                return true;
            }
            return false;
        }

        public static bool ChangeMin<T>(ref this T value, T other) where T : struct, IComparable<T>
        {
            if (value.CompareTo(other) > 0)
            {
                value = other;
                return true;
            }
            return false;
        }

        public static void SwapIfLargerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>
        {
            if (a.CompareTo(b) > 0)
            {
                (a, b) = (b, a);
            }
        }

        public static void SwapIfSmallerThan<T>(ref this T a, ref T b) where T : struct, IComparable<T>
        {
            if (a.CompareTo(b) < 0)
            {
                (a, b) = (b, a);
            }
        }

        public static void Sort<T>(this T[] array) where T : IComparable<T> => Array.Sort(array);
        public static void Sort<T>(this T[] array, Comparison<T> comparison) => Array.Sort(array, comparison);
    }

    public static class CollectionExtensions
    {
        private class ArrayWrapper<T>
        {
            public T[] Array;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public static Span<T> AsSpan<T>(this List<T> list)
        {
            return Unsafe.As<ArrayWrapper<T>>(list).Array.AsSpan(0, list.Count);
        }

        public static void Fill<T>(this T[] array, T value) => array.AsSpan().Fill(value);
        public static void Fill<T>(this T[,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0], array.Length).Fill(value);
        public static void Fill<T>(this T[,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0], array.Length).Fill(value);
        public static void Fill<T>(this T[,,,] array, T value) => MemoryMarshal.CreateSpan(ref array[0, 0, 0, 0], array.Length).Fill(value);
    }
}

#endregion


using System;
using System.Collections.Generic;
using System.Text;

namespace Codeforces_1428
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine()), i, y = 0;
            List<int>[] X = new List<int>[4];  for (i = 3; 0 <= i; --i) X[i] = new List<int>();
            foreach (string s in Console.ReadLine().Split(' ')) X[int.Parse(s)].Add(++i);
            List<KeyValuePair<int, int>> t = new List<KeyValuePair<int, int>>();
            int c1 = X[1].Count, c2 = X[2].Count, c3 = X[3].Count, x1, x2, x3;
            while (0 < c1 || 0 < c2 || 0 < c3) {
                x1 = 0 < c1 ? X[1][0] : 123456;
                x2 = 0 < c2 ? X[2][0] : 123456;
                x3 = 0 < c3 ? X[3][0] : 123456;
                if (x1 < x2 && x1 < x3) {
                    if (n <= y) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                } else
                if (x3 < x1 && x3 < x2) {
                    if (n <= y+1 || 100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x3));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[3].RemoveAt(0);  --c3;
                } else {  if (100000 < x1) { Console.WriteLine(-1); return; }
                    if (x3 < x1) {
                        if (n <= y+1) { Console.WriteLine(-1); return; }
                        t.Add(new KeyValuePair<int, int>(y,   x2));
                        t.Add(new KeyValuePair<int, int>(y,   x3));
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                        X[2].RemoveAt(0);  --c2;
                        X[3].RemoveAt(0);  --c3;
                    } else {
                        if (n <= y+1) { Console.WriteLine(-1); return; }
                        t.Add(new KeyValuePair<int, int>(y,   x2));
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                        X[2].RemoveAt(0);  --c2;
                    }
                }
                X[1].RemoveAt(0);  --c1;
            }
            Console.WriteLine(t.Count);
            foreach (KeyValuePair<int, int> p in t) {
                Console.WriteLine("{0} {1}", p.Key + 1, p.Value + 1);
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace Codeforces_1428
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine()), i, y = 0;
            List<int>[] X = new List<int>[4];  for (i = 3; 0 <= i; --i) X[i] = new List<int>();
            foreach (string s in Console.ReadLine().Split(' ')) X[int.Parse(s)].Add(++i);
            List<KeyValuePair<int, int>> t = new List<KeyValuePair<int, int>>();
            int c1 = X[1].Count, c2 = X[2].Count, c3 = X[3].Count, x1, x2, x3;
            while (0 < c1 || 0 < c2 || 0 < c3) {
                x1 = 0 < c1 ? X[1][0] : 123456;
                x2 = 0 < c2 ? X[2][0] : 123456;
                x3 = 0 < c3 ? X[3][0] : 123456;
                if (x1 < x2 && x1 < x3) {
                    if (n <= y) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                } else
                if (x3 < x1 && x3 < x2) {
                    if (n <= y+1 || 100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x3));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[3].RemoveAt(0);  --c3;
                } else {  if (100000 < x1) { Console.WriteLine(-1); return; }
                    if (x3 < x1) {
                        if (n <= y+1) { Console.WriteLine(-1); return; }
                        t.Add(new KeyValuePair<int, int>(y,   x2));
                        t.Add(new KeyValuePair<int, int>(y,   x3));
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                        X[2].RemoveAt(0);  --c2;
                        X[3].RemoveAt(0);  --c3;
                    } else {
                        if (n <= y) { Console.WriteLine(-1); return; }
                        t.Add(new KeyValuePair<int, int>(y,   x2));
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                        X[2].RemoveAt(0);  --c2;
                    }
                }
                X[1].RemoveAt(0);  --c1;
            }
            Console.WriteLine(t.Count);
            foreach (KeyValuePair<int, int> p in t) {
                Console.WriteLine("{0} {1}", p.Key + 1, p.Value + 1);
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace Codeforces_1428
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine()), i = -1, y = 0, x;
            int[] a = new int[n];
            List<int> l1 = new List<int>();
            foreach (string s in Console.ReadLine().Split(' ')) if (1 == (a[++i] = int.Parse(s))) l1.Add(i);
            List<KeyValuePair<int, int>> t = new List<KeyValuePair<int, int>>();
            for (i = 0; i < n; ++i) {
              if (2 == a[i]) {
                  if (l1.Count < 1 || n <= y || (x = l1[0]) < i) { Console.WriteLine(-1); return; }
                  t.Add(new KeyValuePair<int, int>(y, x));  l1.RemoveAt(0);
                  t.Add(new KeyValuePair<int, int>(y++, i));
              } else
              if (3 == a[i]) {
                  if (l1.Count < 1 || n <= y+1 || (x = l1[0]) < i) { Console.WriteLine(-1); return; }
                  t.Add(new KeyValuePair<int, int>(y, x));  l1.RemoveAt(0);
                  t.Add(new KeyValuePair<int, int>(y++, i));
                  t.Add(new KeyValuePair<int, int>(y++, x));
              }
            }
            if (0 < l1.Count) { Console.WriteLine(-1); return; }
            Console.WriteLine(t.Count);
            foreach (KeyValuePair<int, int> p in t) {
                Console.WriteLine("{0} {1}", p.Key + 1, p.Value + 1);
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace Codeforces_1428
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine()), i, y = 0;
            List<int>[] X = new List<int>[4];  for (i = 3; 0 <= i; --i) X[i] = new List<int>();
            foreach (string s in Console.ReadLine().Split(' ')) X[int.Parse(s)].Add(++i);
            List<KeyValuePair<int, int>> t = new List<KeyValuePair<int, int>>();
            int c1 = X[1].Count, c2 = X[2].Count, c3 = X[3].Count, x1, x2, x3;
            while (0 < c1 || 0 < c2 || 0 < c3) {
                if (n <= y) { Console.WriteLine(-1); return; }
                x1 = 0 < c1 ? X[1][0] : 123456;
                x2 = 0 < c2 ? X[2][0] : 123456;
                x3 = 0 < c3 ? X[3][0] : 123456;
                if (x1 < x2 && x1 < x3) {
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[1].RemoveAt(0);  --c1;
                } else
                if (x2 < x1 && x2 < x3) {
                    if (100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x2));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[2].RemoveAt(0);  --c2;
                    X[1].RemoveAt(0);  --c1;
                } else {
                    t.Add(new KeyValuePair<int, int>(y,   x3));
                    X[3].RemoveAt(0);  --c3;
                    x3 = 0 < c3 ? X[3][0] : 123456;
                    if (x1 < x2 && x1 < x3) {
                        t.Add(new KeyValuePair<int, int>(y++, x1));
                    } else
                    if (x2 < x1 && x2 < x3) {
                        t.Add(new KeyValuePair<int, int>(y++, x2));
                    } else
                    if (x3 < x1 && x3 < x2) {  // Consider ai={3,3,3,…,3,1}
                        t.Add(new KeyValuePair<int, int>(y++, x3));
                    } else { Console.WriteLine(-1); return; }
                }
            }
            Console.WriteLine(t.Count);
            foreach (KeyValuePair<int, int> p in t) {
                Console.WriteLine("{0} {1}", p.Key + 1, p.Value + 1);
            }
        }
    }
} // Рейтинг: 1659 (макс. эксперт, 1679)


using System;
using System.Collections.Generic;
using System.Text;

namespace Codeforces_1428
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine()), i, y = 0;
            List<int>[] X = new List<int>[4];  for (i = 3; 0 <= i; --i) X[i] = new List<int>();
            foreach (string s in Console.ReadLine().Split(' ')) X[int.Parse(s)].Add(++i);
            List<KeyValuePair<int, int>> t = new List<KeyValuePair<int, int>>();
            int c1 = X[1].Count, c2 = X[2].Count, c3 = X[3].Count, x1, x2, x3;
            while (0 < c1 || 0 < c2 || 0 < c3) {
                x1 = 0 < c1 ? X[1][0] : 123456;
                x2 = 0 < c2 ? X[2][0] : 123456;
                x3 = 0 < c3 ? X[3][0] : 123456;
                if (x1 < x2 && x1 < x3) {
                    if (n <= y) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                } else
                if (x3 < x1 && x3 < x2) {
                    if (n <= y+1 || 100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x3));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[3].RemoveAt(0);  --c3;
                } else {
                    if (n <= y+1 || 100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x2));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[2].RemoveAt(0);  --c2;
                }
                X[1].RemoveAt(0);  --c1;
            }
            Console.WriteLine(t.Count);
            foreach (KeyValuePair<int, int> p in t) {
                Console.WriteLine("{0} {1}", p.Key + 1, p.Value + 1);
            }
        }
    }
}


using System;
using System.Collections.Generic;
using System.Text;

namespace Codeforces_1428
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = int.Parse(Console.ReadLine()), i, y = 0;
            List<int>[] X = new List<int>[4];  for (i = 3; 0 <= i; --i) X[i] = new List<int>();
            foreach (string s in Console.ReadLine().Split(' ')) X[int.Parse(s)].Add(++i);
            List<KeyValuePair<int, int>> t = new List<KeyValuePair<int, int>>();
            int c1 = X[1].Count, c2 = X[2].Count, c3 = X[3].Count, x1, x2, x3;
            while (0 < c1 || 0 < c2 || 0 < c3) {
                x1 = 0 < c1 ? X[1][0] : 123456;
                x2 = 0 < c2 ? X[2][0] : 123456;
                x3 = 0 < c3 ? X[3][0] : 123456;
                if (x1 < x2 && x1 < x3) {
                    if (n <= y) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                } else
                if (x3 < x1 && x3 < x2) {
                    if (n <= y+1 || 100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x3));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[3].RemoveAt(0);  --c3;
                } else {
                    if (n <= y || 100000 < x1) { Console.WriteLine(-1); return; }
                    t.Add(new KeyValuePair<int, int>(y,   x2));
                    t.Add(new KeyValuePair<int, int>(y++, x1));
                    X[2].RemoveAt(0);  --c2;
                }
                X[1].RemoveAt(0);  --c1;
            }
            Console.WriteLine(t.Count);
            foreach (KeyValuePair<int, int> p in t) {
                Console.WriteLine("{0} {1}", p.Key + 1, p.Value + 1);
            }
        }
    }
}


#![allow(dead_code, non_snake_case)]

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        n: usize,
        g: [usize; n]
    }
    let mut obj = Vec::new();
    let mut h = n;
    let mut dub = n;
    let mut las = n;
    let mut f = vec![false; n+1];
    for i in (1..=n).rev() {
        if g[i - 1] == 1 {
            obj.push((h, i));
            h -= 1;
            las = i;
        } else if g[i - 1] == 2 {
            while dub > 0 && f[dub] {
                dub -= 1;
            }
            if dub == 0 || dub <= h {
                println!("{}", -1);
                return;
            } else {
                obj.push((dub, i));
                f[dub] = true;
                las = i;
            }
        } else if g[i - 1] == 3 {
            if las == n {
                println!("{}", -1);
                return;
            }
            obj.push((h, i));
            obj.push((h, las));
            f[h] = true;
            las = i;
            h -= 1;
        }
    }
    println!("{}", obj.len());
    for &(a, b) in &obj {
        println!("{} {}", a, b);
    }
}


#![allow(dead_code, non_snake_case)]

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        n: usize,
        g: [usize; n]
    }
    let mut obj = Vec::new();
    let mut h = n;
    let mut dub = n;
    let mut las = n + 1;
    let mut f = vec![false; n+1];
    for i in (1..=n).rev() {
        if g[i - 1] == 1 {
            obj.push((h, i));
            h -= 1;
            las = i;
        } else if g[i - 1] == 2 {
            while dub > 0 && f[dub] {
                dub -= 1;
            }
            if dub == 0 || dub <= h {
                println!("{}", -1);
                return;
            } else {
                obj.push((dub, i));
                f[dub] = true;
                las = i;
            }
        } else if g[i - 1] == 3 {
            if las > n {
                println!("{}", -1);
                return;
            }
            obj.push((h, i));
            obj.push((h, las));
            f[h] = true;
            las = i;
            h -= 1;
        }
    }
    println!("{}", obj.len());
    for &(a, b) in &obj {
        println!("{} {}", a, b);
    }
}


#![allow(dead_code, non_snake_case)]

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        n: usize,
        g: [usize; n]
    }
    let mut obj = Vec::new();
    let mut h = n;
    let mut dub = n;
    let mut las = n + 1;
    let mut f = vec![false; n+1];
    for i in (1..=n).rev() {
        if g[i - 1] == 1 {
            obj.push((h, i));
            h -= 1;
            las = i;
        } else if g[i - 1] == 2 {
            while dub > 0 && f[dub] {
                dub -= 1;
            }
            if dub == 0 || dub <= h {
                println!("{}", -1);
                return;
            } else {
                obj.push((dub, i));
                f[dub] = true;
                las = i;
            }
        } else if g[i - 1] == 3 {
            if las > n {
                println!("{}", -1);
                return;
            }
            obj.push((h, i));
            obj.push((h, las));
            f[h] = true;
            f[h+1] = true;
            las = i;
            h -= 1;
        }
    }
    println!("{}", obj.len());
    for &(a, b) in &obj {
        println!("{} {}", a, b);
    }
}


#![allow(dead_code, non_snake_case)]

macro_rules! input {
    (source = $s:expr, $($r:tt)*) => {
        let mut iter = $s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
    ($($r:tt)*) => {
        let s = {
            use std::io::Read;
            let mut s = String::new();
            std::io::stdin().read_to_string(&mut s).unwrap();
            s
        };
        let mut iter = s.split_whitespace();
        input_inner!{iter, $($r)*}
    };
}

macro_rules! input_inner {
    ($iter:expr) => {};
    ($iter:expr, ) => {};

    ($iter:expr, $var:ident : $t:tt $($r:tt)*) => {
        let $var = read_value!($iter, $t);
        input_inner!{$iter $($r)*}
    };
}

macro_rules! read_value {
    ($iter:expr, ( $($t:tt),* )) => {
        ( $(read_value!($iter, $t)),* )
    };

    ($iter:expr, [ $t:tt ; $len:expr ]) => {
        (0..$len).map(|_| read_value!($iter, $t)).collect::<Vec<_>>()
    };

    ($iter:expr, chars) => {
        read_value!($iter, String).chars().collect::<Vec<char>>()
    };

    ($iter:expr, usize1) => {
        read_value!($iter, usize) - 1
    };

    ($iter:expr, $t:ty) => {
        $iter.next().unwrap().parse::<$t>().expect("Parse error")
    };
}

fn main() {
    input! {
        n: usize,
        g: [usize; n]
    }
    let mut obj = Vec::new();
    let mut h = n;
    let mut dub = n;
    let mut las = n;
    let mut f = vec![false; n+1];
    for i in (0..n).rev() {
        if g[i] == 1 {
            obj.push((h, i+1));
            h -= 1;
            las = i;
        } else if g[i] == 2 {
            if dub == 0 || dub <= h {
                println!("{}", -1);
                return;
            }
            obj.push((dub, i+1));
            dub -= 1;
            while dub > 0 && f[dub - 1] {
                dub -= 1;
            }
            las = i;
        } else if g[i] == 3 {
            if las == n {
                println!("{}", -1);
                return;
            }
            obj.push((h, i + 1));
            obj.push((h, las + 1));
            f[h-1] = true;
            las = i;
            h -= 1;
        }
    }
    println!("{}", obj.len());
    for &(a, b) in &obj {
        println!("{} {}", a, b);
    }
}


use std::io::stdin;
use std::cmp::min;

fn main() {

    let mut str = String::new();
    let _ = stdin().read_line(&mut str).unwrap();
    let n: usize = str.trim().parse().unwrap();
    str.clear();
		let _ = stdin().read_line(&mut str).unwrap();
		let throws:Vec<usize> = str.trim().split_whitespace().map(|x| {x.parse().unwrap()}).rev().collect();
		let mut heights = vec![0;n];
		let mut one:usize = 0;
		let mut line:usize = 0;
		let mut two :usize = 0;
		let mut flag = true;
		let mut xy : Vec<(usize, usize)> = Vec::new();
		for i in 0..n {
			match throws[i] {
				1 => {
					heights[i] = line;
					line += 1;
					xy.push((i,heights[i]));
				},
				2 => {
					while one <= i{
						if throws[one] == 1 {break;}
						one +=1;
					}
					if one > i {
						flag = false;
						break;
					}
					else {
						heights[i] = heights[one];
						xy.push((i,heights[i]));
						one += 1;
					}
				},
				3 => {
					while two < i{
						if throws[two] > 1 {break;}
						two +=1;
					}
					let mut bounce = two;
					if two >= i {
							while one <= i{
								if throws[one] == 1 {break;}
								one +=1;
							}
							if one > i{
								flag = false;
								break;
							}
							bounce = one;
							one += 1;
					} else {two += 1;}
					heights[i] = line;
					line += 1;
					xy.push((i,heights[i]));
					xy.push((bounce,heights[i]));
				},
				_ => {continue;},
			}
		}
		if flag{
			println!("{}",xy.len());
			for (a,b) in xy {
				println!("{} {}",n-b, n - a);
			}
		}
		else{println!("-1");}
}


use std::io::stdin;
use std::cmp::min;

fn main() {

    let mut str = String::new();
    let _ = stdin().read_line(&mut str).unwrap();
    let n: usize = str.trim().parse().unwrap();
    str.clear();
		let _ = stdin().read_line(&mut str).unwrap();
		let throws:Vec<usize> = str.trim().split_whitespace().map(|x| {x.parse().unwrap()}).rev().collect();
		let mut heights = vec![0;n];
		let mut one:usize = 0;
		let mut line:usize = 0;
		let mut two :usize = 0;
		let mut flag = true;
		let mut xy : Vec<(usize, usize)> = Vec::new();
		for i in 0..n {
			match throws[i] {
				1 => {
					heights[i] = line;
					line += 1;
					xy.push((i,heights[i]));
				},
				2 => {
					while one <= i{
						if throws[one] == 1 {break;}
						one +=1;
					}
					if one > i {
						flag = false;
						break;
					}
					else {
						heights[i] = heights[one];
						xy.push((i,heights[i]));
						one += 1;
					}
				},
				3 => {
					while two < i{
						if throws[two] > 1 {break;}
						two +=1;
					}
					let mut bounce = two;
					if two >= i {
							while one <= i{
								if throws[one] == 1 {break;}
								one +=1;
							}
							if one > i{
								flag = false;
								break;
							}
							bounce = one;
							one += 1;
					} else {two += 1;}
					heights[i] = line;
					line += 1;
					xy.push((i,heights[i]));
					xy.push((bounce,heights[i]));
				},
				_ => {continue;},
			}
		}
		if flag{
			println!("{}",xy.len());
			for (a,b) in xy {
				println!("{} {}",b+1, n - a);
			}
		}
		else{println!("-1");}
}


use std::io::stdin;
use std::cmp::min;

fn main() {

    let mut str = String::new();
    let _ = stdin().read_line(&mut str).unwrap();
    let n: usize = str.trim().parse().unwrap();
    str.clear();
		let _ = stdin().read_line(&mut str).unwrap();
		let throws:Vec<usize> = str.trim().split_whitespace().map(|x| {x.parse().unwrap()}).rev().collect();
		let mut heights = vec![0;n];
		let mut one:usize = 0;
		let mut line:usize = 0;
		let mut two :usize = 0;
		let mut flag = true;
		let mut xy : Vec<(usize, usize)> = Vec::new();
		for i in 0..n {
			match throws[i] {
				1 => {
					heights[i] = line;
					line += 1;
					xy.push((i,heights[i]));
				},
				2 => {
					while one <= i{
						if throws[one] == 1 {break;}
						one +=1;
					}
					if one > i {
						flag = false;
						break;
					}
					else {
						heights[i] = heights[one];
						xy.push((i,heights[i]));
						one += 1;
					}
				},
				3 => {
					while two < i{
						if throws[two] > 1 {break;}
						two +=1;
					}
					let mut bounce = two;
					if two >= i {
							while one <= i{
								if throws[one] == 1 {break;}
								one +=1;
							}
							if one > i{
								flag = false;
								break;
							}
							bounce = one;
							one += 1;
					} else {two += 1;}
					heights[i] = line;
					line += 1;
					xy.push((i,heights[i]));
					xy.push((bounce,heights[i]));
				},
				_ => {continue;},
			}
		}
		if flag{
			println!("{}",xy.len());
			for (a,b) in xy {
				println!("{} {}",n - a, b + 1);
			}
		}
		else{println!("-1");}
}