//#pragma GCC target("avx2,avx")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <atcoder/all>
using namespace atcoder;
//using mint = modint998244353;
//using mint = modint1000000007;
#include <bits/stdc++.h>
using namespace std;
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
//using namespace __gnu_pbds;
//using i128 = __int128_t;
using ll = long long;
using ull = unsigned long long;
using pii = pair<int, int>;
using pll = pair<long long, long long>;
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define all(x) (x).begin(),(x).end()
#define SZ(x) ((int)(x).size())
constexpr char ln = '\n';
template<class T1, class T2> inline bool chmax(T1 &a, T2 b) {if (a < b) {a = b; return true;} return false;}
template<class T1, class T2> inline bool chmin(T1 &a, T2 b) {if (a > b) {a = b; return true;} return false;}
inline int topbit(int x) {return x == 0 ? -1 : 31-__builtin_clz(x);}
inline int topbit(long long x) {return x == 0 ? -1 : 63-__builtin_clzll(x);}
inline int botbit(int x) {return x == 0 ? 32 : __builtin_ctz(x);}
inline int botbit(long long x) {return x == 0 ? 64 : __builtin_ctzll(x);}
inline int popcount(int x) {return __builtin_popcount(x);}
inline int popcount(long long x) {return __builtin_popcountll(x);}
inline int kthbit(long long x, int k) {return (x>>k)&1;}
inline void print() {cout << "\n";}
template<class T>
inline void print(const vector<T> &v) {
    for (auto itr = v.begin(); itr != v.end(); ++itr) cout << *itr << " ";
    print();
}
template<class T, class... Args>
inline void print(const T &x, const Args &... args) {
    cout << x << " ";
    print(args...);
}
#ifdef MINATO_LOCAL
#define dump(x) cerr << __LINE__ << " : " << #x << " = " << (x) << endl;
inline void debug() {cerr << endl;}
template<class T>
inline void debug(const vector<T> &v) {
    for (auto itr = v.begin(); itr != v.end(); ++itr) cerr << *itr << " ";
    debug();
}
template<class T, class... Args>
inline void debug(const T &x, const Args &... args) {
    cerr << x << " ";
    debug(args...);
}
#else
#define dump(x) void(0)
inline void debug() {}
template<class T> inline void debug(const vector<T> &v) {}
template<class T, class... Args> inline void debug(const T &x, const Args &... args) {}
#endif
struct Fast_ios {Fast_ios() {cin.tie(nullptr); ios::sync_with_stdio(false); cout << fixed << setprecision(20);};} fast_ios;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const int dx[4] = {-1,0,0,1};
const int dy[4] = {0,-1,1,0};
int main() {
    int N,M; cin >> N >> M;
    vector<string> S(N);
    rep(i,N) cin >> S[i];

    const int s = N*M;
    const int t = s+1;
    mf_graph<int> g(N*M+2);
    rep(i,N) rep(j,M) {
        if (S[i][j]=='#') continue;
        if (~(i+j)&1) g.add_edge(s,i*M+j,1);
        else {
            g.add_edge(i*M+j,t,1);
            continue;
        }
        rep(k,4) {
            int ni = i + dx[k];
            int nj = j + dy[k];
            if (ni < 0 or ni >= N or nj < 0 or nj >= M) continue;
            if (S[ni][nj]=='#') continue;
            g.add_edge(i*M+j,ni*M+nj,1);
        }
    }

    cout << g.flow(s,t) << ln;
    auto edges = g.edges();
    for (auto &e : edges) {
        if (e.from==s or e.to==t or e.flow==0) continue;
        int i0 = e.from/M, j0 = e.from%M;
        int i1 = e.to/M, j1 = e.to%M;
        if (i0==i1) {
            if (j0 > j1) swap(j0,j1);
            S[i0][j0] = '>';
            S[i1][j1] = '<';
        } else {
            if (i0 > i1) swap(i0,i1);
            S[i0][j0] = 'v';
            S[i1][j1] = '^';
        }
    }

    rep(i,N) cout << S[i] << ln;
}


Measured memory_bytes: 5688