local WhiteBlack = {}

WhiteBlack.create = function(self)
  self.edge = {}
  self.invedge = {}
  self.leftnode = {}
  self.rightmatched = {}
  self.route = {}
  self.routelen = 0
  self.asked = {}
  self.finaldst = {}
end

WhiteBlack.addNode = function(self, node, isLeft)
  if isLeft then
    table.insert(self.leftnode, node)
    self.edge[node] = {}
  else
    self.invedge[node] = {}
  end
end

WhiteBlack.addEdge = function(self, src, dst)
  assert(self.edge[src])
  self.edge[src][dst] = 1
  self.invedge[dst][src] = 0
end

WhiteBlack.dfs = function(self)
  local src = self.route[self.routelen]
  if self.routelen % 2 == 1 then
    for dst, c in pairs(self.edge[src]) do
      if c == 1 and not self.asked[dst] then
        self.asked[dst] = true
        self.routelen = self.routelen + 1
        self.route[self.routelen] = dst
        local ret = self:dfs()
        if ret then return true end
        self.routelen = self.routelen - 1
      end
    end
  else
    if not self.rightmatched[src] then
      self.rightmatched[src] = true
      return true
    end
    for dst, c in pairs(self.invedge[src]) do
      if c == 1 and not self.asked[dst] then
        self.asked[dst] = true
        self.routelen = self.routelen + 1
        self.route[self.routelen] = dst
        local ret = self:dfs()
        if ret then return true end
        self.routelen = self.routelen - 1
      end
    end
  end
  return false
end

WhiteBlack.run = function(self, spos)
  local tasks = {spos}
  local tasked = {}
  local dstpos = 0
  tasked[spos] = true
  for k, _u in pairs(self.asked) do
    self.asked[k] = false
  end
  self.asked[spos] = true
  self.routelen = 1
  self.route[1] = spos
  local found = self:dfs()
  if found then
    for i = 1, self.routelen - 1 do
      local src, dst = self.route[i], self.route[i + 1]
      if i % 2 == 1 then
        self.edge[src][dst] = 0
        self.invedge[dst][src] = 1
        self.finaldst[src] = dst
      else
        self.edge[dst][src] = 1
        self.invedge[src][dst] = 0
      end
    end
    return true
  else return false end
end

WhiteBlack.getMatchCount = function(self)
  local cnt = 0
  local lnodenum = #self.leftnode
  for i = 1, lnodenum do
    local res = self:run(self.leftnode[i])
    if res then cnt = cnt + 1 end
  end
  return cnt
end

WhiteBlack.new = function()
  local obj = {}
  setmetatable(obj, {__index = WhiteBlack})
  obj:create()
  return obj
end

local wb = WhiteBlack.new()
local h, w = io.read("*n", "*n", "*l")
local map = {}
for i = 1, h do
  local s = io.read()
  for j = 1, w do
    local idx = (i - 1) * w + j
    map[idx] = s:sub(j, j)
    wb:addNode(idx, (i + j) % 2 == 0)
  end
end
for i = 1, h - 1 do
  for j = 1, w do
    local idx = (i - 1) * w + j
    local isleft = (i + j) % 2 == 0
    if map[idx] == "." and map[idx + w] == "." then
      if isleft then
        wb:addEdge(idx, idx + w)
      else
        wb:addEdge(idx + w, idx)
      end
    end
  end
end
for i = 1, h do
  for j = 1, w - 1 do
    local idx = (i - 1) * w + j
    local isleft = (i + j) % 2 == 0
    if map[idx] == "." and map[idx + 1] == "." then
      if isleft then
        wb:addEdge(idx, idx + 1)
      else
        wb:addEdge(idx + 1, idx)
      end
    end
  end
end
local cnt = wb:getMatchCount()
print(cnt)
for l, r in pairs(wb.finaldst) do
  if l + w == r then
    map[l] = "v"
    map[r] = "^"
  elseif l - w == r then
    map[r] = "v"
    map[l] = "^"
  elseif l + 1 == r then
    map[l] = ">"
    map[r] = "<"
  elseif l - 1 == r then
    map[l] = "<"
    map[r] = ">"
  end
end
for i = 1, h do
  for j = 1, w do
    io.write(map[(i - 1) * w + j])
  end
  io.write("\n")
end


Measured memory_bytes: 5668