use flow::dinic::Dinic;
use proconio::{fastout, input, marker::Bytes};
mod flow {
    use std::fmt::Display;
    use std::ops::{Add, AddAssign, Neg, Sub, SubAssign};

    pub trait Zero: Sized {
        fn zero() -> Self;
    }

    pub trait One: Sized {
        fn one() -> Self;
    }

    pub trait Cost:
        Display
        + Copy
        + Eq
        + Ord
        + Zero
        + One
        + Add<Output = Self>
        + AddAssign
        + Sub<Output = Self>
        + Neg<Output = Self>
    {
        fn is_zero(&self) -> bool {
            self == &Self::zero()
        }
        fn is_positive(&self) -> bool {
            self > &Self::zero()
        }
        fn is_negative(&self) -> bool {
            self < &Self::zero()
        }
    }

    pub trait Flow:
        Display
        + Copy
        + Eq
        + Ord
        + Zero
        + One
        + Add<Output = Self>
        + AddAssign
        + Sub<Output = Self>
        + SubAssign
        + Neg<Output = Self>
    {
        fn is_zero(&self) -> bool {
            self == &Self::zero()
        }
        fn is_positive(&self) -> bool {
            self > &Self::zero()
        }
        fn is_negative(&self) -> bool {
            self < &Self::zero()
        }
        fn abs(&self) -> Self {
            if self.is_negative() {
                -*self
            } else {
                *self
            }
        }
    }

    macro_rules! implement {
        ($T:ty) => {
            impl Zero for $T {
                #[inline]
                fn zero() -> Self {
                    0
                }
            }
            impl One for $T {
                #[inline]
                fn one() -> Self {
                    1
                }
            }
            impl Flow for $T {}
            impl Cost for $T {}
        };
    }

    implement!(i8);
    implement!(i16);
    implement!(i32);
    implement!(i64);
    implement!(i128);
    implement!(isize);
    pub mod dinic {
        use super::Flow;
        use core::mem;
        use std::cmp::{max, min};

        struct Edge<F> {
            dst: usize,
            rev: usize,
            flow: F,
            upper: F,
        }

        #[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug, Hash)]
        pub struct EdgeId(usize, usize);
        impl EdgeId {}

        struct TemporaryData {
            n: usize,
            s: usize,
            t: usize,
            label: Vec<usize>,
            current_edge: Vec<usize>,
            buffer: Vec<usize>,
        }

        pub struct Dinic<F: Flow> {
            edges: Vec<Vec<Edge<F>>>,
        }
        impl<F: Flow> Dinic<F> {
            pub fn new() -> Self {
                Self { edges: Vec::new() }
            }

            pub fn add_edge(&mut self, src: usize, dst: usize, capacity: F) -> EdgeId {
                let n = max(max(src, dst) + 1, self.edges.len());
                self.edges.resize_with(n, || Vec::with_capacity(4));
                let e = self.edges[src].len();
                let re = self.edges[dst].len() + if src == dst { 1 } else { 0 };

                self.edges[src].push(Edge {
                    dst,
                    rev: re,
                    flow: F::zero(),
                    upper: capacity,
                });
                self.edges[dst].push(Edge {
                    dst: src,
                    rev: e,
                    flow: capacity,
                    upper: capacity,
                });
                EdgeId(src, e)
            }

            fn prepare_data(&mut self, s: usize, t: usize) -> TemporaryData {
                let n = max(max(s, t) + 1, self.edges.len());
                self.edges.resize_with(n, || Default::default());
                TemporaryData {
                    n,
                    s,
                    t,
                    label: vec![0; n],
                    current_edge: vec![0; n],
                    buffer: Vec::with_capacity(n),
                }
            }

            fn dual(&self, data: &mut TemporaryData) -> bool {
                let n = data.n;
                data.label.iter_mut().for_each(|v| *v = n);
                data.current_edge.iter_mut().for_each(|v| *v = 0);
                let mut queue = mem::take(&mut data.buffer);
                queue.clear();
                queue.push(data.s);
                data.label[data.s] = 0;
                let mut q_pos = 0;
                'new_node: while q_pos < queue.len() {
                    let u = queue[q_pos];
                    q_pos += 1;
                    let next_label = data.label[u] + 1;
                    for e in &self.edges[u] {
                        if e.flow < e.upper && data.label[e.dst] == data.n {
                            data.label[e.dst] = next_label;
                            if e.dst == data.t {
                                break 'new_node;
                            }
                            queue.push(e.dst);
                        }
                    }
                }
                data.buffer = queue;
                data.label[data.t] < n
            }

            fn primal_dfs(&mut self, u: usize, data: &mut TemporaryData, mut limit: F) -> F {
                if u == data.s {
                    return limit;
                }
                let mut total = F::zero();
                let mut i = data.current_edge[u];
                while i < self.edges[u].len() {
                    let e = &self.edges[u][i];
                    if e.flow.is_positive() && data.label[e.dst] < data.label[u] {
                        let new_limit = min(limit, e.flow);
                        let v = e.dst;
                        let f = self.primal_dfs(v, data, new_limit);
                        if !f.is_zero() {
                            let e = &mut self.edges[u][i];
                            let v = e.dst;
                            let r = e.rev;
                            e.flow -= f;
                            self.edges[v][r].flow += f;
                            total += f;
                            limit -= f;
                            if limit.is_zero() {
                                if self.edges[u][i].flow.is_zero() {
                                    i += 1;
                                }
                                data.current_edge[u] = i;
                                return total;
                            }
                        }
                    }
                    i += 1;
                }
                data.current_edge[u] = !0;
                data.label[u] = data.n;
                total
            }

            pub fn augment(&mut self, s: usize, t: usize, limit: F) -> F {
                let mut data = self.prepare_data(s, t);
                let mut flow = F::zero();
                while self.dual(&mut data) {
                    flow += self.primal_dfs(data.t, &mut data, limit - flow);
                    if flow == limit {
                        break;
                    }
                }
                flow
            }

            pub fn max_flow(&mut self, s: usize, t: usize) -> (F, Vec<usize>) {
                let mut data = self.prepare_data(s, t);
                let inf = self.edges[s]
                    .iter()
                    .map(|e| e.upper - e.flow)
                    .fold(F::zero(), |a, b| a + b);
                let mut flow = F::zero();
                while self.dual(&mut data) {
                    flow += self.primal_dfs(data.t, &mut data, inf);
                }
                let label = mem::take(&mut data.label);
                let cut = label
                    .into_iter()
                    .enumerate()
                    .filter(|(_, l)| l < &data.n)
                    .map(|(i, _)| i)
                    .collect();
                (flow, cut)
            }

            pub fn get_flow(&self, e: &EdgeId) -> F {
                self.edges[e.0][e.1].flow
            }
        }
    }
}

#[fastout]
fn main() {
    input! {
        h: usize,
        w: usize,
        mut b: [Bytes; h]
    }

    let mut dinic = Dinic::new();
    let enc = |u, v| u * w + v;
    let s = h * w;
    let t = s + 1;
    for u in 0..h {
        for v in 0..w {
            if b[u][v] == b'#' {
                continue;
            }
            if (u + v) % 2 == 0 {
                dinic.add_edge(s, enc(u, v), 1);
            } else {
                dinic.add_edge(enc(u, v), t, 1);
            }
        }
    }

    let mut edges = Vec::with_capacity(h * w * 4);
    for u in 0..h {
        for v in 0..w {
            if (u + v) % 2 == 1 || b[u][v] == b'#' {
                continue;
            }
            if u > 0 && b[u - 1][v] == b'.' {
                edges.push((
                    u,
                    v,
                    u - 1,
                    v,
                    b'^',
                    b'v',
                    dinic.add_edge(enc(u, v), enc(u - 1, v), 1),
                ));
            }
            if u + 1 < h && b[u + 1][v] == b'.' {
                edges.push((
                    u,
                    v,
                    u + 1,
                    v,
                    b'v',
                    b'^',
                    dinic.add_edge(enc(u, v), enc(u + 1, v), 1),
                ));
            }
            if v > 0 && b[u][v - 1] == b'.' {
                edges.push((
                    u,
                    v,
                    u,
                    v - 1,
                    b'<',
                    b'>',
                    dinic.add_edge(enc(u, v), enc(u, v - 1), 1),
                ));
            }
            if v + 1 < w && b[u][v + 1] == b'.' {
                edges.push((
                    u,
                    v,
                    u,
                    v + 1,
                    b'>',
                    b'<',
                    dinic.add_edge(enc(u, v), enc(u, v + 1), 1),
                ));
            }
        }
    }
    println!("{}", dinic.max_flow(s, t).0);
    for (u, v, uu, vv, c, cc, e) in edges {
        if dinic.get_flow(&e) != 0 {
            b[u][v] = c;
            b[uu][vv] = cc;
        }
    }
    for line in b {
        println!("{}", String::from_utf8(line).unwrap());
    }
}


Measured memory_bytes: 5844