using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] % (i + 1) > 0)
            {
                long d = i + 1 - a[i] % (i + 1);
                if (d <= a[0])
                {
                    a[i] += d;
                    a[0] -= d;
                    ret.Add((1, i + 1, d));
                }
            }
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        var o = new List<(int, long)>();
        for (int i = 1; i < n; i++)
        {
            if (a[i] > 0)
            {
                long x = i + 1 - a[i];
                o.Add((i, x));
            }
        }
        o.Sort((o1, o2) => o1.Item2.CompareTo(o2.Item2));
        var f = new bool[n];
        int p = 0;
        for (int i = 1; i < n; i++)
            if (a[i] > v)
            {
                long x = i + 1 - (a[i] - v);
                while (x > a[0])
                {
                    while (p < o.Count && f[o[p].Item1])
                        p++;
                    if (p == o.Count || o[p].Item2 > a[0])
                        return null;
                    long y = i + 1 - a[o[p].Item1];
                    a[0] -= y;
                    a[i] += y;
                    a[0] += o[p].Item1 + 1;
                    a[i] -= o[p].Item1 + 1;
                    ret.Add((1, o[p].Item1 + 1, y));
                    ret.Add((o[p].Item1 + 1, 1, 1));
                    f[o[p].Item1] = true;
                }
                if (x <= a[0])
                {
                    a[0] -= x;
                    a[i] += x;
                    f[i] = true;
                    a[0] += i + 1;
                    a[i] -= i + 1;
                    ret.Add((1, i + 1, x));
                    ret.Add((i + 1, 1, 1));
                }

            }

        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] == v)
                continue;
            if (a[i] < v)
            {
                long x = v - a[i];
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                a[i] += x;
                ret.Add((1, i + 1, x));
            }
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
            //WriteArray(a);
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] % (i + 1) > 0)
            {
                long d = i + 1 - a[i] % (i + 1);
                if (d <= a[0])
                {
                    a[i] += d;
                    a[0] -= d;
                    ret.Add((1, i + 1, d));
                }
            }
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        var o = new List<(int, long)>();
        for (int i = 1; i < n; i++)
        {
            if (a[i] > 0)
            {
                long x = i + 1 - a[i];
                o.Add((i, x));
            }
        }
        o.Sort((o1, o2) => o1.Item2.CompareTo(o2.Item2));
        var f = new bool[n];
        int p = 0;
        for (int i = 1; i < n; i++)
            if (a[i] > v)
            {
                long x = i + 1 - (a[i] - v);
                while (x > a[0])
                {
                    while (p < o.Count && f[o[p].Item1])
                        p++;
                    if (p == o.Count || o[p].Item2 > a[0])
                        return null;
                    long y = i + 1 - a[o[p].Item1];
                    a[0] -= y;
                    a[i] += y;
                    a[0] += o[p].Item1 + 1;
                    a[i] -= o[p].Item1 + 1;
                    ret.Add((1, o[p].Item1 + 1, y));
                    ret.Add((o[p].Item1 + 1, 1, 1));
                }
                if (x <= a[0])
                {
                    a[0] -= x;
                    a[i] += x;
                    f[i] = true;
                    a[0] += i + 1;
                    a[i] -= i + 1;
                    ret.Add((1, i + 1, x));
                    ret.Add((i + 1, 1, 1));
                }

            }

        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] == v)
                continue;
            if (a[i] < v)
            {
                long x = v - a[i];
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                a[i] += x;
                ret.Add((1, i + 1, x));
            }
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
            //WriteArray(a);
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = n - 1; i > 0; i--)
        {
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        var o = new List<(int, long)>();
        for (int i = 1; i < n; i++)
        {
            if (a[i] > 0)
            {
                long x = i + 1 - a[i];
                o.Add((i, x));
            }
        }
        o.Sort((o1, o2) => o1.Item2.CompareTo(o2.Item2));

        foreach (var oo in o)
        {
            if (oo.Item2 > a[0])
                return null;
            int i = oo.Item1;
            long x = i + 1 - a[i];
            a[0] -= x;
            a[i] += x;
            a[0] += i + 1;
            a[i] -= i + 1;
            ret.Add((1, i + 1, x));
            ret.Add((i + 1, 1, 1));
        }

        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] == v)
                continue;
            if (a[i] < v)
            {
                long x = v - a[i];
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                a[i] += x;
                ret.Add((1, i + 1, x));
            }
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
            //WriteArray(a);
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = n - 1; i > 0; i--)
        {
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        var o = new List<(int, long)>();
        for (int i = 1; i < n; i++)
            if (a[i] > v)
            {
                long x = i + 1 - a[i] + v;
                o.Add((i, x));
            }
        o.Sort((o1, o2) => o1.Item2.CompareTo(o2.Item2));

        foreach (var oo in o)
        {
            if (oo.Item2 > a[0])
                return null;
            int i = oo.Item1;
            long x = i + 1 - a[i] + v;
            a[0] -= x;
            a[0] += i + 1;
            ret.Add((1, i + 1, x));
            ret.Add((i + 1, 1, 1));
        }

        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] == v)
                continue;
            if (a[i] < v)
            {
                long x = v - a[i];
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                ret.Add((1, i + 1, x));
            }
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = 1; i < n; i++)
        {
            if (a[i] % (i + 1) > 0)
            {
                long d = i + 1 - a[i] % (i + 1);
                if (d <= a[0])
                {
                    a[0] -= d;
                    a[i] += d;
                    ret.Add((1, i + 1, d));
                }
            }
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        for (int i = 1; i < n; i++)
            if (a[i] > v)
            {
                long x = (i + 1) - (a[i] - v);
                if (x > a[0])
                    return null;
                a[0] -= x;
                a[i] += x;
                ret.Add((1, i + 1, x));
                a[0] += i + 1;
                a[i] -= i + 1;
                ret.Add((i + 1, 1, 1));
            }

        for (int i = 1; i < n; i++)
        {
            if (a[i] == v)
                continue;
            long x = v - a[i];
            if (a[0] < x)
                throw new Exception();
            a[0] -= x;
            a[i] += x;
            ret.Add((1, i + 1, x));
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                if (ans.Count > 3 * n)
                    throw new Exception();
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
            //WriteArray(a);
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = n - 1; i > 0; i--)
        {
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] == v)
                continue;
            if (a[i] > v)
            {
                long x = i + 1 - a[i] + v;
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                a[0] += i + 1;
                ret.Add((1, i + 1, x));
                ret.Add((i + 1, 1, 1));
            }
            else
            {
                long x = v - a[i];
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                ret.Add((1, i + 1, x));
            }
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;

// (づ°ω°)づﾐe★゜・。。・゜゜・。。・゜☆゜・。。・゜゜・。。・゜
public class Solver
{
    List<(int, int, long)> Fun(int n, long[] a)
    {
        long sum = a.Sum(aa => aa);
        if (sum % n > 0)
            return null;

        int v = (int)(sum / n);
        var ret = new List<(int, int, long)>();
        for (int i = n - 1; i > 0; i--)
        {
            long x = a[i] / (i + 1);
            if (x > 0)
            {
                a[i] -= x * (i + 1);
                a[0] += x * (i + 1);
                ret.Add((i + 1, 1, x));
            }
        }

        var o = new List<(int, long)>();
        for (int i = 1; i < n; i++)
        {
            long x = i + 1 - a[i];
            o.Add((i, x));
        }
        o.Sort((o1, o2) => o1.Item2.CompareTo(o2.Item2));

        foreach (var oo in o)
        {
            if (oo.Item2 > a[0])
                return null;
            int i = oo.Item1;
            long x = i + 1 - a[i];
            a[0] -= x;
            a[i] += x;
            a[0] += i + 1;
            a[i] -= i + 1;
            ret.Add((1, i + 1, x));
            ret.Add((i + 1, 1, 1));
        }

        for (int i = n - 1; i > 0; i--)
        {
            if (a[i] == v)
                continue;
            if (a[i] < v)
            {
                long x = v - a[i];
                if (a[0] < x)
                    throw new Exception();
                a[0] -= x;
                a[i] += x;
                ret.Add((1, i + 1, x));
            }
        }

        return ret;
    }

    public void Solve()
    {
        for (int tt = ReadInt(); tt > 0; tt--)
        {
            int n = ReadInt();
            var a = ReadLongArray();

            var ans = Fun(n, a);
            if (ans == null)
                Write(-1);
            else
            {
                Write(ans.Count);
                foreach (var t in ans)
                    Write(t.Item1, t.Item2, t.Item3);
            }
            //WriteArray(a);
        }
    }

    #region Main

    protected static TextReader reader;
    protected static TextWriter writer;
    static void Main()
    {
#if DEBUG
        reader = new StreamReader("..\\..\\input.txt");
        //reader = new StreamReader(Console.OpenStandardInput());
        writer = Console.Out;
        //writer = new StreamWriter("..\\..\\output.txt");
#else
        reader = new StreamReader(Console.OpenStandardInput());
        writer = new StreamWriter(Console.OpenStandardOutput());
        //reader = new StreamReader("input.txt");
        //writer = new StreamWriter("output.txt");
#endif
        try
        {
            new Solver().Solve();
            //var thread = new Thread(new Solver().Solve, 1024 * 1024 * 128);
            //thread.Start();
            //thread.Join();
        }
        catch (Exception ex)
        {
#if DEBUG
            Console.WriteLine(ex);
#else
            throw;
#endif
        }
        reader.Close();
        writer.Close();
    }

    #endregion

    #region Read / Write
    private static Queue<string> currentLineTokens = new Queue<string>();
    private static string[] ReadAndSplitLine() { return reader.ReadLine().Split(new[] { ' ', '\t', }, StringSplitOptions.RemoveEmptyEntries); }
    public static string ReadToken() { while (currentLineTokens.Count == 0) currentLineTokens = new Queue<string>(ReadAndSplitLine()); return currentLineTokens.Dequeue(); }
    public static int ReadInt() { return int.Parse(ReadToken()); }
    public static long ReadLong() { return long.Parse(ReadToken()); }
    public static double ReadDouble() { return double.Parse(ReadToken(), CultureInfo.InvariantCulture); }
    public static int[] ReadIntArray() { return ReadAndSplitLine().Select(int.Parse).ToArray(); }
    public static long[] ReadLongArray() { return ReadAndSplitLine().Select(long.Parse).ToArray(); }
    public static double[] ReadDoubleArray() { return ReadAndSplitLine().Select(s => double.Parse(s, CultureInfo.InvariantCulture)).ToArray(); }
    public static int[][] ReadIntMatrix(int numberOfRows) { int[][] matrix = new int[numberOfRows][]; for (int i = 0; i < numberOfRows; i++) matrix[i] = ReadIntArray(); return matrix; }
    public static int[][] ReadAndTransposeIntMatrix(int numberOfRows)
    {
        int[][] matrix = ReadIntMatrix(numberOfRows); int[][] ret = new int[matrix[0].Length][];
        for (int i = 0; i < ret.Length; i++) { ret[i] = new int[numberOfRows]; for (int j = 0; j < numberOfRows; j++) ret[i][j] = matrix[j][i]; }
        return ret;
    }
    public static string[] ReadLines(int quantity) { string[] lines = new string[quantity]; for (int i = 0; i < quantity; i++) lines[i] = reader.ReadLine().Trim(); return lines; }
    public static void WriteArray<T>(IEnumerable<T> array) { writer.WriteLine(string.Join(" ", array)); }
    public static void Write(params object[] array) { WriteArray(array); }
    public static void WriteLines<T>(IEnumerable<T> array) { foreach (var a in array) writer.WriteLine(a); }
    private class SDictionary<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get { return ContainsKey(key) ? base[key] : default(TValue); }
            set { base[key] = value; }
        }
    }
    private static T[] Init<T>(int size) where T : new() { var ret = new T[size]; for (int i = 0; i < size; i++) ret[i] = new T(); return ret; }
    #endregion
}


using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;
using System.Linq;

using E = System.Linq.Enumerable;
using System.Threading;

internal partial class Solver {
    public void Run() {
        var t = ni();
        while (t-- > 0) {
            var n = ni();
            var a = nl(n);
            var ans = Solve(n, a);
            if (ans == null) cout.WriteLine(-1);
            else {
                cout.WriteLine(ans.Count);
                cout.WriteLine(ans.Select(v => v.I + " " + v.J + " " + v.X).JoinToString("\n"));
            }
        }
    }

    // i,j,x
    private List<(int I, int J, long X)> Solve(int n, long[] a) {
        var sum = a.Sum();
        if (sum % n != 0) return null;
        var expected = sum / n;
        // a[i] -= x * i, a[j] += x * j
        var res = new List<(int I, int J, long X)>();
        Action<int, int, long> move = (from, to, x) => {
            a[from] -= x * (from + 1);
            a[to] += x * (from + 1);
            res.Add((from + 1, to + 1, x));
        };

        for (int i = 1; i < a.Length; i++) {
            var d = i + 1;
            if (a[i] % d != 0) { // dの倍数にしたい
                var need = d - a[i] % d;
                move(0, i, need);
            }
            if (a[i] % d != 0) throw new Exception();
            move(i, 0, a[i] / d);
        }
        for (int i = 1; i < a.Length; i++) {
            move(0, i, expected);
        }

        return res;
    }
}

// PREWRITEN CODE BEGINS FROM HERE

static public class StringExtensions {
    static public string JoinToString<T>(this IEnumerable<T> source, string separator = " ") {
        return string.Join(separator, source);
    }
}

internal partial class Solver : Scanner {
    static readonly int? StackSizeInMebiByte = null; //50;
    public static void StartAndJoin(Action action, int maxStackSize) {
        var thread = new Thread(new ThreadStart(action), maxStackSize);
        thread.Start();
        thread.Join();
    }

    public static void Main() {
#if LOCAL
        byte[] inputBuffer = new byte[1000000];
        var inputStream = Console.OpenStandardInput(inputBuffer.Length);
        using (var reader = new StreamReader(inputStream, Console.InputEncoding, false, inputBuffer.Length)) {
            Console.SetIn(reader);
            new Solver(Console.In, Console.Out).Run();
        }
#else
        Console.SetOut(new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false });
        if (StackSizeInMebiByte.HasValue) {
            StartAndJoin(() => new Solver(Console.In, Console.Out).Run(), StackSizeInMebiByte.Value * 1024 * 1024);
        } else {
            new Solver(Console.In, Console.Out).Run();
        }
        Console.Out.Flush();
#endif
    }

#pragma warning disable IDE0052
    private readonly TextReader cin;
    private readonly TextWriter cout;
    private readonly TextWriter cerr;
#pragma warning restore IDE0052

    public Solver(TextReader reader, TextWriter writer)
        : base(reader) {
        cin = reader;
        cout = writer;
        cerr = Console.Error;
    }

    public Solver(string input, TextWriter writer)
        : this(new StringReader(input), writer) {
    }

#pragma warning disable IDE1006
#pragma warning disable IDE0051
    private int ni() { return NextInt(); }
    private int[] ni(int n) { return NextIntArray(n); }
    private long nl() { return NextLong(); }
    private long[] nl(int n) { return NextLongArray(n); }
    private double nd() { return NextDouble(); }
    private double[] nd(int n) { return NextDoubleArray(n); }
    private string ns() { return Next(); }
    private string[] ns(int n) { return NextArray(n); }
#pragma warning restore IDE1006
#pragma warning restore IDE0051
}

#if DEBUG
internal static class LinqPadExtension {
    public static string TextDump<T>(this T obj) {
        if (obj is IEnumerable) return (obj as IEnumerable).Cast<object>().JoinToString().Dump();
        else return obj.ToString().Dump();
    }
    public static T Dump<T>(this T obj) {
        return LINQPad.Extensions.Dump(obj);
    }
}
#endif

public class Scanner {
    private readonly TextReader Reader;
    private readonly CultureInfo ci = CultureInfo.InvariantCulture;

    private readonly char[] buffer = new char[2 * 1024];
    private int cursor = 0, length = 0;
    private string Token;
    private readonly StringBuilder sb = new StringBuilder(1024);

    public Scanner()
        : this(Console.In) {
    }

    public Scanner(TextReader reader) {
        Reader = reader;
    }

    public int NextInt() { return checked((int)NextLong()); }
    public long NextLong() {
        var s = Next();
        long r = 0;
        int i = 0;
        bool negative = false;
        if (s[i] == '-') {
            negative = true;
            i++;
        }
        for (; i < s.Length; i++) {
            r = r * 10 + (s[i] - '0');
#if DEBUG
            if (!char.IsDigit(s[i])) throw new FormatException();
#endif
        }
        return negative ? -r : r;
    }
    public double NextDouble() { return double.Parse(Next(), ci); }
    public string[] NextArray(int size) {
        string[] array = new string[size];
        for (int i = 0; i < size; i++) {
            array[i] = Next();
        }

        return array;
    }
    public int[] NextIntArray(int size) {
        int[] array = new int[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextInt();
        }

        return array;
    }

    public long[] NextLongArray(int size) {
        long[] array = new long[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextLong();
        }

        return array;
    }

    public double[] NextDoubleArray(int size) {
        double[] array = new double[size];
        for (int i = 0; i < size; i++) {
            array[i] = NextDouble();
        }

        return array;
    }

    public string Next() {
        if (Token == null) {
            if (!StockToken()) {
                throw new Exception();
            }
        }
        var token = Token;
        Token = null;
        return token;
    }

    public bool HasNext() {
        if (Token != null) {
            return true;
        }

        return StockToken();
    }

    private bool StockToken() {
        while (true) {
            sb.Clear();
            while (true) {
                if (cursor >= length) {
                    cursor = 0;
                    if ((length = Reader.Read(buffer, 0, buffer.Length)) <= 0) {
                        break;
                    }
                }
                var c = buffer[cursor++];
                if (33 <= c && c <= 126) {
                    sb.Append(c);
                } else {
                    if (sb.Length > 0) break;
                }
            }

            if (sb.Length > 0) {
                Token = sb.ToString();
                return true;
            }

            return false;
        }
    }
}


use std::fmt::Debug;
use std::str::FromStr;

pub struct TokenReader {
    reader: std::io::Stdin,
    tokens: Vec<String>,
    index: usize,
}

impl TokenReader {
    pub fn new() -> Self {
        Self {
            reader: std::io::stdin(),
            tokens: Vec::new(),
            index: 0,
        }
    }

    pub fn next<T>(&mut self) -> T
    where
        T: FromStr,
        T::Err: Debug,
    {
        if self.index >= self.tokens.len() {
            self.load_next_line();
        }
        self.index += 1;
        self.tokens[self.index - 1].parse().unwrap()
    }

    pub fn vector<T>(&mut self) -> Vec<T>
    where
        T: FromStr,
        T::Err: Debug,
    {
        if self.index >= self.tokens.len() {
            self.load_next_line();
        }
        self.index = self.tokens.len();
        self.tokens.iter().map(|tok| tok.parse().unwrap()).collect()
    }

    pub fn load_next_line(&mut self) {
        let mut line = String::new();
        self.reader.read_line(&mut line).unwrap();

        self.tokens = line
            .split_whitespace()
            .map(String::from)
            .collect();
        self.index = 0;
    }
}

fn make_move(nums: &mut Vec<i64>, i: usize, j: usize, x: i64) {
    let delta = (i as i64 + 1) * x;
    nums[i] -= delta;
    nums[j] += delta;
}

fn solve(nums: &mut Vec<i64>) -> Option<Vec<(usize, usize, i64)>> {
    let sum: i64 = nums.iter().sum();
    if sum % nums.len() as i64 != 0 {
        return None;
    }
    let avg = sum / (nums.len() as i64);

    let mut res = vec![];
    for i in 1..nums.len() {
        let mut x = nums[i] / (i + 1) as i64;
        let d = (x + 1) * (i + 1) as i64 - nums[i];

        if (x + 1) * (i + 1) as i64 - nums[i] <= nums[0] {
            res.push((0, i, d));
            make_move(nums, 0, i, d);
            x += 1;
        }
        if x > 0 {
            res.push((i, 0, x));
            make_move(nums, i, 0, x);
        }
    }

    for i in 1..nums.len() {
        let x = avg - nums[i];
        if x > 0 {
            res.push((0, i, x));
            make_move(nums, 0, i, x);
        }
        if nums[i] != avg {
            return None;
        }
    }
    Some(res)
}

fn main() {
    let mut reader = TokenReader::new();
    let tests = reader.next();

    for _ in 0..tests {
        let _ = reader.next::<usize>();
        let mut nums = reader.vector();

        if let Some(res) = solve(&mut nums) {
            println!("{}", res.len());
            for (i, j, x) in res {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        } else {
            println!("-1");
        }
    }
}


use std::fmt::Debug;
use std::str::FromStr;

pub struct TokenReader {
    reader: std::io::Stdin,
    tokens: Vec<String>,
    index: usize,
}

impl TokenReader {
    pub fn new() -> Self {
        Self {
            reader: std::io::stdin(),
            tokens: Vec::new(),
            index: 0,
        }
    }

    pub fn next<T>(&mut self) -> T
    where
        T: FromStr,
        T::Err: Debug,
    {
        if self.index >= self.tokens.len() {
            self.load_next_line();
        }
        self.index += 1;
        self.tokens[self.index - 1].parse().unwrap()
    }

    pub fn vector<T>(&mut self) -> Vec<T>
    where
        T: FromStr,
        T::Err: Debug,
    {
        if self.index >= self.tokens.len() {
            self.load_next_line();
        }
        self.index = self.tokens.len();
        self.tokens.iter().map(|tok| tok.parse().unwrap()).collect()
    }

    pub fn load_next_line(&mut self) {
        let mut line = String::new();
        self.reader.read_line(&mut line).unwrap();

        self.tokens = line
            .split_whitespace()
            .map(String::from)
            .collect();
        self.index = 0;
    }
}

fn make_move(nums: &mut Vec<i64>, i: usize, j: usize, x: i64) {
    let delta = (i as i64 + 1) * x;
    nums[i] -= delta;
    nums[j] += delta;
}

fn solve(nums: &mut Vec<i64>) -> Option<Vec<(usize, usize, i64)>> {
    let sum: i64 = nums.iter().sum();
    if sum % nums.len() as i64 != 0 {
        return None;
    }
    let avg = sum / (nums.len() as i64);

    let mut res = vec![];
    for i in 1..nums.len() {
        let x = nums[i] / (i + 1) as i64;
        if x > 0 {
            res.push((i, 0, x));
            make_move(nums, i, 0, x);
        }
    }

    for i in 1..nums.len() {
        let x = avg - nums[i];
        if x > 0 {
            res.push((0, i, x));
            make_move(nums, 0, i, x);
        }
        if nums[i] != avg {
            return None;
        }
    }
    Some(res)
}

fn main() {
    let mut reader = TokenReader::new();
    let tests = reader.next();

    for _ in 0..tests {
        let _ = reader.next::<usize>();
        let mut nums = reader.vector();

        if let Some(res) = solve(&mut nums) {
            println!("{}", res.len());
            for (i, j, x) in res {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        } else {
            println!("-1");
        }
    }
}


use std::fmt::Debug;
use std::str::FromStr;

pub struct TokenReader {
    reader: std::io::Stdin,
    tokens: Vec<String>,
    index: usize,
}

impl TokenReader {
    pub fn new() -> Self {
        Self {
            reader: std::io::stdin(),
            tokens: Vec::new(),
            index: 0,
        }
    }

    pub fn next<T>(&mut self) -> T
    where
        T: FromStr,
        T::Err: Debug,
    {
        if self.index >= self.tokens.len() {
            self.load_next_line();
        }
        self.index += 1;
        self.tokens[self.index - 1].parse().unwrap()
    }

    pub fn vector<T>(&mut self) -> Vec<T>
    where
        T: FromStr,
        T::Err: Debug,
    {
        if self.index >= self.tokens.len() {
            self.load_next_line();
        }
        self.index = self.tokens.len();
        self.tokens.iter().map(|tok| tok.parse().unwrap()).collect()
    }

    pub fn load_next_line(&mut self) {
        let mut line = String::new();
        self.reader.read_line(&mut line).unwrap();

        self.tokens = line
            .split_whitespace()
            .map(String::from)
            .collect();
        self.index = 0;
    }
}

fn make_move(nums: &mut Vec<i64>, i: usize, j: usize, x: i64) {
    let delta = (i as i64 + 1) * x;
    nums[i] -= delta;
    nums[j] += delta;
}

fn solve(nums: &mut Vec<i64>) -> Option<Vec<(usize, usize, i64)>> {
    let sum: i64 = nums.iter().sum();
    if sum % nums.len() as i64 != 0 {
        return None;
    }
    let avg = sum / (nums.len() as i64);

    let mut res = vec![];
    for i in 1..nums.len() {
        let x = nums[i] / (i + 1) as i64;
        if x > 0 {
            res.push((i, 0, x));
            make_move(nums, i, 0, x);
        }
    }

    for i in 1..nums.len() {
        let x = avg - nums[i];
        if x > 0 {
            res.push((0, i, x));
            make_move(nums, 0, i, x);
        }
    }
    Some(res)
}

fn main() {
    let mut reader = TokenReader::new();
    let tests = reader.next();

    for _ in 0..tests {
        let _ = reader.next::<usize>();
        let mut nums = reader.vector();

        if let Some(res) = solve(&mut nums) {
            println!("{}", res.len());
            for (i, j, x) in res {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        } else {
            println!("-1");
        }
    }
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! m {
	($c:tt,$x:expr,$y:expr) => {{
		let b=$y; let a=&mut$x; if b$c*a {*a=b; true} else {false}
	}};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: Vec::new(), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = Vec::with_capacity(8);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
}
//------------------- End rusT }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	rep!{[rin.u()]
		let n = rin.u();
		let mut a = rin.vi(n);
		let sum = a.iter().sum::<i32>();
		let f = |x:usize| x as i32;
		let ni = f(n);
		let mut dead = false;
		if sum % ni != 0 {
			writeln!(rout, "-1").ok();
			continue;
		}
		let goal = sum / ni;
		{
			let mut ok = true;
			for i in 0..n {
				if a[i] != goal {
					ok = false;
					break;
				}
			}
			if ok {
				writeln!(rout, "0").ok();
				continue;
			}
		}
		let mut is_bad = vec![false; n];
		let mut bad = Vec::new();
		let mut sol = Vec::new();
		for i in 1..n {
			let ii = f(i+1);
			if a[i] % ii > goal {
				bad.push((ii - a[i] % ii, ii, i));
				is_bad[i] = true;
			}
			if a[i] >= ii {
				let x = a[i] / ii;
				a[i] -= x * ii;
				a[0] += x * ii;
				sol.push((ii,1,x));
			}
		}
		bad.sort();
		for (need, give, i) in bad {
			let ii = f(i+1);
			if a[0] < need {
				dead = true;
				break;
			}
			let x = need;
			a[0] -= need;
			a[i] += need;
			sol.push((1,ii,x));
			let x = give / ii;
			a[0] += give;
			a[i] -= give;
			sol.push((ii,1,x));
		}
		if !dead {
			for i in 1..n {
				let ii = f(i+1);
				assert!(a[i] <= goal);
				if a[i] < goal {
					let x = goal - a[i];
					if a[0] < x {
						dead = true;
						break;
					}
					a[0] -= x;
					a[i] += x;
					sol.push((1,ii,x));
				}
			}
		}
		if dead {
			writeln!(rout, "-1").ok();
			continue;
		}
		writeln!(rout, "{}", sol.len()).ok();
		for (i,j,x) in sol {
			writeln!(rout, "{} {} {}", i, j, x).ok();
		}
	};
}


//spnauti-rusT {{{
use std::io::*; use std::str::{self,*}; use std::fmt::Debug;
#[allow(unused_imports)] use std::cmp::Ordering::{self,*};
#[allow(unused_imports)] use std::ops::{self,*};
#[allow(unused_imports)] use std::iter::{self,*};
#[allow(unused_imports)] use std::collections::*;
#[allow(unused_imports)] use std::cell::*;
#[allow(unused_macros)] macro_rules! m {
	($c:tt,$x:expr,$y:expr) => {{
		let b=$y; let a=&mut$x; if b$c*a {*a=b; true} else {false}
	}};
}
#[allow(unused_macros)] macro_rules! l {
	($($v:ident),+ =$e:expr) => {$(let$v=$e;)+};
	($($v:ident),+:$t:ty=$e:expr) => {$(let$v:$t=$e;)+};
	(mut $($v:ident),+ =$e:expr) => {$(let mut$v=$e;)+};
	(mut $($v:ident),+:$t:ty=$e:expr) => {$(let mut$v:$t=$e;)+};
}
#[allow(unused_macros)] macro_rules! v {
	([$d:expr]$($s:tt)+) => {vec![v!($($s)+);$d]};
	([]) => {Vec::new()}; ([$e:expr]) => {Vec::with_capacity($e)}; (=$e:expr) => {$e};
}
#[allow(unused_macros)] macro_rules! rep { {[$c:expr]$($s:tt)+} => {for _ in 0..$c {$($s)+}} }
#[allow(dead_code)] fn reader() -> WordReaderC { WordReaderC::new() }
#[allow(dead_code)] fn writer() -> BufWriter<Stdout> { BufWriter::new(stdout()) }
struct WordReaderC {buf: Vec<u8>, pos: usize, q: std::io::StdinLock<'static>}//'
#[allow(dead_code)] impl WordReaderC {
	fn new() -> Self {
		let r = unsafe {&*Box::into_raw(Box::new(stdin()))};
		Self { q: r.lock(), buf: Vec::new(), pos: 0 }
	}
	fn next_line(&mut self) -> bool {
		self.buf.clear(); self.pos = 0;
		self.q.read_until(b'\n', &mut self.buf).unwrap_or(0) > 0
	}
	fn is_ws(c: u8) -> bool {
		c == b' ' || c == b'\r' || c == b'\n' || c == b'\t'
	}
	fn byte(&mut self) -> Option<u8> {
		if self.pos == self.buf.len() { if !self.next_line() { return None; } }
		self.pos += 1; Some(self.buf[self.pos - 1])
	}
	fn vb(&mut self) -> Vec<u8> {
		let mut s = Vec::with_capacity(8);
		let mut f = false;
		loop {
			if let Some(c) = self.byte() {
				if !Self::is_ws(c) {
					s.push(c);
					f = true;
				} else if f { break; }
			} else { break; }
		}
		s
	}
	fn s(&mut self) -> String { String::from_utf8(self.vb()).expect("invalid utf8") }
	fn i(&mut self) ->    i32 { self.p() }
	fn l(&mut self) ->    i64 { self.p() }
	fn u(&mut self) ->  usize { self.p() }
	fn f(&mut self) ->    f64 { self.p() }
	fn vi(&mut self, n: usize) -> Vec<i32> { self.vp(n) }
	fn vl(&mut self, n: usize) -> Vec<i64> { self.vp(n) }
	fn vu(&mut self, n: usize) -> Vec<usize> { self.vp(n) }
	fn ii(&mut self, n: usize) -> impl Iterator<Item=i32> { self.ip(n).into_iter() }
	fn iu(&mut self, n: usize) -> impl Iterator<Item=usize> { self.ip(n).into_iter() }
	fn p<T: FromStr>(&mut self) -> T where T::Err: Debug {
		let w = self.vb(); str::from_utf8(w.as_ref()).unwrap().parse::<T>().unwrap()
	}
	fn vp<T: FromStr>(&mut self, n: usize) -> Vec<T> where T::Err: Debug {
		(0..n).map(|_|self.p()).collect()
	}
	fn ip<T: FromStr>(&mut self, n: usize) -> impl Iterator<Item=T> where T::Err: Debug {
		self.vp(n).into_iter()
	}
}
//------------------- End rusT }}}

fn main() {
	let mut rin = reader();
	let mut rout = writer();

	rep!{[rin.u()]
		let f = |i:i64, j:i64, x:i64, sol: &mut Vec<(i64,i64,i64)>, a: &mut [i64]| {
			assert!(x % i == 0);
			a[i as usize - 1] -= x;
			a[j as usize - 1] += x;
			sol.push( (i,j,x/i) );
		};
		let n = rin.u();
		let mut a = rin.vl(n);
		let sum = a.iter().sum::<i64>();
		if sum % n as i64 != 0 {
			writeln!(rout, "-1").ok();
			continue;
		}
		let avg = sum / n as i64;
		let mut sol = v!([]);
		for i in 1..n {
			let ii = (i + 1) as i64;
			if a[i] % ii != 0 {
				f(1, ii, ii - a[i] % ii, &mut sol, &mut a);
			}
			f(ii, 1, a[i], &mut sol, &mut a);
		}
		for i in 1..n {
			let ii = (i + 1) as i64;
			f(1, ii, avg, &mut sol, &mut a);
		}
		writeln!(rout, "{}", sol.len()).ok();
		for (i,j,x) in sol {
			writeln!(rout, "{} {} {}", i, j, x).ok();
		}
	}
}


/* This code was written by
Russell Emerine - linguist,
mathematician, coder,
musician, and metalhead. */

use std::ops::Index;

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

struct A {
    a: Vec<usize>,
    operations: Vec<(usize, usize, usize)>,
}

impl A {
    fn new(a: Vec<usize>) -> Self {
        Self {
            a,
            operations: vec![],
        }
    }

    fn operate(&mut self, i: usize, j: usize, x: usize) {
        self.operations.push((i, j, x));
        self.a[i] -= x * (i + 1);
        self.a[j] += x * (i + 1);
    }

    fn results(self) -> Vec<(usize, usize, usize)> {
        self.operations
    }
}

impl Index<usize> for A {
    type Output = usize;

    fn index(&self, i: usize) -> &usize {
        &self.a[i]
    }
}

fn main() {
    let mut scanner = Scanner::default();
    for _ in 0..scanner.next() {
        let n = scanner.next();
        let a: Vec<_> = (0..n).map(|_| scanner.next()).collect();

        if a.iter().sum::<usize>() % n != 0 {
            println!("-1");
        } else {
            let average = a.iter().sum::<usize>() / n;
            let mut a = A::new(a);

            for i in 1..n {
                a.operate(0, i, (i + 1 - a[i] % (i + 1)) % (i + 1));
                a.operate(i, 0, a[i] / (i + 1));
            }

            for i in 1..n {
                a.operate(0, i, average);
            }

            let operations = a.results();
            println!("{}", operations.len());
            for (i, j, x) in operations.into_iter() {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        }
    }
}


/* This code was written by
Russell Emerine - linguist,
mathematician, coder,
musician, and metalhead. */

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::default();
    for _ in 0..scanner.next() {
        let n = scanner.next();
        let mut a: Vec<_> = (0..n).map(|_| scanner.next()).collect();

        if a.iter().sum::<usize>() % n != 0 {
            println!("-1");
        } else {
            let average = a.iter().sum::<usize>() / n;
            let mut operations = vec![];

            for i in (1..n).rev() {
                let x = a[i] / (i + 1);
                operations.push((i, i - 1, x));
                a[i] -= x * (i + 1);
                a[i - 1] += x * (i + 1);
            }

            for i in (1..n).rev() {
                if a[i] > average {
                    let x = (i + 1 + average - a[i]).rem_euclid(i + 1);
                    operations.push((0, i, x));
                    a[0] -= x;
                    a[i] += x;

                    let x = (a[i] - average) / (i + 1);
                    operations.push((i, 0, x));
                    a[i] -= x * (i + 1);
                    a[0] += x * (i + 1);
                } else {
                    let x = average - a[i];
                    operations.push((0, i, x));
                    a[0] -= x;
                    a[i] += x;
                }
            }

            println!("{}", operations.len());
            for (i, j, x) in operations.into_iter() {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        }
    }
}


/* This code was written by
Russell Emerine - linguist,
mathematician, coder,
musician, and metalhead. */

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::default();
    for _ in 0..scanner.next() {
        let n = scanner.next();
        let mut a: Vec<_> = (0..n).map(|_| scanner.next::<usize>()).collect();

        if a.iter().sum::<usize>() % n != 0 {
            println!("-1");
        } else {
            let average = a.iter().sum::<usize>() / n;
            let mut operations = vec![];

            for i in (1..n).rev() {
                let x = a[i] / (i + 1);
                operations.push((i, i - 1, x));
                a[i] -= x * (i + 1);
                a[i - 1] += x * (i + 1);
            }

            for i in 1..n {
                let x = average - a[i];
                operations.push((0, i, x));
                a[0] -= x;
                a[i] += x;
            }

            println!("{}", operations.len());
            for (i, j, x) in operations.into_iter() {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        }
    }
}


/* This code was written by
Russell Emerine - linguist,
mathematician, coder,
musician, and metalhead. */

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::default();
    for _ in 0..scanner.next() {
        let n = scanner.next();
        let mut a: Vec<_> = (0..n).map(|_| scanner.next::<usize>() - 1).collect();

        if a.iter().sum::<usize>() % n != 0 {
            println!("-1");
        } else {
            let average = a.iter().sum::<usize>() / n;
            let mut operations = vec![];

            for i in (1..n).rev() {
                let x = a[i] / (i + 1);
                operations.push((i, i - 1, x));
                a[i] -= x * (i + 1);
                a[i - 1] += x * (i + 1);
            }

            for i in 1..n {
                let x = average - a[i];
                operations.push((0, i, x));
                a[0] -= x;
                a[i] += x;
            }

            println!("{}", operations.len());
            for (i, j, x) in operations.into_iter() {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        }
    }
}


/* This code was written by
Russell Emerine - linguist,
mathematician, coder,
musician, and metalhead. */

#[derive(Default)]
struct Scanner {
    buffer: Vec<String>,
}

impl Scanner {
    fn next<T: std::str::FromStr>(&mut self) -> T {
        loop {
            if let Some(token) = self.buffer.pop() {
                return token.parse().ok().expect("Failed parse");
            }
            let mut input = String::new();
            std::io::stdin().read_line(&mut input).expect("Failed read");
            self.buffer = input.split_whitespace().rev().map(String::from).collect();
        }
    }
}

fn main() {
    let mut scanner = Scanner::default();
    for _ in 0..scanner.next() {
        let n = scanner.next();
        let mut a: Vec<_> = (0..n).map(|_| scanner.next()).collect();

        if a.iter().sum::<usize>() % n != 0 {
            println!("-1");
        } else {
            let average = a.iter().sum::<usize>() / n;
            let mut operations = vec![];

            for i in (1..n).rev() {
                let x = a[i] / (i + 1);
                operations.push((i, i - 1, x));
                a[i] -= x * (i + 1);
                a[i - 1] += x * (i + 1);
            }

            for i in 1..n {
                if a[i] > average {
                    let x = (i + 1 + average - a[i]).rem_euclid(i + 1);
                    operations.push((0, i, x));
                    a[0] -= x;
                    a[i] += x;

                    let x = (a[i] - average) / (i + 1);
                    operations.push((i, 0, x));
                    a[i] -= x * (i + 1);
                    a[0] += x * (i + 1);
                } else {
                    let x = average - a[i];
                    operations.push((0, i, x));
                    a[0] -= x;
                    a[i] += x;
                }
            }

            println!("{}", operations.len());
            for (i, j, x) in operations.into_iter() {
                println!("{} {} {}", i + 1, j + 1, x);
            }
        }
    }
}


#[allow(unused_macros)]
macro_rules! read_line_to_tuple {
    ( $( $t:ty ),* ) => {{
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).unwrap();
        let mut iter = input.split_whitespace();
        ( $( iter.next().unwrap().parse::<$t>().unwrap() ),* )
    }};
}

#[allow(unused_macros)]
macro_rules! read_line_to_collection {
    ( $t:ty ) => {{
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).unwrap();
        let iter = input.split_whitespace();
        iter.map(|x| x.parse().unwrap()).collect::<$t>()
    }};
}

fn solve() -> String {
    let n = read_line_to_tuple!(usize);
    let mut a = read_line_to_collection!(Vec<usize>);
    a.insert(0, 0);

    let sum = a.iter().sum::<usize>();
    if sum % n != 0 { return String::from("-1") }

    let mut ans = Vec::with_capacity(3 * n);
    let mut f = |i: usize, j: usize, x: usize| {
        ans.push(format!("{} {} {}", i, j, x));
    };

    for i in 2..=n {
        if a[i] % i != 0 {
            f(1, i, i - a[i] % i);
            a[i] += i - a[i] % i;
        }
        f(i, 1, a[i] / i);
    }

    for i in 2..=n {
        f(1, i, sum / n);
    }

    format!("{}\n{}", ans.len(), ans.join("\n"))
}

fn main() {
    let t = read_line_to_tuple!(usize);
    let answers = (0..t).map(|_| solve()).collect::<Vec<_>>();
    println!("{}", answers.join("\n"));
}


#[allow(unused_macros)]
macro_rules! read_line_to_tuple {
    ( $( $t:ty ),* ) => {{
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).unwrap();
        let mut iter = input.split_whitespace();
        ( $( iter.next().unwrap().parse::<$t>().unwrap() ),* )
    }};
}

#[allow(unused_macros)]
macro_rules! read_line_to_collection {
    ( $t:ty ) => {{
        let mut input = String::new();
        std::io::stdin().read_line(&mut input).unwrap();
        let iter = input.split_whitespace();
        iter.map(|x| x.parse().unwrap()).collect::<$t>()
    }};
}

fn solve() -> String {
    let n = read_line_to_tuple!(usize);
    let mut a = read_line_to_collection!(Vec<usize>);
    a.insert(0, 0);

    let sum = a.iter().sum::<usize>();
    if sum % n != 0 { return String::from("-1") }

    let mut ans = Vec::with_capacity(3 * n);
    let mut f = |i: usize, j: usize, x: usize| {
        ans.push(format!("{} {} {}", i, j, x));
    };

    for i in 2..=n {
        if a[i] % i != 0 {
            f(1, i, i - a[i] % i);
            a[i] += i - a[i] % i;
        }
        f(i, 1, a[i]);
    }

    for i in 2..=n {
        f(1, i, sum / n);
    }

    format!("{}\n{}", ans.len(), ans.join("\n"))
}

fn main() {
    let t = read_line_to_tuple!(usize);
    let answers = (0..t).map(|_| solve()).collect::<Vec<_>>();
    println!("{}", answers.join("\n"));
}


mod cp {
    use std::io::prelude::*;
    pub fn stdin_to_string() -> String {
        let mut content = String::new();
        let stdin = std::io::stdin();
        let mut rd = stdin.lock();
        rd.read_to_string(&mut content).unwrap();
        return content;
    }

    pub struct Parser<'a> {
        tokens: std::str::SplitWhitespace<'a>,
    }

    impl<'a> Parser<'a> {
        pub fn new(text: &'a str) -> Self {
            Self {
                tokens: text.split_whitespace(),
            }
        }

        pub fn read_or_eof<T: std::str::FromStr>(&mut self) -> Option<T> {
            self.next().map(|s| match s.parse() {
                Ok(x) => x,
                Err(_) => panic!("cannot parse {:?}", s),
            })
        }

        pub fn read<T: std::str::FromStr>(&mut self) -> T {
            self.read_or_eof::<T>().expect("unexpected end-of-file")
        }
    }

    impl<'a> Iterator for Parser<'a> {
        type Item = &'a str;
        fn next(&mut self) -> Option<&'a str> {
            self.tokens.next()
        }
    }

    #[macro_export]
    macro_rules! take {
        ($p: expr, $n: expr) => {
            $p.by_ref().take($n).map(|x| x.parse().unwrap())
        };
        ($p: expr, $n: expr, $t: ty) => {
            $p.by_ref().take($n).map(|x| x.parse::<$t>().unwrap())
        };
    }

    #[macro_export]
    macro_rules! take_all {
        ($p: expr) => {
            $p.by_ref().map(|x| x.parse().unwrap())
        };
        ($p: expr, $t: ty) => {
            $p.by_ref().map(|x| x.parse::<$t>().unwrap())
        };
    }
}

use cp::*;

fn main() {
    let content = stdin_to_string();
    let mut inp = Parser::new(&content);
    let t: usize = inp.read();
    for _cs in 1..=t {
        let n: usize = inp.read();
        let a = std::iter::once(0)
            .chain(take!(inp, n, i32))
            .collect::<Vec<_>>();
        let sum = a.iter().sum::<i32>();
        if sum % (n as i32) != 0 {
            println!("-1");
        } else {
            let avg = sum / (n as i32);
            for i in 2..=n {
                let ii = i as i32;
                let chg = if a[i] % ii == 0 {0} else {ii - a[i] % ii};
                println!("{} {} {}", 1, i, chg);
                println!("{} {} {}", i, 1, (a[i] + chg) / ii);
            }
            for i in 2..=n {
                println!("{} {} {}", 1, i, avg);
            }
        }
    }
}


mod cp {
    use std::io::prelude::*;
    pub fn stdin_to_string() -> String {
        let mut content = String::new();
        let stdin = std::io::stdin();
        let mut rd = stdin.lock();
        rd.read_to_string(&mut content).unwrap();
        return content;
    }

    pub struct Parser<'a> {
        tokens: std::str::SplitWhitespace<'a>,
    }

    impl<'a> Parser<'a> {
        pub fn new(text: &'a str) -> Self {
            Self {
                tokens: text.split_whitespace(),
            }
        }

        pub fn read_or_eof<T: std::str::FromStr>(&mut self) -> Option<T> {
            self.next().map(|s| match s.parse() {
                Ok(x) => x,
                Err(_) => panic!("cannot parse {:?}", s),
            })
        }

        pub fn read<T: std::str::FromStr>(&mut self) -> T {
            self.read_or_eof::<T>().expect("unexpected end-of-file")
        }
    }

    impl<'a> Iterator for Parser<'a> {
        type Item = &'a str;
        fn next(&mut self) -> Option<&'a str> {
            self.tokens.next()
        }
    }

    #[macro_export]
    macro_rules! take {
        ($p: expr, $n: expr) => {
            $p.by_ref().take($n).map(|x| x.parse().unwrap())
        };
        ($p: expr, $n: expr, $t: ty) => {
            $p.by_ref().take($n).map(|x| x.parse::<$t>().unwrap())
        };
    }

    #[macro_export]
    macro_rules! take_all {
        ($p: expr) => {
            $p.by_ref().map(|x| x.parse().unwrap())
        };
        ($p: expr, $t: ty) => {
            $p.by_ref().map(|x| x.parse::<$t>().unwrap())
        };
    }
}

use cp::*;

fn main() {
    let content = stdin_to_string();
    let mut inp = Parser::new(&content);
    let t: usize = inp.read();
    for _cs in 1..=t {
        let n: usize = inp.read();
        let a = std::iter::once(0)
            .chain(take!(inp, n, i32))
            .collect::<Vec<_>>();
        let sum = a.iter().sum::<i32>();
        if sum % (n as i32) != 0 {
            println!("-1");
        } else {
            println!("{}", n * 3 - 3);
            let avg = sum / (n as i32);
            for i in 2..=n {
                let ii = i as i32;
                let chg = if a[i] % ii == 0 {0} else {ii - a[i] % ii};
                println!("{} {} {}", 1, i, chg);
                println!("{} {} {}", i, 1, (a[i] + chg) / ii);
            }
            for i in 2..=n {
                println!("{} {} {}", 1, i, avg);
            }
        }
    }
}


// ---------- begin scannner ----------
#[allow(dead_code)]
mod scanner {
    use std::str::FromStr;
    use std::str::SplitWhitespace;
    use std::io::Read;
    use std;
    pub struct Scanner<'a> {
        it: SplitWhitespace<'a>
    }
    impl<'a> Scanner<'a> {
        pub fn new(s: &'a String) -> Scanner<'a> {
            Scanner {
                it: s.split_whitespace()
            }
        }
        pub fn next<T: FromStr>(&mut self) -> T {
            match self.it.next().unwrap().parse::<T>() {
                Ok(v) => v,
                _ => panic!("Scanner error")
            }
        }
        pub fn next_chars(&mut self) -> Vec<char> {
            self.next::<String>().chars().collect()
        }
        pub fn next_vec<T: FromStr>(&mut self, len: usize) -> Vec<T> {
            (0..len).map(|_| self.next()).collect()
        }
    }
    pub fn read_string() -> String {
        let mut s = String::new();
        std::io::stdin().read_to_string(&mut s).unwrap();
        s
    }
}
// ---------- end scannner ----------

use std::io::Write;

fn main() {
    let sc = scanner::read_string();
    let mut sc = scanner::Scanner::new(&sc);
    let out = std::io::stdout();
    let mut out = std::io::BufWriter::new(out.lock());
    run(&mut sc, &mut out);
}

fn run(sc: &mut scanner::Scanner, out: &mut std::io::BufWriter<std::io::StdoutLock>) {
    let t: usize = sc.next();
    for _ in 0..t {
        let n: usize = sc.next();
        let mut a: Vec<i64> = sc.next_vec(n);
        a.insert(0, 0);
        let mut b = a.clone();
        let sum = a.iter().sum::<i64>();
        if sum % n as i64 != 0 {
            writeln!(out, "-1").ok();
            continue;
        }
        let mut ans = vec![];
        for i in 2..=n {
            let k = i as i64;
            if a[i] % k != 0 {
                let req = k - a[i] % k;
                ans.push((1, i, req));
                a[1] -= req;
                a[i] += req;
                assert!(a[1] >= 0);
            }
            assert!(a[i] % k == 0);
            let v = a[i] / k;
            ans.push((i, 1, v));
            a[i] -= k * v;
            a[1] += k * v;
        }
        let ave = sum / n as i64;
        for i in 2..=n {
            ans.push((1, i, ave));
            a[1] -= ave;
            a[i] += ave;
        }
        writeln!(out, "{}", ans.len()).ok();
        for (i, j, x) in ans {
            b[i] -= x * i as i64;
            b[j] += x * i as i64;
            assert!(b[i] >= 0 && b[j] >= 0);
            writeln!(out, "{} {} {}", i, j, x).ok();
        }
        assert!(b.iter().skip(1).all(|a| *a == ave));
    }
}


use std::cmp::*;
use std::collections::*;
use std::io::*;
use std::str::*;

// scanner from https://codeforces.com/contest/1396/submission/91365784
struct Scanner {
    stdin: Stdin,
    buffer: VecDeque<String>,
}
#[allow(dead_code)]
impl Scanner {
    fn new() -> Self {
        Scanner {
            stdin: stdin(),
            buffer: VecDeque::new(),
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.is_empty() {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
    fn chars(&mut self) -> Vec<char> {
        self.cin::<String>().chars().collect()
    }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.cin()).collect()
    }
    fn u(&mut self) -> usize {
        self.cin()
    }
    fn ll(&mut self) -> i64 {
        self.cin()
    }
    fn ull(&mut self) -> u64 {
        self.cin()
    }
    fn vecu(&mut self, n: usize) -> Vec<usize> {
        self.vec(n)
    }
    fn vecll(&mut self, n: usize) -> Vec<i64> {
        self.vec(n)
    }
}

//
// ModInt
//

const M: i64 = 1000_000_007;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct ModInt {
    val: i64,
}
#[allow(dead_code)]
const M0: ModInt = ModInt { val: 0 };
const M1: ModInt = ModInt { val: 1 };
//const M_ERROR: ModInt = ModInt { val: -1 };

impl ModInt {
    fn new(v: i64) -> ModInt {
        ModInt {
            val: ModInt::val_from_i64(v),
        }
    }
    #[allow(dead_code)]
    fn new_raw(v: i64) -> ModInt {
        ModInt { val: v }
    }
    fn val_from_i64(v: i64) -> i64 {
        let t = v % M;
        if t < 0 {
            t + M
        } else {
            t
        }
    }
    fn val_from_addval(t: i64) -> i64 {
        if t >= M {
            t - M
        } else {
            t
        }
    }

    fn pow(self, exp: i64) -> ModInt {
        if exp == 0 {
            M1
        } else {
            let x = self.pow(exp / 2);
            if exp % 2 == 0 {
                x * x
            } else {
                self * x * x
            }
        }
    }

    fn inv(self) -> ModInt {
        self.pow(M - 2)
    }
}

impl std::ops::Add for ModInt {
    type Output = ModInt;
    fn add(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: ModInt::val_from_addval(self.val + rhs.val),
        }
    }
}
impl std::ops::Add<i64> for ModInt {
    type Output = ModInt;
    fn add(self, rhs: i64) -> ModInt {
        ModInt {
            val: ModInt::val_from_i64(self.val + rhs),
        }
    }
}
impl std::ops::AddAssign for ModInt {
    fn add_assign(&mut self, other: ModInt) {
        self.val = ModInt::val_from_addval(self.val + other.val);
    }
}
impl std::ops::AddAssign<i64> for ModInt {
    fn add_assign(&mut self, other: i64) {
        self.val = ModInt::val_from_i64(self.val + other);
    }
}

impl std::ops::Sub for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: ModInt::val_from_addval(self.val - rhs.val + M),
        }
    }
}
impl std::ops::Sub<i64> for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: i64) -> ModInt {
        self - ModInt::new(rhs)
    }
}
impl std::ops::SubAssign for ModInt {
    fn sub_assign(&mut self, other: ModInt) {
        self.val = ModInt::val_from_addval(self.val - other.val + M);
    }
}
impl std::ops::SubAssign<i64> for ModInt {
    fn sub_assign(&mut self, other: i64) {
        self.val = ModInt::val_from_i64(self.val - other);
    }
}

impl std::ops::Neg for ModInt {
    type Output = ModInt;
    fn neg(self) -> ModInt {
        ModInt {
            val: if self.val == 0 { 0 } else { M - self.val },
        }
    }
}

impl std::ops::Mul for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: self.val * rhs.val % M,
        }
    }
}
impl std::ops::Mul<i64> for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: i64) -> ModInt {
        self * ModInt::new(rhs)
    }
}
impl std::ops::MulAssign for ModInt {
    fn mul_assign(&mut self, other: ModInt) {
        self.val = self.val * other.val % M;
    }
}
impl std::ops::MulAssign<i64> for ModInt {
    fn mul_assign(&mut self, other: i64) {
        self.mul_assign(ModInt::new(other));
    }
}

impl std::ops::Div for ModInt {
    type Output = ModInt;
    fn div(self, rhs: ModInt) -> ModInt {
        self * rhs.inv()
    }
}
impl std::ops::Div<i64> for ModInt {
    type Output = ModInt;
    fn div(self, rhs: i64) -> ModInt {
        self / ModInt::new(rhs)
    }
}

impl std::fmt::Display for ModInt {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // '
        write!(f, "{}", self.val)
    }
}

#[derive(Clone, Debug, Default)]
struct Solver {}

impl Solver {
    fn solve(&mut self, scan: &mut Scanner, out: &mut BufWriter<Stdout>) {
        //1416b
        let n = scan.u();
        let mut a = scan.vecu(n);
        a.insert(0, 0);

        let mut ans = Vec::with_capacity(n * 3);

        let sum: usize = a.iter().sum();
        if sum % n != 0 {
            writeln!(out, "{} ", -1).ok();
            return;
        }
        let avg = sum / n;

        for i in 2..=n {
            let rem = a[i] % i;
            let x = (i - rem) % i;
            ans.push((1, i, x));
            a[1] -= x;
            a[i] += x;
            assert!( a[i] % i == 0 );

            let x = a[i] / i;
            ans.push((i, 1, x));
            a[i] -= x * i;
            a[1] += x * i;
        }

        for i in 2..=n {
            ans.push((1, i, avg));
            a[1] -= avg;
            a[i] += avg;
        }

        writeln!(out, "{}", ans.len()).ok();
        for (i, j, x) in ans {
            writeln!(out, "{} {} {}", i, j, x).ok();
        }
    }
}

fn solve() {
    let mut scan = Scanner::new();
    let out = &mut BufWriter::new(stdout());

    //let testcase = 1;
    let testcase: usize = scan.cin();
    for _ in 0..testcase {
        let mut s: Solver = Default::default();
        s.solve(&mut scan, out);
    }
}

fn main() {
    let th = std::thread::Builder::new().stack_size(64 * 1024 * 1024);
    th.spawn(|| solve()).unwrap().join().unwrap()
}


use std::cmp::*;
use std::collections::*;
use std::io::*;
use std::str::*;

// scanner from https://codeforces.com/contest/1396/submission/91365784
struct Scanner {
    stdin: Stdin,
    buffer: VecDeque<String>,
}
#[allow(dead_code)]
impl Scanner {
    fn new() -> Self {
        Scanner {
            stdin: stdin(),
            buffer: VecDeque::new(),
        }
    }
    fn cin<T: FromStr>(&mut self) -> T {
        while self.buffer.is_empty() {
            let mut line = String::new();
            let _ = self.stdin.read_line(&mut line);
            for w in line.split_whitespace() {
                self.buffer.push_back(String::from(w));
            }
        }
        self.buffer.pop_front().unwrap().parse::<T>().ok().unwrap()
    }
    fn chars(&mut self) -> Vec<char> {
        self.cin::<String>().chars().collect()
    }
    fn vec<T: FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.cin()).collect()
    }
    fn u(&mut self) -> usize {
        self.cin()
    }
    fn ll(&mut self) -> i64 {
        self.cin()
    }
    fn ull(&mut self) -> u64 {
        self.cin()
    }
    fn vecu(&mut self, n: usize) -> Vec<usize> {
        self.vec(n)
    }
    fn vecll(&mut self, n: usize) -> Vec<i64> {
        self.vec(n)
    }
}

//
// ModInt
//

const M: i64 = 1000_000_007;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
struct ModInt {
    val: i64,
}
#[allow(dead_code)]
const M0: ModInt = ModInt { val: 0 };
const M1: ModInt = ModInt { val: 1 };
//const M_ERROR: ModInt = ModInt { val: -1 };

impl ModInt {
    fn new(v: i64) -> ModInt {
        ModInt {
            val: ModInt::val_from_i64(v),
        }
    }
    #[allow(dead_code)]
    fn new_raw(v: i64) -> ModInt {
        ModInt { val: v }
    }
    fn val_from_i64(v: i64) -> i64 {
        let t = v % M;
        if t < 0 {
            t + M
        } else {
            t
        }
    }
    fn val_from_addval(t: i64) -> i64 {
        if t >= M {
            t - M
        } else {
            t
        }
    }

    fn pow(self, exp: i64) -> ModInt {
        if exp == 0 {
            M1
        } else {
            let x = self.pow(exp / 2);
            if exp % 2 == 0 {
                x * x
            } else {
                self * x * x
            }
        }
    }

    fn inv(self) -> ModInt {
        self.pow(M - 2)
    }
}

impl std::ops::Add for ModInt {
    type Output = ModInt;
    fn add(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: ModInt::val_from_addval(self.val + rhs.val),
        }
    }
}
impl std::ops::Add<i64> for ModInt {
    type Output = ModInt;
    fn add(self, rhs: i64) -> ModInt {
        ModInt {
            val: ModInt::val_from_i64(self.val + rhs),
        }
    }
}
impl std::ops::AddAssign for ModInt {
    fn add_assign(&mut self, other: ModInt) {
        self.val = ModInt::val_from_addval(self.val + other.val);
    }
}
impl std::ops::AddAssign<i64> for ModInt {
    fn add_assign(&mut self, other: i64) {
        self.val = ModInt::val_from_i64(self.val + other);
    }
}

impl std::ops::Sub for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: ModInt::val_from_addval(self.val - rhs.val + M),
        }
    }
}
impl std::ops::Sub<i64> for ModInt {
    type Output = ModInt;
    fn sub(self, rhs: i64) -> ModInt {
        self - ModInt::new(rhs)
    }
}
impl std::ops::SubAssign for ModInt {
    fn sub_assign(&mut self, other: ModInt) {
        self.val = ModInt::val_from_addval(self.val - other.val + M);
    }
}
impl std::ops::SubAssign<i64> for ModInt {
    fn sub_assign(&mut self, other: i64) {
        self.val = ModInt::val_from_i64(self.val - other);
    }
}

impl std::ops::Neg for ModInt {
    type Output = ModInt;
    fn neg(self) -> ModInt {
        ModInt {
            val: if self.val == 0 { 0 } else { M - self.val },
        }
    }
}

impl std::ops::Mul for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: ModInt) -> ModInt {
        ModInt {
            val: self.val * rhs.val % M,
        }
    }
}
impl std::ops::Mul<i64> for ModInt {
    type Output = ModInt;
    fn mul(self, rhs: i64) -> ModInt {
        self * ModInt::new(rhs)
    }
}
impl std::ops::MulAssign for ModInt {
    fn mul_assign(&mut self, other: ModInt) {
        self.val = self.val * other.val % M;
    }
}
impl std::ops::MulAssign<i64> for ModInt {
    fn mul_assign(&mut self, other: i64) {
        self.mul_assign(ModInt::new(other));
    }
}

impl std::ops::Div for ModInt {
    type Output = ModInt;
    fn div(self, rhs: ModInt) -> ModInt {
        self * rhs.inv()
    }
}
impl std::ops::Div<i64> for ModInt {
    type Output = ModInt;
    fn div(self, rhs: i64) -> ModInt {
        self / ModInt::new(rhs)
    }
}

impl std::fmt::Display for ModInt {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        // '
        write!(f, "{}", self.val)
    }
}

#[derive(Clone, Debug, Default)]
struct Solver {}

impl Solver {
    fn solve(&mut self, scan: &mut Scanner, out: &mut BufWriter<Stdout>) {
        //1416b
        let n = scan.u();
        let mut a = scan.vecu(n);
        a.insert(0, 0);

        let mut ans = Vec::with_capacity(n * 3);

        let sum: usize = a.iter().sum();
        if sum % n != 0 {
            writeln!(out, "{} ", -1).ok();
            return;
        }
        let avg = sum / n;

        for i in 2..=n {
            let x = a[i] / i;
            a[i] -= x * i;
            a[1] += x * i;
            ans.push((i, 1, x));
        }

        for i in 2..=n {
            if a[i] > avg {
                // a[i] に x を足してから i を引いて avg にする必要がある
                // a[i]+x-i=avg
                let x = avg + i - a[i];
                if a[1] < x {
                    writeln!(out, "{} ", -1).ok();
                    return;
                }
                a[1] -= x;
                a[i] += x;
                ans.push((1, i, x));

                let x = 1;
                a[i] -= x * i;
                a[1] += x * i;
                ans.push((i, 1, x));
            }
        }
        for i in 2..=n {
            if a[i] < avg {
                let x = avg - a[i];
                a[1] -= x;
                a[i] += x;
                ans.push((1, i, x));
            }
        }

        writeln!(out, "{}", ans.len()).ok();
        for (i, j, x) in ans {
            writeln!(out, "{} {} {}", i, j, x).ok();
        }
    }
}

fn solve() {
    let mut scan = Scanner::new();
    let out = &mut BufWriter::new(stdout());

    //let testcase = 1;
    let testcase: usize = scan.cin();
    for _ in 0..testcase {
        let mut s: Solver = Default::default();
        s.solve(&mut scan, out);
    }
}

fn main() {
    let th = std::thread::Builder::new().stack_size(64 * 1024 * 1024);
    th.spawn(|| solve()).unwrap().join().unwrap()
}


//#include <bits/stdc++.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<map>
#include<sstream>
#define ll long lo`ng
#define LL long long
#define inf 1000000000
#define iosfalse ios::sync_with_stdio(false);
#define lowbit(x) x&-x
using namespace std;

///0224cf2
///E 栈
struct Ri
{
int a,b,h;
}ri[100005];
int cmp(Ri a,Ri b)
{
    if(a.b!=b.b)
        return a.b>b.b;
    else if(a.a!=b.a)
        return a.a>b.a;
    return a.h<=b.h;
}
stack<Ri>st;
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>ri[i].a>>ri[i].b>>ri[i].h;
    sort(ri,ri+n,cmp);
    long long  ans=0,sum=0;
    for(int i=0;i<n;i++)
    {
        while(1)
        {
            if(st.empty())
                break;
            if(ri[i].b>st.top().a)
                break;
            sum-=st.top().h;
            st.pop();
        }
        st.push(ri[i]);
        sum+=ri[i].h;
        ans=max(ans,sum);
    }
    cout<<ans<<endl;
    return 0;
}


//#include <bits/stdc++.h>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<vector>
#include<map>
#include<sstream>
#define ll long long
#define LL long long
#define inf 1000000000
#define iosfalse ios::sync_with_stdio(false);
#define lowbit(x) x&-x
using namespace std;

///0224cf2
///E
struct Ring{
int b;
int as,ab;
int h;
Ring()
{
    b=ab=h=0;
    as=1e9;
}
}ring[100005];
struct Ri
{
int a,b,h;
}ri[100005];
int cmp(Ri a,Ri b)
{
    if(a.b!=b.b)
        return a.b>b.b;
    else if(a.a!=b.a)
        return a.a<b.a;
    return a.h<=b.h;
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>ri[i].a>>ri[i].b>>ri[i].h;
    sort(ri,ri+n,cmp);
    /*int num_ring=0;
    for(int i=0;i<n;i++)
    {
        ring[num_ring].b=ri[i].b;
        ring[num_ring].ab=max(ring[num_ring].ab,ri[i].a);
        ring[num_ring].as=min(ring[num_ring].ab,ri[i].a);
        ring[num_ring].h+=ri[i].h;
        if(i+1<n&&ri[i].b!=ri[i+1].b)
            num_ring++;
    }*/
    stack<Ri>st;
    ll ans=0,sum=0;
    for(int i=0;i<n;i++)
    {
        while(1)
        {
            if(st.empty())
                break;
            if(ri[i].b>st.top().a&&ri[i].b<=st.top().b)
                break;
            sum-=st.top().h;
            st.pop();
        }
        st.push(ri[i]);
        sum+=ri[i].h;
        ans=max(ans,sum);
    }
    cout<<ans<<endl;
    return 0;
}