class maxflow():
    def __init__(self, n):
        self.pos = []
        self.g = [[] for _ in range(n)]
        self.n = n
    
    def add_edge(self, frm, to, cap):
        self.pos.append((frm, len(self.g[frm])))
        self.g[frm].append([to, len(self.g[to]), cap])
        self.g[to].append([frm, len(self.g[frm]) - 1, 0])
        return len(self.pos) - 1
    
    def get_edge(self, i):
        e = self.g[self.pos[i][0]][self.pos[i][1]]
        re = self.g[e[0]][e[1]]
        return (self.pos[i][0], e[0], e[2] + re[2], re[2])
    
    def edges(self):
        return [self.get_edge(i) for i in range(len(self.pos))]
    
    def change_edge(self, i, new_cap, new_flow):
        e = self.g[self.pos[i][0]][self.pos[i][1]]
        re = self.g[e[0]][e[1]]
        e[2] = new_cap - new_flow
        re[2] = new_flow
    
    def flow(self, s, t, flow_limit = -1):
        if flow_limit < 0: flow_limit = 10 ** 100
        it = [0] * self.n
        def bfs():
            L = [-1] * self.n
            L[s] = 0
            Q = [s]
            while Q:
                v = Q.pop()
                for e in self.g[v]:
                    if e[2] == 0 or L[e[0]] >= 0: continue
                    L[e[0]] = L[v] + 1
                    if e[0] == t: return L
                    Q.append(e[0])
            return L
        
        def dfs(v, up):
            if v == s: return up
            res = 0
            lv = L[v]
            for i in range(it[v], len(self.g[v])):
                e = self.g[v][i]
                if lv <= L[e[0]] or self.g[e[0]][e[1]][2] == 0: continue
                
                d = dfs(e[0], min(up - res, self.g[e[0]][e[1]][2]))
                if d <= 0: continue
                self.g[v][i][2] += d
                self.g[e[0]][e[1]][2] -= d
                res += d
                if res == up: break
            return res
        
        flow = 0
        while flow < flow_limit:
            L = bfs()
            if L[t] == -1: break
            it = [0] * self.n
            while flow < flow_limit:
                f = dfs(t, flow_limit - flow)
                if not f: break
                flow += f
        return flow
    
    def min_cut(self, s):
        visited = [0] * self.n
        Q = [s]
        while Q:
            p = Q.pop()
            visited[p] = 1
            for e in self.g[p]:
                if e[2] and visited[e[0]] == 0:
                    visited[e[0]] = 1
                    Q.append(e[0])
        return visited

N, M = map(int, input().split())
mf = maxflow(N * M + 2)
A = [[a for a in input()] for _ in range(N)]
X = [[1 if a == "." else 0 for a in aa] for aa in A]
s = N * M
t = s + 1
for i in range(N):
    for j in range(M):
        if X[i][j]:
            if (i ^ j) & 1 == 0:
                mf.add_edge(s, i * M + j, 1)
            else:
                mf.add_edge(i * M + j, t, 1)

for i in range(N - 1):
    for j in range(M):
        if X[i][j] and X[i+1][j]:
            a = i * M + j
            b = a + M
            if (i ^ j) & 1 == 0:
                mf.add_edge(a, b, 1)
            else:
                mf.add_edge(b, a, 1)
for i in range(N):
    for j in range(M - 1):
        if X[i][j] and X[i][j+1]:
            a = i * M + j
            b = a + 1
            if (i ^ j) & 1 == 0:
                mf.add_edge(a, b, 1)
            else:
                mf.add_edge(b, a, 1)

fl = mf.flow(s, t)
# print("fl =", fl)

# mc = mf.min_cut(s)
# print("mc =", mc)
# print("edges =", mf.edges())

for s, t, _, f in mf.edges():
    if f and max(s, t) < N * M:
        if s > t: s, t = t, s
        i, j = s // M, s % M
        ii, jj = t // M, t % M
        if i == ii:
            A[i][j] = ">"
            A[ii][jj] = "<"
        else:
            A[i][j] = "v"
            A[ii][jj] = "^"

print(fl)
for x in A:
    print("".join(map(str, x)))

Measured memory_bytes: 169664