Problem:
Score : 400 points

Problem Statement

There is a bar of chocolate with a height of H blocks and a width of W blocks.
Snuke is dividing this bar into exactly three pieces.
He can only cut the bar along borders of blocks, and the shape of each piece must be a rectangle.

Snuke is trying to divide the bar as evenly as possible.
More specifically, he is trying to minimize S_{max} - S_{min}, where S_{max} is the area (the number of blocks contained) of the largest piece, and S_{min} is the area of the smallest piece.
Find the minimum possible value of S_{max} - S_{min}.

Constraints

2 ≤ H, W ≤ 10^5

Input

Input is given from Standard Input in the following format:

H W

Output

Print the minimum possible value of S_{max} - S_{min}.

Sample Input 1

3 5

Sample Output 1

0

In the division below, S_{max} - S_{min} = 5 - 5 = 0.

Sample Input 2

4 5

Sample Output 2

2

In the division below, S_{max} - S_{min} = 8 - 6 = 2.

Sample Input 3

5 5

Sample Output 3

4

In the division below, S_{max} - S_{min} = 10 - 6 = 4.

Sample Input 4

100000 2

Sample Output 4

1

Sample Input 5

100000 100000

Sample Output 5

50000

Solution in Rust (1.15.1) (judge verdict: Accepted)

mod reader {
    use std::fmt::Debug;
    use std::str::FromStr;
    use std::collections::VecDeque;
    use std::io::{self, Read};

    fn _read_line() -> String {
        let mut buf = String::new();
        io::stdin().read_to_string(&mut buf);
        buf
    }

    fn _read_vec_deque_string() -> VecDeque<String> {
        _read_line().split_whitespace().map(|s| s.to_string()).collect()
    }

    pub struct Reader {
        buf: VecDeque<String>
    }

    impl Reader {
        pub fn new() -> Reader {
            Reader {buf: VecDeque::new()}
        }

        fn update_buf(&mut self) {
            if self.buf.is_empty() {
                self.buf = _read_vec_deque_string();
            }
        }

        pub fn next<T>(&mut self) -> T where T: FromStr, T::Err: Debug {
            self.update_buf();
            self.buf.pop_front().unwrap().parse::<T>().unwrap()
        }

        pub fn nextN<T>(&mut self, n: usize) -> Vec<T> where T: FromStr, T::Err: Debug {
            let mut vec: Vec<T> = Vec::with_capacity(n);
            for i in 0..n {
                vec.push(self.next());
            }
            vec
        }
    }
}

fn diff(t: &(i64, i64, i64)) -> i64 {
    let t = vec![t.0, t.1, t.2];
    return t.iter().max().unwrap() - t.iter().min().unwrap();
}

fn f(h: i64, w: i64) -> i64 {
    let mut ans = h * w;
    for i in 1..h {
        let s1 = i * w;
        let (s2, s3) = g(h - i, w);
        ans = std::cmp::min(ans, diff(&(s1, s2, s3)));
        let (s2, s3) = g(w, h - i);
        ans = std::cmp::min(ans, diff(&(s1, s2, s3)));
    }
    ans
}

fn g(h: i64, w: i64) -> (i64, i64) {
    if h == 1 {
        return (0, 100000000000);
    }
    if h % 2 == 0 {
        (h / 2 * w, h / 2 * w)
    } else {
        (h / 2 * w, (h / 2 + 1) * w)
    }
}

fn main() {
    let mut reader = reader::Reader::new();

    let h = reader.next();
    let w = reader.next();

    println!("{}", std::cmp::min(f(h, w), f(w, h)));
}