from collections import deque
class maxflow():
    def __init__(self, n):
        self.pos = []
        self.g = [[] for _ in range(n)]
        self.n = n
        self.cap = {}
   
    def add_edge(self, v, w, cap):
        e1 = [w, 0, cap]
        e2 = [v, e1, 0]
        e1[1] = e2
        self.g[v].append(e1)
        self.g[w].append(e2)
        self.cap[(v, w)] = [cap, e1]
    
    def bfs(self, s, t):
        L = [-1] * self.n
        L[s] = 0
        Q = deque([s])
        while Q:
            v = Q.popleft()
            for w, _, cap in self.g[v]:
                if cap == 0 or L[w] >= 0: continue
                L[w] = L[v] + 1
                if w == t:
                    self.L = L
                    return
                Q.append(w)
        self.L = L

    def dfs(self, s, v, up):
        if v == s: return up
        res = 0
        lv = self.L[v]
        for i in range(self.it[v], len(self.g[v])):
            w, rev, cap = self.g[v][i]
            if lv > self.L[w] and rev[2] > 0:
                d = self.dfs(s, w, min(up - res, rev[2]))
                if d > 0: 
                    self.g[v][i][2] += d
                    rev[2] -= d
                    res += d
                    if res == up: break
            self.it[v] += 1
        return res
    
    def flow(self, s, t, flow_limit = -1):
        if flow_limit < 0: flow_limit = 10 ** 100
        
        flow = 0
        while flow < flow_limit:
            self.bfs(s, t)
            if self.L[t] == -1: break
            self.it = [0] * self.n
            while flow < flow_limit:
                f = self.dfs(s, t, flow_limit - flow)
                if not f: break
                flow += f
        return flow, self.g
    
    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
    
    def flow_all(self):
        L = []
        for a in self.cap:
            v, w = a
            c, e = self.cap[a]
            L.append((v, w, c - e[2]))
        return L


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, g = mf.flow(s, t)
for v, w, f in mf.flow_all():
    if max(v, w) >= N * M or not f: continue
    vi, vj = v // M, v % M
    wi, wj = w // M, w % M
    if v > w:
        vi, vj, wi, wj = wi, wj, vi, vj
    if vi == wi:
        A[vi][vj] = ">"
        A[wi][wj] = "<"
    else:
        A[vi][vj] = "v"
        A[wi][wj] = "^"

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


Measured memory_bytes: 89136