unittest
{
	assert( [ "3 5" ].parse.expand.solve == 0 );
	assert( [ "4 5" ].parse.expand.solve == 2 );
	assert( [ "5 5" ].parse.expand.solve == 4 );
	assert( [ "100000 2" ].parse.expand.solve == 1 );
	assert( [ "100000 100000" ].parse.expand.solve == 50000 );
}



import std.algorithm;
import std.conv;
import std.math;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void main()
{
	stdin.byLineCopy.parse.expand.solve.writeln;
}

auto parse( Range )( Range input )
if( isInputRange!Range && is( ElementType!Range == string ) )
{
	auto hw = input.front.split.to!( long[] );
	return tuple( hw[ 0 ], hw[ 1 ] );
}

auto solve( long h, long w )
{
	// 縦に割って横に割る場合を計算
	auto r1 = divD( h, w );
	
	// 横に割って縦に割る場合を計算
	auto r2 = divD( w, h );
	
	// 差が小さいほうを取る
	return min( r1, r2 );
}

auto divD( long h, long w )
{
	auto ps = new long[ 3 ];
	
	// 三等分したときの1つの大きさを計算
	auto d3 = h * w / 3.0f;
	ps[ 0 ] = roundN( d3, h );		// マス目に合わせる
	if( h % 3 == 0 || w % 3 == 0 ) return 0L;		// マス目に沿って均等に三等分できた
	w -= ps[ 0 ] / h;
	
	// 残りの部分を二等分したときの1つの大きさを計算
	auto d2 = h * w / 2.0f;
	ps[ 1 ] = roundN( d2, w );		// マス目に合わせる
	if( h % 2 == 0 ) return ( ps[ 0 ] - ps[ 1 ] ).abs;		// 均等に二等分できた
	h -= ps[ 1 ] / w;
	
	// 残りの部分の大きさを計算
	ps[ 2 ] = h * w;
	
	// 差を計算
	auto mm = ps.reduce!( max, min );
	return mm[ 0 ] - mm[ 1 ];
}

auto roundN( real x, long b )
{
	auto r = x % b;
	if( b / 2 <= r ) x += b;
	x -= r;
	return x.to!long;
}
