#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <algorithm>
using i64 = long long;

class Dinic {
    using i64 = long long;
    struct EdgeState {
        unsigned to;
        unsigned rev;
        i64 cap;
        EdgeState(const unsigned t, const i64 c, const unsigned r) : to(t), rev(r), cap(c) {}
    };

    static constexpr i64 inf = 1000000000000000;
    std::vector<std::vector<EdgeState>> g;
    std::vector<int> level;
    std::vector<unsigned> iter;
    const unsigned size;

    void bfs(const unsigned s) {
        for (unsigned i = 0; i < size; i++) level[i] = -1;
        level[s] = 0;

        std::deque<unsigned> q { s };

        while (!q.empty()) {
            const auto curr = q.front();
            q.pop_front();
            for (auto &e : g[curr]) {
                if (e.cap > 0 && level[e.to] < 0) {
                    level[e.to] = level[curr] + 1;
                    q.push_back(e.to);
                }
            }
        }
    }

    i64 dfs(const int v, const int t, const i64 f) {
        if (v == t) return f;

        for (unsigned i = 0; i < g[v].size(); i++) {
            iter[v] = i;
            auto &e = g[v][i];

            if (e.cap > 0 && level[v] < level[e.to]) {
                i64 d = dfs(e.to, t, std::min(f, e.cap));
                if (d > 0) {
                    e.cap -= d;
                    g[e.to][e.rev].cap += d;
                    return d;
                }
            }
        }

        return 0;
    }

public:
    using Index = std::pair<unsigned, unsigned>;
    struct Edge {
        unsigned from, to;
        i64 cap, flow;
    };

    explicit Dinic(const unsigned s) :
        g(s),
        level(s),
        iter(s),
        size(s) {}

    Index add_edge(const unsigned from, const unsigned to, const i64 cap) {
        const auto &e = g[from].emplace_back(to, cap, g[to].size());
        g[to].emplace_back(from, 0, g[from].size() - 1);
        return { e.to, e.rev };
    }

    Edge get_edge(const Index &p) {
        const decltype(auto) rev = g[p.first][p.second];
        const decltype(auto) e = g[rev.to][rev.rev];
        return {
            rev.to,
            e.to,
            e.cap + rev.cap,
            rev.cap,
        };
    }

    i64 calc(const unsigned s, const unsigned t) {
        i64 flow = 0;
        while (true) {
            bfs(s);
            if (level[t] < 0) return flow;

            for (auto &el : iter) el = 0;

            i64 f = dfs(s, t, inf);
            while (f > 0) {
                flow += f;
                f = dfs(s, t, inf);
            }
        }
    }
};

int main() {
    int n, m;
    std::cin >> n >> m;
    std::vector<std::string> b(n);
    for (auto &e : b) std::cin >> e;

    const int s = n * m, t = s + 1;
    Dinic d(t + 1);
    std::vector<Dinic::Index> w;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) {
        if (b[i][j] == '#') continue;
        const int k = i * m + j;
        if ((i + j) & 1) {
            d.add_edge(k, t, 1);
            continue;
        }

        d.add_edge(s, k, 1);

        if (i > 0 && b[i - 1][j] == '.') w.push_back(d.add_edge(k, k - m, 1));
        if (i + 1 < n && b[i + 1][j] == '.') w.push_back(d.add_edge(k, k + m, 1));
        if (j > 0 && b[i][j - 1] == '.') w.push_back(d.add_edge(k, k - 1, 1));
        if (j + 1 < m && b[i][j + 1] == '.') w.push_back(d.add_edge(k, k + 1, 1));
    }

    d.calc(s, t);

    int ret = 0;
    for (const auto index : w) {
        const auto &e = d.get_edge(index);
        if (!e.flow) continue;
        ret++;
        const int is = e.from / m, js = e.from % m, it = e.to / m, jt = e.to % m;
        if (is == it) {
            const auto [l, r] = std::minmax(js, jt);
            b[is][l] = '>';
            b[is][r] = '<';
        } else {
            const auto [u, d] = std::minmax(is, it);
            b[u][js] = 'v';
            b[d][js] = '^';
        }
    }

    std::cout << ret << '\n';
    for (const auto &line : b) std::cout << line << '\n';

    return 0;
}


Measured memory_bytes: 5212