/**
 * 3つに割る方法は、同一方向に3分割、2分割して一方を2分割する方法があり、それぞれについて縦方向と横方向がある。
 */
fun main(args: Array<String>) {
    val (h, w) = readLine()!!.split(" ").map(String::toLong)     // 2≤H,W≤10^5 積はInt.Maxを超えうる。

    /**
     * 水平方向の分割
     * @param a 3分割される辺の長さ
     * @return a == 2だとこの方向では分割できないのでnullを返す。
     */
    fun pararell(a: Long, b: Long): Long? {
        if (a < 3) return null
        return when (a % 3) {
            0L -> 0      // 等分できる
            1L, 2L -> b   // a方向の長さが1違う形に分割できる。
            else -> throw Exception()   // それ以外の場合はない
        }
    }

    /**
     * 長さaの辺を2分割して、分割した一方のみをさらに分割する。
     * @param a
     */
    fun vertical(a: Long, b: Long): Long {
        val a0 = a / 3      // a == 2でも最後のmin()により正しく動作する。
        return (a0 .. a0 + 2).map {     // きれいに割れないところについては全て試す。割り切れる場合も、最後のmin()により正しく動作する。
            /** 長方形の面積 */
            val areas = listOf(it * b, (a - it) * (b / 2), (a - it) * (b - (b / 2)))
            // 空のリストでないことは保証されている。
            areas.max()!! - areas.min()!!
        }.min()!!       // 空のリストでないことは保証されている。
    }

    val candidates = listOf(vertical(h, w), vertical(w, h), pararell(h, w), pararell(w, h)).filterNotNull()

    println(candidates.min()!!)       // 空のリストでないことはverticalの戻り値があることにより保証されている。
}