human
Write me a the Python program you requested given the following:
After a hard-working week Polycarp prefers to have fun. Polycarp's favorite entertainment is drawing snakes. He takes a rectangular checkered sheet of paper of size n × m (where n is the number of rows, m is the number of columns) and starts to draw snakes in cells.

Polycarp draws snakes with lowercase Latin letters. He always draws the first snake with the symbol 'a', the second snake with the symbol 'b', the third snake with the symbol 'c' and so on. All snakes have their own unique symbol. There are only 26 letters in the Latin alphabet, Polycarp is very tired and he doesn't want to invent new symbols, so the total number of drawn snakes doesn't exceed 26.

Since by the end of the week Polycarp is very tired, he draws snakes as straight lines without bends. So each snake is positioned either vertically or horizontally. Width of any snake equals 1, i.e. each snake has size either 1 × l or l × 1, where l is snake's length. Note that snakes can't bend.

When Polycarp draws a new snake, he can use already occupied cells for drawing the snake. In this situation, he draws the snake "over the top" and overwrites the previous value in the cell.

Recently when Polycarp was at work he found a checkered sheet of paper with Latin letters. He wants to know if it is possible to get this sheet of paper from an empty sheet by drawing some snakes according to the rules described above. If it is possible, he is interested in a way to draw snakes.

Input

The first line of the input contains one integer t (1 ≤ t ≤ 10^5) — the number of test cases to solve. Then t test cases follow.

The first line of the test case description contains two integers n, m (1 ≤ n,m ≤ 2000) — length and width of the checkered sheet of paper respectively.

Next n lines of test case description contain m symbols, which are responsible for the content of the corresponding cell on the sheet. It can be either lowercase Latin letter or symbol dot ('.'), which stands for an empty cell.

It is guaranteed that the total area of all sheets in one test...
assistant
#Here is the Python program you requested.

# I stole this code from a stupid birb
from collections import defaultdict as di

def solve():
    n,m = map(int,input().split())
    B = [input().rstrip() for _ in range(n)]

    pos = di(list)
    for i in range(n):
        b = B[i]
        for j in range(m):
            pos[b[j]].append((i,j))
    if '.' in pos:
        del pos['.']

    C = [list('.'*m) for _ in range(n)]
    moves = []

    if pos:
        mxx = max(pos)
        for i in range(97,ord(mxx)+1):
            c = chr(i)
            if c not in pos:
                pos[c] = pos[mxx]
            P = pos[c]
            if all(p[0] == P[0][0] for p in P):
                mn = min(p[1] for p in P)
                mx = max(p[1] for p in P)
                i = P[0][0]
                for j in range(mn,mx+1):
                    C[i][j] = c
                moves.append((i+1,mn+1,i+1,mx+1))
            elif all(p[1] == P[0][1] for p in P):
                mn = min(p[0] for p in P)
                mx = max(p[0] for p in P)
                j = P[0][1]
                for i in range(mn,mx+1):
                    C[i][j] = c
                moves.append((mn+1,j+1,mx+1,j+1))
    
    if [''.join(s) for s in C] == B:
        print('YES')
        print(len(moves))
        for m in moves:
            print(*m)
    else:
        print('NO')

def main():
    t = int(input())

    for _ in range(t):
        solve()

######## Python 2 and 3 footer by Pajenegod and c1729

# Note because cf runs old PyPy3 version which doesn't have the sped up
# unicode strings, PyPy3 strings will many times be slower than pypy2.
# There is a way to get around this by using binary strings in PyPy3
# but its syntax is different which makes it kind of a mess to use.

# So on cf, use PyPy2 for best string performance.

py2 = round(0.5)
if py2:
    from future_builtins import ascii, filter, hex, map, oct, zip
    range = xrange

import os, sys
from io import IOBase, BytesIO

BUFSIZE = 8192
class FastIO(BytesIO):
    newlines = 0

    def __init__(self, file):
        self._file = file
...