import Control.Monad.State

data Board = Board (Int, Int) [[Int]]
data Points = Points Int Int Int Int

maxEven :: Int -> Int -> State (Board, [Points]) [Points]
maxEven h w = do
  (Board (y, x) xss, mvs) <- get
  let rightSide = (x == w-1)
      downSide  = (y == h-1) 
  if rightSide && downSide then return mvs
  else do
    let mv
         | not rightSide  = Points y x y (x+1)
         | otherwise      = Points y x (y+1) x
        newPoint
         | rightSide  = (y+1, 0) 
         | otherwise  = (y, x+1)
    if odd (xss !! y !! x) then
      put $ (Board newPoint (moveCoin mv xss), mvs ++ [mv])
    else
      put $ (Board newPoint xss, mvs)
    maxEven h w
    
moveCoin :: Points -> [[Int]] -> [[Int]]
moveCoin (Points y1 x1 y2 x2) xss = shift (y1 == y2)   
 where shift bool
        | bool       = pre1 ++ (pre2 ++ (c1-1):(c1'+1):suc2') : suc1
        | otherwise  = pre1 ++ (pre2 ++ (c1-1):suc2) : (pre3 ++ (c2+1):suc3) : suc1'
        where (pre1, l:suc1@(l':suc1'))    = splitAt y1 xss
              (pre2, c1:suc2@(c1':suc2'))  = splitAt x1 l
              (pre3, c2:suc3)              = splitAt x1 l'

main = do
  [h, w] <- (map read).words <$> getLine
  cells <- (map $ (map read).words).lines <$> getContents
  let rslt = evalState (maxEven h w) (Board (0, 0) cells, [])
      ans = [[y1+1, x1+1, y2+1, x2+1] | Points y1 x1 y2 x2 <- rslt]
  print $ length ans
  putStrLn $ unlines $ map (unwords.(map show)) ans