object Main {
  import java.util.Scanner

  def readStrings(n: Int)(implicit sc: Scanner): Array[String] = Array.fill(n) { sc.next() }
  def readInts(n: Int)(implicit sc: Scanner): Array[Int] = Array.fill(n) { sc.nextInt() }
  def readLongs(n: Int)(implicit sc: Scanner): Array[Long] = Array.fill(n) { sc.nextLong() }
  def readLineStrings(implicit sc: Scanner): Array[String] = sc.nextLine().split(' ')
  def readLineInts(implicit sc: Scanner): Array[Int] = readLineStrings.map(_.toInt)
  def readLineLongs(implicit sc: Scanner): Array[Long] = readLineStrings.map(_.toLong)

  def main(args: Array[String]): Unit = solve(new Scanner(System.in))

  def solve(implicit sc: Scanner): Unit = {
    def adjustRow(row: Seq[Int]): Seq[Int] = row.scanLeft(0){ (a, carry) => (a + carry) % 2 }.drop(1).dropRight(1)

    val Array(h, w) = readLineInts
    val a = Array.fill(h)(readLineInts)
    val b = a.map(row => row.map(aij => if (aij == 0) aij else if (aij % 2 == 0) 2 else 1))
    val moveResults: Seq[(Seq[Int], Int)] = b.map { row =>
      val moves = adjustRow(row)
      (moves, row.last + moves.lastOption.getOrElse(0))
    }
    val rowMoves = moveResults.map(_._1)
    val column = moveResults.map(_._2)
    val columnMoves = adjustRow(column)

    val rowWiseMoves = {
      for((rowMove, rowIndex) <- rowMoves.zipWithIndex;
          (moveFlag, columnIndex) <- rowMove.zipWithIndex;
          move <- Some((rowIndex + 1, columnIndex + 1, rowIndex + 1, columnIndex + 2)) if moveFlag == 1) yield move
    }
    val columnWiseMoves = {
      for ((moveFlag, rowIndex) <- columnMoves.zipWithIndex;
            move <- Some((rowIndex + 1, w, rowIndex + 2, w)) if moveFlag == 1) yield move
    }
    val moves = rowWiseMoves ++ columnWiseMoves

    println(moves.length)
    for ((a, b, c, d) <- moves) println(s"$a $b $c $d")
  }
}
