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)
         | not downSide   = 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 = incCoin 1 (y2, x2) $ incCoin (-1) (y1, x1) xss   
 where incCoin n (y, x) xss = pre ++ (pre' ++ (c1+n) : suc') : suc
        where (pre, l1:suc) = splitAt y xss
              (pre', c1:suc') = splitAt x l1

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