#include <bits/stdc++.h>
//#include <chrono>
//#pragma GCC optimize("Ofast")
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second
typedef long long ll;
typedef vector<ll> vec;
typedef vector<vec> mat;

ll N,M,H,W,Q,K,A,B;
string S;
typedef pair<ll, ll> P;
const ll INF = (1LL<<60);

template<class T> bool chmin(T &a, const T &b){
    if(a > b) {a = b; return true;}
    else return false;
}
template<class T> bool chmax(T &a, const T &b){
    if(a < b) {a = b; return true;}
    else return false;
}

struct edge{
    int to, rev;
    ll cap;
    edge(){}
    edge(int a, ll b, int c){
        to = a;
        cap = b;
        rev = c;
    }
};
using ve = vector<edge>;

void add_edge(int from, int to, ll cap, vector<ve> &G, bool directed = true){
    G[from].emplace_back(to, cap, (int)G[to].size());
    G[to].emplace_back(from, directed ? 0 : cap, (int)G[from].size() - 1);
}

void bfs(int s, vector<ve> &G, vector<int> &level){
    queue<int> que;
    level[s] = 0;
    que.push(s);
    while(!que.empty()){
        int v = que.front(); que.pop();
        for(edge &e : G[v]){
            if(e.cap > 0 && chmin(level[e.to], level[v] + 1)){
                que.push(e.to);
            }
        }
    }
}

ll dfs(int v, int t, ll f, vector<ve> &G, vector<int> &level, vector<int> &iter){
    if(v == t) return f;
    for(int &i = iter[v]; i < G[v].size(); ++i){
        edge &e = G[v][i];
        if(e.cap > 0 && level[v] < level[e.to]){
            ll d = dfs(e.to, t, min(f, e.cap), G, level, iter);
            if(d > 0){
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

ll dinic(int s, int t, vector<ve> &G){
    ll res = 0;
    int sz = G.size();
    for( ; ; ){
        vector<int> level(sz, INT_MAX), iter(sz, 0);
        bfs(s, G, level);
        if(level[t] == INT_MAX) return res;
        ll f;
        while((f = dfs(s, t, INF, G, level, iter)) > 0) res += f;
    }
}

int main() {
    cin>>H>>W;
    vector<string> s(H), ans(s);
    vector<ve> G(H * W + 2, ve(0));
    rep(i, H) {
        char buf[101];
        scanf("%s", buf);
        s[i] = buf;
    }
    vector<int> dh = {-1, 0, 1, 0}, dw = {0, -1, 0, 1}; //片側のみ
    const int start = (int)(H * W), goal = start + 1;
    rep(h, H){
        rep(w, W){
            if(s[h][w] == '.'){
                int from, to;
                if((h + w)&1) {
                    from = start, to = h * W + w;
                    rep(i, 4){
                        int nh = h + dh[i], nw = w + dw[i];
                        if(nh >= 0 && nh < H && nw >= 0 && nw < W && s[nh][nw] == '.'){
                            add_edge(to, nh * W + nw, 1, G);
                        }
                    }
                }else {
                    from = h * W + w, to = goal;
                }
                add_edge(from, to, 1, G);
            }
        }
    }
    cout<<dinic(start, goal, G)<<endl;
    vector<char> itoc = {'^', '<', 'v', '>'};
    rep(h, H){
        rep(w, W){
            if(s[h][w] == '.' && (h + w)&1){
                for(edge &e : G[h * W + w]){
                    if(e.to == start || e.cap == 1) continue;
                    int h_to = e.to / W, w_to = e.to % W;
                    rep(i, 4){
                        if(h + dh[i] == h_to && w + dw[i] == w_to){
                            s[h][w] = itoc[i];
                            s[h_to][w_to] = itoc[(i + 2)%4];
                        }
                    }
                }
            }
        }
    }
    rep(i, H) {
        rep(j, W) printf("%c", s[i][j]);
        printf("\n");
    }
}


Measured memory_bytes: 5220