# -*- coding: utf-8 -*-
# import bisect
# import heapq
# import math
# import random
# from collections import Counter, defaultdict, deque
# from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
# from fractions import Fraction
# from functools import lru_cache, reduce
# from itertools import combinations, combinations_with_replacement, product, permutations, accumulate
# from operator import add, mul, sub, itemgetter, attrgetter
import queue

import sys
# sys.setrecursionlimit(10**6)
# readline = sys.stdin.buffer.readline
readline = sys.stdin.readline

INF = 2**62-1


def read_int():
    return int(readline())


def read_int_n():
    return list(map(int, readline().split()))


def read_float():
    return float(readline())


def read_float_n():
    return list(map(float, readline().split()))


def read_str():
    return readline().strip()


def read_str_n():
    return readline().strip().split()


def ep(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.perf_counter()
        ret = f(*args, **kwargs)
        e = time.perf_counter()

        ep(e - s, 'sec')
        return ret

    return wrap


class Dinic:
    """ 最大流(Dinic)：O(E*V^2) """

    INF = 10**18

    def __init__(self, n):
        self.n = n
        self.links = [[] for _ in range(n)]
        self.depth = None
        self.progress = None
        self.pos = []

    def copy(self):
        res = Dinic(self.n)
        res.links = [[a[:] for a in b] for b in self.links]
        res.pos = [a[:] for a in self.pos]
        return res

    def add_edge(self, _from, to, cap):
        self.pos.append((_from, len(self.links[_from])))
        self.links[_from].append([cap, to, len(self.links[to])])
        self.links[to].append([0, _from, len(self.links[_from]) - 1])

    def bfs(self, s):
        from collections import deque

        depth = [-1] * self.n
        depth[s] = 0
        q = deque([s])
        while q:
            v = q.popleft()
            for cap, to, _ in self.links[v]:
                if cap > 0 and depth[to] < 0:
                    depth[to] = depth[v] + 1
                    q.append(to)
        self.depth = depth

    def dfs(self, v, t, flow):
        if v == t:
            return flow
        links_v = self.links[v]
        for i in range(self.progress[v], len(links_v)):
            self.progress[v] = i
            cap, to, rev = link = links_v[i]
            if cap == 0 or self.depth[v] >= self.depth[to]:
                continue
            d = self.dfs(to, t, min(flow, cap))
            if d == 0:
                continue
            link[0] -= d
            self.links[to][rev][0] += d
            return d
        return 0

    def flow(self, s, t):
        INF = Dinic.INF
        flow = 0
        while True:
            self.bfs(s)
            if self.depth[t] < 0:
                return flow
            self.progress = [0] * self.n
            current_flow = self.dfs(s, t, INF)
            while current_flow > 0:
                flow += current_flow
                current_flow = self.dfs(s, t, INF)

    def get_edge(self, i):
        e = self.links[self.pos[i][0]][self.pos[i][1]]
        re = self.links[e[1]][e[2]]
        # from, to, cap, flow
        return (self.pos[i][0], e[1], e[0]+re[0], re[0])

    def get_edges(self):
        M = len(self.pos)
        res = []
        for i in range(M):
            res.append(self.get_edge(i))
        return res

# class Dinic:
#     def __init__(self, v):
#         self.V = v
#         self.G = [list() for _ in range(v)]
#         self.level = [0 for _ in range(v)]
#         self.iter = [0 for _ in range(v)]
#         self.pos = []

#     def add_edge(self, from_, to, cap):
#         self.pos.append((from_, len(self.G[from_])))
#         # to: 行き先, cap: 容量, rev: 反対側の辺
#         # 0           1          2
#         self.G[from_].append([to, cap, len(self.G[to])])
#         self.G[to].append([from_, 0, len(self.G[from_])-1])


#     def edges(self):
#         es = []
#         for f, t in self.pos:
#             e = self.G[f][t]
#             re = self.G[e[0]][e[2]]
#             # from, to, cap, flow
#             e = [f, e[0], e[1] + re[1], re[1]]
#             es.append(e)
#         return es

#     # sからの最短距離をbfsで計算
#     def bfs(self, s):
#         self.level = [-1 for _ in range(self.V)]
#         self.level[s] = 0
#         que = queue.Queue()
#         que.put(s)
#         while not que.empty():
#             v = que.get()
#             for i in range(len(self.G[v])):
#                 e = self.G[v][i]
#                 if e[1] > 0 and self.level[e[0]] < 0:
#                     self.level[e[0]] = self.level[v] + 1
#                     que.put(e[0])

#     # 増加バスをdfsで探す
#     def dfs(self, v, t, f):
#         if v == t:
#             return f
#         for i in range(self.iter[v], len(self.G[v])):
#             self.iter[v] = i
#             e = self.G[v][i]
#             if e[1] > 0 and self.level[v] < self.level[e[0]]:
#                 d = self.dfs(e[0], t, min(f, e[1]))
#                 if d > 0:
#                     e[1] -= d
#                     self.G[e[0]][e[2]][1] += d
#                     return d

#         return 0

#     def max_flow(self, s, t):
#         flow = 0
#         while True:
#             self.bfs(s)
#             # bfsで到達不可
#             if self.level[t] < 0:
#                 return flow
#             self.iter = [0 for _ in range(self.V)]
#             f = self.dfs(s, t, INF)
#             while f > 0:
#                 flow += f
#                 f = self.dfs(s, t, INF)


@mt
def slv(N, M, S):
    S = [list(s) for s in S]
    g = Dinic(N*M+2)
    s = N*M
    t = s + 1

    for i in range(N):
        for j in range(M):
            if S[i][j] == '#':
                continue
            v = i*M + j
            if (i + j )%2 == 0:
                g.add_edge(s, v, 1)
            else:
                g.add_edge(v, t, 1)



    for i in range(N):
        for j in range(M):
            if S[i][j] == '#':
                continue
            if (i+j) % 2 == 1:
                continue
            v0 = i*M + j
            for x, y in [(i-1, j), (i+1, j), (i, j-1), (i, j+1)]:
                if not (0 <= x < N and 0 <= y < M):
                    continue
                v1 = x*M + y
                g.add_edge(v0, v1, 1)

    print(g.flow(s, t))
    for from_, to, _, flow in g.get_edges():
        if from_ in {s, t} or to in {s, t} or flow == 0:
            continue
        i0 = from_ // M
        j0 = from_ % M
        i1 = to // M
        j1 = to % M

        if i0 == i1+1:
            S[i1][j1] = 'v'
            S[i0][j0] = '^'
        elif j0 == j1+1:
            S[i1][j1] = '>'
            S[i0][j0] = '<'
        elif i0 == i1-1:
            S[i1][j1] = '^'
            S[i0][j0] = 'v'
        else:
            S[i1][j1] = '<'
            S[i0][j0] = '>'

    for s in S:
        print(''.join(s))


def main():
    N, M = read_int_n()
    S = [read_str() for _ in range(N)]
    slv(N, M, S)


if __name__ == '__main__':
    main()


Measured memory_bytes: 87572