import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int j = 0; j < m-2; j++) {
                    for (int i = 0; i < n; i++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                            A[i][j+1] = flip(A[i][j+1]);
                            A[r1][j+1] = flip(A[r1][j+1]);
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    void apply(char[][] A, List<int[]> ops) {
        for (int[] op : ops) {
            for (int i = 0; i < 6; i += 2) {
                A[op[i]-1][op[i+1]-1] = flip(A[op[i]-1][op[i+1]-1]);
            }
        }
    }

    char flip(char c) {
        return c == '0' ? '1' : '0';
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m-2; j++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += n-2;
                    op[3] += n-2;
                    op[5] += n-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int j = 0; j < m-2; j++) {
                    for (int i = 0; i < n; i++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                            A[i][j+1] = flip(A[i][j+1]);
                            A[r1][j+1] = flip(A[r1][j+1]);
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    void apply(char[][] A, List<int[]> ops) {
        for (int[] op : ops) {
            for (int i = 0; i < 6; i += 2) {
                A[op[i]-1][op[i+1]-1] = flip(A[op[i]-1][op[i+1]-1]);
            }
        }
    }

    char flip(char c) {
        return c == '0' ? '1' : '0';
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (At[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            At[i+1][j] = flip(At[i+1][j]);
                            At[i+1][c1] = flip(At[i+1][c1]);
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int j = 0; j < m-2; j++) {
                    for (int i = 0; i < n; i++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                            A[i][j+1] = flip(A[i][j+1]);
                            A[r1][j+1] = flip(A[r1][j+1]);
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                            left[i+1][j] = flip(left[i+1][j]);
                            left[i+1][c1] = flip(left[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    void apply(char[][] A, List<int[]> ops) {
        for (int[] op : ops) {
            for (int i = 0; i < 6; i += 2) {
                A[op[i]-1][op[i+1]-1] = flip(A[op[i]-1][op[i+1]-1]);
            }
        }
    }

    char flip(char c) {
        return c == '0' ? '1' : '0';
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int j = 0; j < m-2; j++) {
                    for (int i = 0; i < n; i++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                            A[i][j+1] = flip(A[i][j+1]);
                            A[r1][j+1] = flip(A[r1][j+1]);
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                            left[i+1][j] = flip(left[i+1][j]);
                            left[i+1][c1] = flip(left[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    void apply(char[][] A, List<int[]> ops) {
        for (int[] op : ops) {
            for (int i = 0; i < 6; i += 2) {
                A[op[i]-1][op[i+1]-1] = flip(A[op[i]-1][op[i+1]-1]);
            }
        }
    }

    char flip(char c) {
        return c == '0' ? '1' : '0';
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int j = 0; j < m-2; j++) {
                    for (int i = 0; i < n; i++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    void apply(char[][] A, List<int[]> ops) {
        for (int[] op : ops) {
            for (int i = 0; i < 6; i += 2) {
                A[op[i]-1][op[i+1]-1] = flip(A[op[i]-1][op[i+1]-1]);
            }
        }
    }

    char flip(char c) {
        return c == '0' ? '1' : '0';
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m-2; j++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            A[i+1][j] = flip(A[i+1][j]);
                            A[i+1][c1] = flip(A[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (At[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                            At[i+1][j] = flip(At[i+1][j]);
                            At[i+1][c1] = flip(At[i+1][c1]);
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int j = 0; j < m-2; j++) {
                    for (int i = 0; i < n; i++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                            A[i][j+1] = flip(A[i][j+1]);
                            A[r1][j+1] = flip(A[r1][j+1]);
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                            left[i+1][j] = flip(left[i+1][j]);
                            left[i+1][c1] = flip(left[i+1][c1]);
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    for (int z = 0; z < 6; z++) op[z]++;
                    op[1] += m-2;
                    op[3] += m-2;
                    op[5] += m-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 4) return;
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    void apply(char[][] A, List<int[]> ops) {
        for (int[] op : ops) {
            for (int i = 0; i < 6; i += 2) {
                A[op[i]-1][op[i+1]-1] = flip(A[op[i]-1][op[i+1]-1]);
            }
        }
    }

    char flip(char c) {
        return c == '0' ? '1' : '0';
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {
    static int MOD = 1000000007;

    // After writing solution, quick scan for:
    //   array out of bounds
    //   special cases e.g. n=1?
    //
    // Big numbers arithmetic bugs:
    //   int overflow
    //   sorting, or taking max, after MOD
    void solve() throws IOException {
        int T = ri();
        for (int Ti = 0; Ti < T; Ti++) {
            int[] nm = ril(2);
            int n = nm[0];
            int m = nm[1];
            char[][] A = new char[n][];
            for (int i = 0; i < n; i++) A[i] = rs();

            List<int[]> ops = new ArrayList<>();
            if (n % 2 == 0 && m % 2 == 0) {
                for (int i = 0; i < n; i += 2) {
                    for (int j = 0; j < m; j += 2) {
                        solve(ops, A, i, j);
                    }
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 1 && m % 2 == 0) {
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < m; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < m ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < m; j += 2) {
                    solve(ops, A, i, j);
                }
                pw.println(ops.size());
                for (int[] op : ops) {
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            } else if (n % 2 == 0 && m % 2 == 1) {
                char[][] At = new char[m][n];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m; j++) {
                        At[j][i] = A[i][j];
                    }
                }

                // Copy Paste
                for (int i = 0; i < m-2; i++) {
                    for (int j = 0; j < n; j++) {
                        if (A[i][j] != '0') {
                            int c1 = j+1 < n ? j+1 : j-1;
                            ops.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = m-2;
                for (int j = 0; j < n; j += 2) {
                    solve(ops, At, i, j);
                }
                // End Copy Paste

                pw.println(ops.size());
                for (int[] op : ops) {
                    pw.println(op[1] + " " + op[0] + " " + op[3] + " " + op[2] + " " + op[5] + " " + op[4]);
                }
            } else {
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < m-2; j++) {
                        if (A[i][j] != '0') {
                            int r1 = i+1 < n ? i+1 : i-1;
                            ops.add(new int[]{i, j, i, j+1, r1, j+1});
                        }
                    }
                }

                // We are left with a ODDx2 to solve
                char[][] left = new char[n][2];
                for (int i = 0; i < n; i++) {
                    for (int j = 0; j < 2; j++) {
                        left[i][j] = A[i][m-2+j];
                    }
                }

                List<int[]> ops2 = new ArrayList<>();
                for (int i = 0; i < n-2; i++) {
                    for (int j = 0; j < 2; j++) {
                        if (left[i][j] != '0') {
                            int c1 = j+1 < 2 ? j+1 : j-1;
                            ops2.add(new int[]{i, j, i+1, j, i+1, c1});
                        }
                    }
                }
                int i = n-2;
                for (int j = 0; j < 2; j += 2) {
                    solve(ops2, left, i, j);
                }
                pw.println(ops.size() + ops2.size());
                for (int[] op : ops) {
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
                for (int[] op : ops2) {
                    op[1] += n-2;
                    op[3] += n-2;
                    op[5] += n-2;
                    for (int x : op) {
                        pw.print(x + " ");
                    }
                    pw.println();
                }
            }
        }
    }

    void solve(List<int[]> ops, char[][] A, int i, int j) {
        List<int[]> z = new ArrayList<>();
        List<int[]> o = new ArrayList<>();
        for (int a = i; a <= i+1; a++) {
            for (int b = j; b <= j+1; b++) {
                if (A[a][b] == '0') z.add(new int[]{a, b});
                else o.add(new int[]{a, b});
            }
        }
        if (z.size() == 3) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(2)[0], z.get(2)[1], z.get(0)[0], z.get(0)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], z.get(1)[0], z.get(1)[1], z.get(2)[0], z.get(2)[1]});
        } else if (z.size() == 2) {
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(0)[0], o.get(0)[1]});
            ops.add(new int[]{z.get(0)[0], z.get(0)[1], z.get(1)[0], z.get(1)[1], o.get(1)[0], o.get(1)[1]});
        } else if (z.size() == 1) {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
        } else {
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1]});
            ops.add(new int[]{o.get(1)[0], o.get(1)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(3)[0], o.get(3)[1], o.get(1)[0], o.get(1)[1]});
            ops.add(new int[]{o.get(0)[0], o.get(0)[1], o.get(2)[0], o.get(2)[1], o.get(3)[0], o.get(3)[1]});
        }
    }

    // Template code below

    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    PrintWriter pw = new PrintWriter(System.out);

    public static void main(String[] args) throws IOException {
        Main m = new Main();
        m.solve();
        m.close();
    }

    void close() throws IOException {
        pw.flush();
        pw.close();
        br.close();
    }

    int ri() throws IOException {
        return Integer.parseInt(br.readLine().trim());
    }

    long rl() throws IOException {
        return Long.parseLong(br.readLine().trim());
    }

    int[] ril(int n) throws IOException {
        int[] nums = new int[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            int x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    long[] rll(int n) throws IOException {
        long[] nums = new long[n];
        int c = 0;
        for (int i = 0; i < n; i++) {
            int sign = 1;
            c = br.read();
            long x = 0;
            if (c == '-') {
                sign = -1;
                c = br.read();
            }
            while (c >= '0' && c <= '9') {
                x = x * 10 + c - '0';
                c = br.read();
            }
            nums[i] = x * sign;
        }
        while (c != '\n' && c != -1) c = br.read();
        return nums;
    }

    int[] rkil() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return ril(x);
    }

    long[] rkll() throws IOException {
        int sign = 1;
        int c = br.read();
        int x = 0;
        if (c == '-') {
            sign = -1;
            c = br.read();
        }
        while (c >= '0' && c <= '9') {
            x = x * 10 + c - '0';
            c = br.read();
        }
        return rll(x);
    }

    char[] rs() throws IOException {
        return br.readLine().toCharArray();
    }

    void sort(int[] A) {
        Random r = new Random();
        for (int i = A.length-1; i > 0; i--) {
            int j = r.nextInt(i+1);
            int temp = A[i];
            A[i] = A[j];
            A[j] = temp;
        }
        Arrays.sort(A);
    }

    void printDouble(double d) {
        pw.printf("%.16f", d);
    }
}


import java.util.*;
import java.lang.*;
import java.io.*;

public class Main
{
	PrintWriter out = new PrintWriter(System.out);
	BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer tok = new StringTokenizer("");
    String next() throws IOException {
        if (!tok.hasMoreTokens()) { tok = new StringTokenizer(in.readLine()); }
        return tok.nextToken();
    }
    int ni() throws IOException { return Integer.parseInt(next()); }
    long nl() throws IOException { return Long.parseLong(next()); }

    long mod=1000000007;
    ArrayList<Integer>B;
    int[][]A;

    void solve() throws IOException {
        for (int tc=ni();tc>0;tc--) {
            int n=ni(),m=ni();
            A=new int[n][m];
            for (int i=0;i<n;i++) {
                String s=next();
                for (int j=0;j<m;j++) {
                    if (s.charAt(j)=='1') A[i][j]=1;
                }
            }

            /*for (int i=0;i<n;i++) {
                for (int j=0;j<m;j++) out.print(A[i][j]+" ");
                out.println();
            }*/

            B=new ArrayList();

            for (int i=0;i<n-2;i++) {
                int p=0;
                while (p<m) {
                    if (A[i][p]==0) { p++; continue; }
                    if (p<m-1) {
                        go(i,p);
                        p++;
                        if (A[i][p]==0) { go(i+1,p-1); go(i+1,p); }
                        else {
                            go (i,p);
                            if (A[i+1][p-1]==1) go(i+1,p-1);
                            else go(i+1,p);
                        }
                        p++;
                    }
                    else { go(i,p); go(i+1,p-1); go(i+1,p); p++; }
                }
            }

            int p=0;
            int q=n-2;
            int r=n-1;
            while (p<m-2) {
                if (A[r][p]==0 && A[q][p]==0) { p++; continue; }
                if (A[r][p]==1 && A[q][p]==1) {
                    go(q,p);
                    go(r,p);
                    if (A[q][p+1]==1) go (q,p+1);
                    else go (r,p+1);
                }
                else {
                    if (A[q][p]==1) go(q,p);
                    else go(r,p);
                    go(q,p+1);
                    go(r,p+1);
                }
                p++;
            }

            int ct=0;
            ArrayList<Integer>X=new ArrayList();
            ArrayList<Integer>Y=new ArrayList();
            if (A[q][p]==1) { X.add(q); X.add(p); }
            else { Y.add(q); Y.add(p); }
            if (A[r][p]==1) { X.add(r); X.add(p); }
            else { Y.add(r); Y.add(p); }
            p++;
            if (A[q][p]==1) { X.add(q); X.add(p); }
            else { Y.add(q); Y.add(p); }
            if (A[r][p]==1) { X.add(r); X.add(p); }
            else { Y.add(r); Y.add(p); }

            if (X.size()==2) {
                go(X.get(0),X.get(1)); go(Y.get(0),Y.get(1)); go(Y.get(2),Y.get(3));
                go(X.get(0),X.get(1)); go(Y.get(0),Y.get(1)); go(Y.get(4),Y.get(5));
                go(X.get(0),X.get(1)); go(Y.get(4),Y.get(5)); go(Y.get(2),Y.get(3));
            }
            if (X.size()==4) {
                go(X.get(0),X.get(1)); go(Y.get(0),Y.get(1)); go(Y.get(2),Y.get(3));
                go(X.get(2),X.get(3)); go(Y.get(0),Y.get(1)); go(Y.get(2),Y.get(3));
            }
            if (X.size()==6) {
                go(X.get(0),X.get(1)); go(X.get(2),X.get(3)); go(X.get(4),X.get(5));
            }

            out.println(B.size()/6);
            for (int i=0;i<B.size();i+=6) {
                for (int j=0;j<6;j++) out.print(B.get(i+j)+" ");
                out.println();
            }
        }
        out.flush();
    }

    void fin1(int u,int v) {
        go(u,v); go(u-1,v); go(u-1,v+1);
        go(u,v); go(u-1,v+1); go(u,v+1);
        go(u,v); go(u-1,v); go(u,v+1);
    }

    void fin2(int u,int v) {
        go(u,v); go(u-1,v); go(u-1,v-1);
        go(u,v); go(u-1,v-1); go(u,v-1);
        go(u,v); go(u-1,v); go(u,v-1);
    }

    void go(int u,int v) {
        B.add(u+1);
        B.add(v+1);
        if (A[u][v]==1) A[u][v]=0;
        else A[u][v]=1;
    }

    int gcd(int a,int b) { return(b==0?a:gcd(b,a%b)); }
    long gcd(long a,long b) { return(b==0?a:gcd(b,a%b)); }
    long mp(long a,long p) { long r=1; while(p>0) { if ((p&1)==1) r=(r*a)%mod; p>>=1; a=(a*a)%mod; } return r; }

    public static void main(String[] args) throws IOException {
        new Main().solve();
    }
}


import java.util.*;
import java.lang.*;
import java.io.*;

public class Main
{
	PrintWriter out = new PrintWriter(System.out);
	BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer tok = new StringTokenizer("");
    String next() throws IOException {
        if (!tok.hasMoreTokens()) { tok = new StringTokenizer(in.readLine()); }
        return tok.nextToken();
    }
    int ni() throws IOException { return Integer.parseInt(next()); }
    long nl() throws IOException { return Long.parseLong(next()); }

    long mod=1000000007;
    ArrayList<Integer>B;
    int[][]A;

    void solve() throws IOException {
        for (int tc=ni();tc>0;tc--) {
            int n=ni(),m=ni();
            A=new int[n][m];
            for (int i=0;i<n;i++) {
                String s=next();
                for (int j=0;j<m;j++) {
                    if (s.charAt(j)=='1') A[i][j]=1;
                }
            }

            /*for (int i=0;i<n;i++) {
                for (int j=0;j<m;j++) out.print(A[i][j]+" ");
                out.println();
            }*/

            B=new ArrayList();

            for (int i=0;i<n-2;i++) {
                int p=0;
                while (p<m) {
                    if (A[i][p]==0) { p++; continue; }
                    if (p<m-1) {
                        go(i,p);
                        p++;
                        if (A[i][p]==0) { go(i+1,p-1); go(i+1,p); }
                        else {
                            go (i,p);
                            if (A[i+1][p-1]==1) go(i+1,p-1);
                            else go(i+1,p);
                        }
                        p++;
                    }
                    else { go(i,p); go(i+1,p-1); go(i+1,p); p++; }
                }
            }

            int p=0;
            int q=n-2;
            int r=n-1;
            while (p<m-2) {
                if (A[r][p]==0 && A[q][p]==0) { p++; continue; }
                if (A[r][p]==1 && A[q][p]==1) {
                    go(q,p);
                    go(r,p);
                    if (A[q][p+1]==1) go (q,p+1);
                    else go (r,p+1);
                }
                else {
                    if (A[q][p]==1) go(q,p);
                    else go(r,p);
                    go(q,p+1);
                    go(r,p+1);
                }
                p++;
            }

            int ct=0;
            ArrayList<Integer>X=new ArrayList();
            ArrayList<Integer>Y=new ArrayList();
            if (A[q][p]==1) { X.add(q); X.add(p); }
            else { Y.add(q); Y.add(p); }
            if (A[r][p]==1) { X.add(r); X.add(p); }
            else { Y.add(r); Y.add(p); }
            p++;
            if (A[q][p]==1) { X.add(q); X.add(p); }
            else { Y.add(q); Y.add(p); }
            if (A[r][p]==1) { X.add(r); X.add(p); }
            else { Y.add(r); Y.add(p); }

            if (X.size()==2) {
                go(X.get(0),X.get(1)); go(Y.get(0),Y.get(1)); go(Y.get(2),Y.get(3));
                go(X.get(0),X.get(1)); go(Y.get(0),Y.get(1)); go(Y.get(4),Y.get(5));
                go(X.get(0),X.get(1)); go(Y.get(4),Y.get(5)); go(Y.get(2),Y.get(3));
            }
            if (X.size()==4) {
                go(X.get(0),X.get(1)); go(Y.get(0),Y.get(1)); go(Y.get(2),Y.get(3));
                go(X.get(2),X.get(3)); go(Y.get(0),Y.get(1)); go(Y.get(2),Y.get(3));
            }
            if (X.size()==6) {
                go(X.get(0),X.get(1)); go(X.get(2),X.get(3)); go(X.get(4),X.get(5));
            }
            if (X.size()==8) {
                go(X.get(0),X.get(1)); go(X.get(2),X.get(3)); go(X.get(4),X.get(5));
                go(X.get(0),X.get(1)); go(X.get(6),X.get(7)); go(X.get(4),X.get(5));
                go(X.get(0),X.get(1)); go(X.get(2),X.get(3)); go(X.get(6),X.get(7));
                go(X.get(6),X.get(7)); go(X.get(2),X.get(3)); go(X.get(4),X.get(5));
            }

            out.println(B.size()/6);
            for (int i=0;i<B.size();i+=6) {
                for (int j=0;j<6;j++) out.print(B.get(i+j)+" ");
                out.println();
            }
        }
        out.flush();
    }

    void fin1(int u,int v) {
        go(u,v); go(u-1,v); go(u-1,v+1);
        go(u,v); go(u-1,v+1); go(u,v+1);
        go(u,v); go(u-1,v); go(u,v+1);
    }

    void fin2(int u,int v) {
        go(u,v); go(u-1,v); go(u-1,v-1);
        go(u,v); go(u-1,v-1); go(u,v-1);
        go(u,v); go(u-1,v); go(u,v-1);
    }

    void go(int u,int v) {
        B.add(u+1);
        B.add(v+1);
        if (A[u][v]==1) A[u][v]=0;
        else A[u][v]=1;
    }

    int gcd(int a,int b) { return(b==0?a:gcd(b,a%b)); }
    long gcd(long a,long b) { return(b==0?a:gcd(b,a%b)); }
    long mp(long a,long p) { long r=1; while(p>0) { if ((p&1)==1) r=(r*a)%mod; p>>=1; a=(a*a)%mod; } return r; }

    public static void main(String[] args) throws IOException {
        new Main().solve();
    }
}