← Home
```go
package main

import (
	"bufio"
	"fmt"
	"os"
)

type Op struct {
	x1, y1, x2, y2 int
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	
	scanner.Scan()
	n := atoi(scanner.Text())
	scanner.Scan()
	m := atoi(scanner.Text())
	
	initGrid := make([][]string, n)
	for i := 0; i < n; i++ {
		initGrid[i] = make([]string, m)
		for j := 0; j < m; j++ {
			scanner.Scan()
			initGrid[i][j] = scanner.Text()
		}
	}
	
	finalGrid := make([][]string, n)
	for i := 0; i < n; i++ {
		finalGrid[i] = make([]string, m)
		for j := 0; j < m; j++ {
			scanner.Scan()
			finalGrid[i][j] = scanner.Text()
		}
	}
	
	count0 := make([]int, n)
	count1 := make([]int, n)
	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			s := initGrid[i][j]
			for k := 0; k < len(s); k++ {
				if s[k] == '0' {
					count0[i]++
				} else {
					count1[i]++
				}
			}
		}
	}
	
	var ops []Op
	
	// Phase 1: collect to (1,1) and (1,2)
	// Step 1: columns 3..m to column 1 or 2
	for i := 0; i < n; i++ {
		for j := 2; j < m; j++ {
			s := initGrid[i][j]
			for k := len(s) - 1; k >= 0; k-- {
				if s[k] == '0' {
					ops = append(ops, Op{i + 1, j + 1, i + 1, 1})
				} else {
					ops = append(ops, Op{i + 1, j + 1, i + 1, 2})
				}
			}
		}
	}
	
	// Step 2: column 1 (move 1s to col 2) and column 2 (move 0s to col 1)
	for i := 0; i < n; i++ {
		s := initGrid[i][0]
		for k := len(s) - 1; k >= 0; k-- {
			if s[k] == '1' {
				if i == 0 {
					ops = append(ops, Op{1, 1, 1, 2})
				} else {
					ops = append(ops, Op{i + 1, 1, i + 1, 2})
				}
			}
		}
		s = initGrid[i][1]
		for k := len(s) - 1; k >= 0; k-- {
			if s[k] == '0' {
				if i == 0 {
					ops = append(ops, Op{1, 2, 1, 1})
				} else {
					ops = append(ops, Op{i + 1, 2, i + 1, 1})
				}
			}
		}
	}
	
	// Step 3: rows 2..n to row 1
	for i := n - 1; i >= 1; i-- {
		for k := 0; k < count0[i]; k++ {
			ops = append(ops, Op{i + 1, 1, 1, 1})
		}
		for k := 0; k < count1[i]; k++ {
			ops = append(ops, Op{i + 1, 2, 1, 2})
		}
	}
	
	// Phase 2: distribute to final positions
	for i := 0; i < n; i++ {
		for j := 0; j < m; j++ {
			s := finalGrid[i][j]
			for k := len(s) - 1; k >= 0; k-- {
				c := s[k]
				srcR, srcC := 1, 1
				if c == '1' {
					srcR, srcC = 1, 2
				}
				destR, destC := i+1, j+1
				
				if destR == srcR && destC == srcC {
					continue
				}
				if destR == 1 {
					ops = append(ops, Op{srcR, srcC, 1, destC})
				} else if destC == srcC {
					ops = append(ops, Op{1, srcC, destR, srcC})
				} else {
					ops = append(ops, Op{srcR, srcC, 1, destC})
					ops = append(ops, Op{1, destC, destR, destC})
				}
			}
		}
	}
	
	fmt.Println(len(ops))
	for _, op := range ops {
		fmt.Printf("%d %d %d %d\n", op.x1, op.y1, op.x2, op.y2)
	}
}

func atoi(s string) int {
	n := 0
	for i := 0; i < len(s); i++ {
		n = n*10 + int(s[i]-'0')
	}
	return n
}
```