#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#define DEBUG(...) debug(#__VA_ARGS__, __VA_ARGS__);
#else
#define DEBUG(...) 6;
#endif

template<typename T, typename S> ostream& operator << (ostream &os, const pair<T, S> &p) {return os << "(" << p.first << ", " << p.second << ")";}
template<typename C, typename T = decay<decltype(*begin(declval<C>()))>, typename enable_if<!is_same<C, string>::value>::type* = nullptr>
ostream& operator << (ostream &os, const C &c) {bool f = true; os << "["; for (const auto &x : c) {if (!f) os << ", "; f = false; os << x;} return os << "]";}
template<typename T> void debug(string s, T x) {cerr << s << " = " << x << "\n";}
template<typename T, typename... Args> void debug(string s, T x, Args... args) {cerr << s.substr(0, s.find(',')) << " = " << x << " | "; debug(s.substr(s.find(',') + 2), args...);}

const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};

#define MAX 10005

int n, m, matchL[MAX], matchR[MAX], dist[MAX];
vector<int> adj[MAX];

bool bfs() {
    queue<int> q;
    for (int i=1; i<=n*m; i++) {
        if (!matchL[i]) {
            dist[i] = 0;
            q.push(i);
        } else
            dist[i] = INT_MAX;
    }
    dist[0] = INT_MAX;

    while (!q.empty()) {
        int u = q.front();
        q.pop();

        if (dist[u] < dist[0])
            for (int v : adj[u])
                if (dist[matchR[v]] == INT_MAX) {
                    dist[matchR[v]] = dist[u] + 1;
                    q.push(matchR[v]);
                }
    }
    return dist[0] != INT_MAX;
}

bool dfs(int u) {
    if (u != 0) {
        for (int v : adj[u])
            if (dist[matchR[v]] == dist[u] + 1 && dfs(matchR[v])) {
                matchL[u] = v;
                matchR[v] = u;
                return true;
            }
        dist[u] = INT_MAX;
        return false;
    }
    return true;
}

int mcbm() {
    int ret = 0;
    memset(matchL, 0, sizeof(matchL));
    memset(matchR, 0, sizeof(matchR));
    while (bfs())
        for (int i=1; i<=n*m; i++)
            if (!matchL[i] && dfs(i))
                ret++;
    return ret;
}

string grid[105];

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);

    cin >> n >> m;
    for (int i=0; i<n; i++)
        cin >> grid[i];

    for (int i=0; i<n; i++)
        for (int j=0; j<m; j++) {
            if (grid[i][j] == '#')
                continue;
            if ((i + j) % 2) {
                for (int d=0; d<4; d++)
                    if (0 <= i + dr[d] && i + dr[d] < n && 0 <= j + dc[d] && j + dc[d] < m && grid[i + dr[d]][j + dc[d]] == '.')
                        adj[i * m + j + 1].push_back((i + dr[d]) * m + j + dc[d] + 1);
            }
        }

    cout << mcbm() << "\n";
    for (int i=1; i<=n*m; i++)
        if (matchL[i]) {
            int r0 = (i - 1) / m, c0 = (i - 1) % m, r1 = (matchL[i] - 1) / m, c1 = (matchL[i] - 1) % m;
            if (r0 > r1 || c0 > c1) {
                swap(r0, r1);
                swap(c0, c1);
            }
            if (r1 == r0 + 1) {
                grid[r0][c0] = 'v';
                grid[r1][c1] = '^';
            } else {
                grid[r0][c0] = '>';
                grid[r1][c1] = '<';
            }
        }

    for (int i=0; i<n; i++)
        cout << grid[i] << "\n";

    return 0;
}


Measured memory_bytes: 4176