#include "iostream"
#include "climits"
#include "list"
#include "queue"
#include "stack"
#include "set"
#include "functional"
#include "algorithm"
#include "string"
#include "map"
#include "unordered_map"
#include "unordered_set"
#include "iomanip"
#include "cmath"
#include "random"
#include "bitset"
#include "cstdio"
#include "numeric"
#include "cassert"
#include "ctime"

using namespace std;

//constexpr long long int MOD = 1000000007;
//constexpr int MOD = 1000000007;
//constexpr int MOD = 998244353;
constexpr long long int MOD = 998244353;
constexpr double EPS = 1e-12;

//int N, M, K, T, H, W, L, R;
long long int N, M, K, T, H, W, L, R;

class Edge {
public:
	long long int to;
	long long int max_flow;
	long long int rev;
};

class Dinic {
	int V;
	bool directed;
public:
	vector<vector<Edge>>edge;
	vector<int>depth;
	vector<int>index;
	Dinic(int n, bool D) {
		n++;
		V = n;
		edge.resize(V);
		depth.resize(V);
		index.resize(V);
		directed = D;
		return;
	}
	void Add_Edge(int l, int r, int max_flow) {
		edge[l].push_back({ r,max_flow,(int)edge[r].size() });
		if (directed) {
			edge[r].push_back({ l,0,(int)edge[l].size() - 1 });
		}
		else {
			edge[r].push_back({ l,max_flow,(int)edge[l].size() - 1 });
		}
		return;
	}
	void Check_Depth(int s) {
		for (int i = 0; i < V; i++) {
			depth[i] = INT_MAX;
		}
		depth[s] = 0;
		queue<int>Q;
		Q.push(s);
		while (!Q.empty()) {
			int cn = Q.front();
			Q.pop();
			for (auto i : edge[cn]) {
				if (i.max_flow > 0 && depth[i.to] == INT_MAX) {
					depth[i.to] = depth[cn] + 1;
					Q.push(i.to);
				}
			}
		}
		return;
	}
	long long int max_flow(int v, int g, long long int ret) {
		if (v == g) {
			return ret;
		}
		for (int i = index[v]; i < edge[v].size(); i++) {
			if (edge[v][i].max_flow > 0 && depth[v] < depth[edge[v][i].to]) {
				long long int d = max_flow(edge[v][i].to, g, min(ret, edge[v][i].max_flow));
				if (d > 0) {
					edge[v][i].max_flow -= d;
					edge[edge[v][i].to][edge[v][i].rev].max_flow += d;
					return d;
				}
			}
		}
		return 0;
	}
	long long Solve(int s, int g) {
		long long int ret = 0;
		while (1) {
			Check_Depth(s);
			if (depth[g] == INT_MAX) {
				return ret;
			}
			for (int i = 0; i < V; i++) {
				index[i] = 0;
			}
			long long int add = 0;
			while ((add = max_flow(s, g, INT_MAX)) > 0) {
				ret += add;
			}
		}
		return ret;
	}
};

int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin >> H >> W;
	vector<string>s(H);
	for (auto &i : s)cin >> i;
	Dinic d(H*W + 2, true);
	int dir[] = { 1,0,-1,0,1 };
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			if (s[i][j] == '#')continue;
			if ((i + j) & 1) {
				d.Add_Edge(H*W, i*W + j, 1);
				for (int k = 0; k < 4; k++) {
					int ny = i + dir[k];
					int nx = j + dir[k + 1];
					if (ny < 0 || nx < 0 || ny >= H || nx >= W) continue;
					d.Add_Edge(i*W + j, ny*W + nx, 1);
				}
			}
			else {
				d.Add_Edge(i*W + j, H*W + 1, 1);
			}
		}
	}
	cout << d.Solve(H*W, H*W + 1) << endl;
	for (int i = 0; i < H; i++) {
		for (int j = 0; j < W; j++) {
			if ((i + j) & 1) {
				int num = i * W + j;
				for (auto k : d.edge[num]) {
					if (k.max_flow == 0) {
						if (k.to == H * W)continue;
						if (num + W == k.to) {
							s[i][j] = 'v';
							s[i + 1][j] = '^';
						}
						else if (num + 1 == k.to) {
							s[i][j] = '>';
							s[i][j + 1] = '<';
						}
						else if (num - W == k.to) {
							s[i][j] = '^';
							s[i - 1][j] = 'v';
						}
						else {
							s[i][j] = '<';
							s[i][j - 1] = '>';
						}
					}
				}
			}
		}
	}
	for (auto i : s)cout << i << endl;
}

Measured memory_bytes: 5800