# https://atcoder.jp/contests/practice2/submissions/16598132
# 上記のリンクの提出をいじらせてもらってます。

from collections import deque


class mf_graph:

    # __slots__ = ["N", "graph", "capacities", "level", "it"]

    def __init__(self, N):
        self.N = N
        self.graph = [[] for _ in range(N)]
        self.capacities = [dict() for _ in range(N)]

    def add_edge(self, v, w, cap):
        self.graph[v].append(w)
        self.graph[w].append(v)
        self.capacities[v][w] = cap
        self.capacities[w][v] = 0

    def bfs(self, s, t):
        self.level = [-1] * self.N
        q = deque([s])
        self.level[s] = 0
        while q:
            v = q.popleft()
            if v == t:
                return True
            lw = self.level[v]+1
            for w, cap in self.capacities[v].items():
                if cap and self.level[w] == -1:
                    self.level[w] = lw
                    q.append(w)
        return self.level[t] != -1

    def dfs(self, s, t, up):
        st = [t]
        while st:
            v = st[-1]
            if v == s:
                st.pop()
                flow = up
                for w in st:
                    v = self.graph[w][self.it[w]]
                    flow = min(flow, self.capacities[v][w])
                for w in st:
                    v = self.graph[w][self.it[w]]
                    self.capacities[w][v] += flow
                    self.capacities[v][w] -= flow
                return flow
            lv = self.level[v]
            while self.it[v] < len(self.graph[v]):
                w = self.graph[v][self.it[v]]
                cap = self.capacities[w][v]
                if cap and self.level[w] != -1:
                    if lv > self.level[w]:
                        st.append(w)
                        break
                self.it[v] += 1
            if self.it[v] == len(self.graph[v]):
                st.pop()
                self.level[v] = self.N
        return 0

    def flow(self, s, t, flow_limit=float('inf')):
        flow = 0
        while flow < flow_limit and self.bfs(s, t):
            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

    def min_cut(self, s):
        visited = [False]*self.N
        q = deque([s])
        while q:
            v = q.pop()
            visited[v] = True
            for w, cap in self.capacities[v].items():
                if cap and not visited[w]:
                    q.append(w)


N, M = map(int, input().split())
S = [list(input()) for i in range(N)]
dc = mf_graph(N*M+2)

s = N*M
t = N*M+1
for i in range(N):
    for j in range(M):
        if (i+j) % 2 == 0:
            dc.add_edge(s, M*i+j, 1)
        else:
            dc.add_edge(M*i+j, t, 1)

for i in range(N):
    for j in range(M):
        if j+1 < M and S[i][j] == "." and S[i][j+1] == ".":
            u, v = M*i+j, M*i+j+1
            if (i+j) % 2 == 1:
                u, v = v, u
            dc.add_edge(u, v, 1)
        if i+1 < N and S[i][j] == "." and S[i + 1][j] == ".":
            u, v = M*i+j, M*(i+1)+j
            if (i+j) % 2 == 1:
                u, v = v, u
            dc.add_edge(u, v, 1)

print(dc.flow(s, t))
for u in range(N*M+2):
    ui, uj = divmod(u, M)
    if (ui+uj) % 2 == 1:
        continue
    for v, cap in dc.capacities[u].items():
        if cap != 0:
            continue
        vi, vj = divmod(v, M)
        if u != s and u != t and v != s and v != t:
            if ui+1 == vi:
                S[ui][uj] = "v"
                S[vi][vj] = "^"
            elif ui == vi+1:
                S[ui][uj] = "^"
                S[vi][vj] = "v"
            elif uj+1 == vj:
                S[ui][uj] = ">"
                S[vi][vj] = "<"
            elif uj == vj+1:
                S[ui][uj] = "<"
                S[vi][vj] = ">"

for res in S:
    print("".join(res))


Measured memory_bytes: 77140