using System;
using System.Linq;
using CompLib.Util;
using System.Threading;
using CompLib.Graph;
using System.Collections.Generic;

public class Program
{

    public void Solve()
    {
        var sc = new Scanner();
        int n = sc.NextInt();
        int m = sc.NextInt();

        string[] s = new string[n];
        for (int i = 0; i < n; i++)
        {
            s[i] = sc.Next();
        }

        var mf = new MaxFlow(1 + n * m + 1);
        var ls = new List<int>();
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < m; j++)
            {
                int cur = i * m + j + 1;
                if (s[i][j] != '.') continue;
                if ((i + j) % 2 == 0)
                {
                    mf.AddEdge(0, cur, 1);
                }
                else
                {
                    mf.AddEdge(cur, n * m + 1, 1);
                }

                if (i + 1 < n && s[i + 1][j] == '.')
                {
                    int d = (i + 1) * m + j + 1;
                    if ((i + j) % 2 == 0)
                    {
                        ls.Add(mf.AddEdge(cur, d, 1));
                    }
                    else
                    {
                        ls.Add(mf.AddEdge(d, cur, 1));
                    }
                }

                if (j + 1 < m && s[i][j + 1] == '.')
                {
                    int r = i * m + j + 2;
                    if ((i + j) % 2 == 0)
                    {
                        ls.Add(mf.AddEdge(cur, r, 1));
                    }
                    else
                    {
                        ls.Add(mf.AddEdge(r, cur, 1));
                    }
                }
            }
        }
        var ans = new char[n][];
        for (int i = 0; i < n; i++)
        {
            ans[i] = s[i].ToCharArray();
        }
        Console.WriteLine(mf.Flow(0, n * m + 1));
        foreach (var e in ls)
        {
            var edge = mf.GetEdge(e);
            if (edge.Flow < edge.Cap) continue;
            int f = edge.From;
            int t = edge.To;
            if (f > t) (f, t) = (t, f);
            int i = (f - 1) / m;
            int j = (f - 1) % m;
            if (f + 1 == t && j + 1 < m)
            {
                ans[i][j] = '>';
                ans[i][j + 1] = '<';
            }
            else
            {
                ans[i][j] = 'v';
                ans[i + 1][j] = '^';
            }
        }

        for (int i = 0; i < n; i++)
        {
            Console.WriteLine(new string(ans[i]));
        }
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}



namespace CompLib.Graph
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using Cap = System.Int32;
    class MaxFlow
    {
        private List<S> _pos;
        private List<InternalEdge>[] _g;
        private readonly int _n;
        private readonly int[] _level, _iter;

        private readonly int[] _queue;
        private int _begin, _end;
        public MaxFlow(int n)
        {
            _n = n;
            _g = new List<InternalEdge>[_n];
            for (int i = 0; i < _n; i++)
            {
                _g[i] = new List<InternalEdge>();
            }
            _pos = new List<S>();

            _level = new int[_n];
            _iter = new int[_n];

            _queue = new int[_n];
        }

        public int AddEdge(int from, int to, Cap cap)
        {
            Debug.Assert(0 <= from && from < _n);
            Debug.Assert(0 <= to && to < _n);
            Debug.Assert(0 <= cap);
            int m = _pos.Count;
            _pos.Add(new S(from, _g[from].Count));
            int fromID = _g[from].Count;
            int toID = _g[to].Count;
            if (from == to) toID++;
            _g[from].Add(new InternalEdge(to, toID, cap));
            _g[to].Add(new InternalEdge(from, fromID, 0));
            return m;
        }

        public Edge GetEdge(int i)
        {
            int m = _pos.Count;
            Debug.Assert(0 <= i && i < m);
            var e = _g[_pos[i].From][_pos[i].Index];
            var re = _g[e.To][e.Rev];

            return new Edge(_pos[i].From, e.To, e.Cap + re.Cap, re.Cap);
        }

        public Edge[] Edges()
        {
            int m = _pos.Count;
            Edge[] result = new Edge[m];
            for (int i = 0; i < m; i++)
            {
                result[i] = GetEdge(i);
            }
            return result;
        }

        public void ChangeEdge(int i, Cap newCap, Cap newFlow)
        {
            int m = _pos.Count;
            Debug.Assert(0 <= i && i < m);
            Debug.Assert(0 <= newFlow && newFlow <= newCap);
            var e = _g[_pos[i].From][_pos[i].Index];
            var re = _g[e.To][e.Rev];
            e.Cap = newCap - newFlow;
            re.Cap = newFlow;
            _g[_pos[i].From][_pos[i].Index] = e;
            _g[e.To][e.Rev] = re;
        }

        private void BFS(int s, int t)
        {
            for (int i = 0; i < _n; i++)
            {
                _level[i] = -1;
            }
            _level[s] = 0;
            _begin = 0;
            _end = 0;
            _queue[_end++] = s;
            while (_end > _begin)
            {
                int v = _queue[_begin++];
                foreach (var e in _g[v])
                {
                    if (e.Cap == 0 || _level[e.To] >= 0) continue;
                    _level[e.To] = _level[v] + 1;
                    if (e.To == t) return;
                    _queue[_end++] = e.To;
                }
            }
        }

        private Cap DFS(int v, int s, Cap up)
        {
            if (v == s) return up;
            Cap res = 0;
            for (; _iter[v] < _g[v].Count; _iter[v]++)
            {
                var e = _g[v][_iter[v]];
                if (_level[v] <= _level[e.To] || _g[e.To][e.Rev].Cap == 0) continue;
                Cap d = DFS(e.To, s, Math.Min(up - res, _g[e.To][e.Rev].Cap));
                if (d <= 0) continue;

                e.Cap += d;
                _g[v][_iter[v]] = e;

                var rev = _g[e.To][e.Rev];
                rev.Cap -= d;
                _g[e.To][e.Rev] = rev;
                res += d;
                if (res == up) break;
            }
            return res;
        }

        public Cap Flow(int s, int t, Cap flowLimit)
        {
            Debug.Assert(0 <= s && s < _n);
            Debug.Assert(0 <= t && t < _n);
            Debug.Assert(s != t);


            Cap flow = 0;
            while (flow < flowLimit)
            {
                BFS(s, t);
                if (_level[t] == -1) break;
                for (int i = 0; i < _n; i++)
                {
                    _iter[i] = 0;
                }
                while (flow < flowLimit)
                {
                    Cap f = DFS(t, s, flowLimit - flow);
                    if (f == 0) break;
                    flow += f;
                }
            }

            return flow;
        }


        public Cap Flow(int s, int t)
        {
            return Flow(s, t, Cap.MaxValue);
        }

        public bool[] MinCut(int s)
        {
            bool[] visited = new bool[_n];
            _begin = 0;
            _end = 0;
            _queue[_end++] = s;
            visited[s] = true;
            while (_end > _begin)
            {
                var p = _queue[_begin++];
                foreach (var e in _g[p])
                {
                    if (e.Cap > 0 && !visited[e.To])
                    {
                        visited[e.To] = true;
                        _queue[_end++] = e.To;
                    }
                }
            }
            return visited;
        }

        struct InternalEdge
        {
            public int To, Rev;
            public Cap Cap;
            public InternalEdge(int to, int rev, Cap cap)
            {
                To = to;
                Rev = rev;
                Cap = cap;
            }
        }

        struct S
        {
            public readonly int From, Index;
            public S(int from, int index)
            {
                From = from;
                Index = index;
            }
        }
    }

    public struct Edge
    {
        public readonly int From, To;
        public readonly Cap Cap, Flow;
        public Edge(int from, int to, Cap cap, Cap flow)
        {
            From = from;
            To = to;
            Cap = cap;
            Flow = flow;
        }
    }
}


namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


Measured memory_bytes: 31220