#include <bits/stdc++.h>

template <typename T>
struct Edge {
  int from, to;
  T weight;
};

template <typename T>
class Graph {
 public:
  Graph(int n) : edges_(n) {}
  void AddEdge(int from, int to, T weight = T()) {
    edges_[from].push_back({from, to, weight});
  }
  const std::vector<Edge<T>>& Edges(int from) const { return edges_[from]; }
  int NumVertices() const { return edges_.size(); }

 private:
  std::vector<std::vector<Edge<T>>> edges_;
};

template <typename T>
std::pair<T, std::vector<std::vector<T>>> EdmondsKarp(const Graph<T>& g,
                                                      int src, int dst) {
  int N = g.NumVertices();
  std::vector<std::vector<T>> flow(N, std::vector<T>(N));
  T total = 0;
  while (true) {
    std::queue<std::pair<int, T>> que;
    que.push({src, std::numeric_limits<T>::max()});
    std::vector<int> prev(N, -1);
    while (!que.empty()) {
      auto [u, f] = que.front();
      que.pop();
      if (u == dst) {
        total += f;
        while (u != src) {
          flow[prev[u]][u] += f;
          flow[u][prev[u]] -= f;
          u = prev[u];
        }
        break;
      }
      for (auto& e : g.Edges(u)) {
        if (prev[e.to] != -1) continue;
        T residue = e.weight - flow[u][e.to];
        if (residue == 0) continue;
        prev[e.to] = u;
        que.push({e.to, std::min(f, residue)});
      }
    }
    if (prev[dst] == -1) break;
  }
  return {total, flow};
}

template <typename T, typename = void>
struct is_iterable : std::false_type {};
template <typename T>
struct is_iterable<T, std::void_t<decltype(std::begin(std::declval<T>())),
                                  decltype(std::end(std::declval<T>()))>>
    : std::true_type {};

template <typename T, typename = void>
struct is_pair : std::false_type {};
template <typename T>
struct is_pair<T, std::void_t<decltype(std::declval<T>().first),
                              decltype(std::declval<T>().second)>>
    : std::true_type {};

template <typename T>
void debug(const T& v) {
  if constexpr (is_pair<T>::value) {
    std::cerr << "{";
    debug(v.first);
    std::cerr << ", ";
    debug(v.second);
    std::cerr << "}";
  } else if constexpr (is_iterable<T>::value &&
                       !std::is_same<T, std::string>::value) {
    std::cerr << "{";
    for (auto it = std::begin(v); it != std::end(v); ++it) {
      if (it != std::begin(v)) std::cerr << ", ";
      debug(*it);
    }
    std::cerr << "}";
  } else {
    std::cerr << v;
  }
}
template <typename T, typename... Ts>
void debug(const T& value, const Ts&... args) {
  debug(value);
  std::cerr << ", ";
  debug(args...);
}
#if DEBUG
#define dbg(...)                        \
  do {                                  \
    cerr << #__VA_ARGS__ << ": ";       \
    debug(__VA_ARGS__);                 \
    cerr << " (L" << __LINE__ << ")\n"; \
  } while (0)
#else
#define dbg(...)
#endif

void read_from_cin() {}
template <typename T, typename... Ts>
void read_from_cin(T& value, Ts&... args) {
  std::cin >> value;
  read_from_cin(args...);
}
#define rd(type, ...) \
  type __VA_ARGS__;   \
  read_from_cin(__VA_ARGS__);
#define ints(...) rd(int, __VA_ARGS__);
#define strings(...) rd(string, __VA_ARGS__);

template <typename T>
void write_to_cout(const T& value) {
  if constexpr (std::is_same<T, bool>::value) {
    std::cout << (value ? "Yes" : "No");
  } else {
    std::cout << value;
  }
}
template <typename T, typename... Ts>
void write_to_cout(const T& value, const Ts&... args) {
  write_to_cout(value);
  std::cout << ' ';
  write_to_cout(args...);
}
#define wt(...)                 \
  do {                          \
    write_to_cout(__VA_ARGS__); \
    cout << '\n';               \
  } while (0)

#define all(x) (x).begin(), (x).end()

#define rep_dispatch(_1, _2, _3, name, ...) name

#define rep3(i, a, b) for (int i = (int)(a); i < (int)(b); ++i)
#define rep2(i, n) rep3(i, 0, n)
#define rep1(n) rep2(_loop_variable_, n)
#define rep(...) rep_dispatch(__VA_ARGS__, rep3, rep2, rep1)(__VA_ARGS__)

#define rrep3(i, a, b) for (int i = (int)(b)-1; i >= a; --i)
#define rrep2(i, n) rrep3(i, 0, n)
#define rrep1(n) rrep2(_loop_variable_, n)
#define rrep(...) rep_dispatch(__VA_ARGS__, rrep3, rrep2, rrep1)(__VA_ARGS__)

template <typename T>
std::istream& operator>>(std::istream& is, std::vector<T>& v) {
  for (T& vi : v) is >> vi;
  return is;
}

template <typename T, typename U>
std::istream& operator>>(std::istream& is, std::pair<T, U>& p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T, typename U>
bool chmax(T& a, U b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template <typename T, typename U>
bool chmin(T& a, U b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template <typename T>
int sz(const T& v) {
  return v.size();
}

template <typename T>
int popcount(T i) {
  return std::bitset<std::numeric_limits<T>::digits>(i).count();
}

#include <boost/hana/functional/fix.hpp>
const auto& Fix = boost::hana::fix;

using ll = long long;

template <typename T>
using low_priority_queue =
    std::priority_queue<T, std::vector<T>, std::greater<T>>;

template <typename T>
using V = std::vector<T>;
template <typename T>
using VV = V<V<T>>;

using namespace std;

int main() {
  ints(n, m);
  V<string> s(n);
  cin >> s;

  auto idx = [&](int r, int c) { return r * m + c; };
  int src = idx(n - 1, m - 1) + 1, dst = src + 1;
  Graph<int> g(dst + 1);
  auto add = [&](int u, int v) {
    g.AddEdge(u, v, 1);
    g.AddEdge(v, u, 0);
  };
  int dr[] = {0, 1, 0, -1};
  int dc[] = {1, 0, -1, 0};
  rep(r, n) rep(c, m) {
    if (s[r][c] == '#') continue;
    if ((r + c) % 2 == 0) {
      add(src, idx(r, c));
      rep(i, 4) {
        int nr = r + dr[i];
        int nc = c + dc[i];
        if (0 <= nr && nr < n && 0 <= nc && nc < m && s[r][c] == '.') {
          add(idx(r, c), idx(nr, nc));
        }
      }
    } else {
      add(idx(r, c), dst);
    }
  }

  auto [total, flow] = EdmondsKarp(g, src, dst);
  rep(r, n) rep(c, m) rep(k, 4) {
    int nr = r + dr[k];
    int nc = c + dc[k];
    if (0 <= nr && nr < n && 0 <= nc && nc < m &&
        flow[idx(r, c)][idx(nr, nc)] == 1) {
      if (k == 0) {
        s[r][c] = '>';
        s[nr][nc] = '<';
      } else if (k == 1) {
        s[r][c] = 'v';
        s[nr][nc] = '^';
      } else if (k == 2) {
        s[r][c] = '<';
        s[nr][nc] = '>';
      } else {
        s[r][c] = '^';
        s[nr][nc] = 'v';
      }
    }
  }
  wt(total);
  rep(i, n) wt(s[i]);
}


Measured memory_bytes: 787000