unittest
{
	assert( [ "3 3", "...", ".#.", "..." ].parse.expand.solve == 2 );
	assert( [ "6 6", "..#..#", "......", "#..#..", "......", ".#....", "....#." ].parse.expand.solve == 3 );
}



import std.conv;
import std.range;
import std.stdio;
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[] );
	auto ass = new char[][]( hw[ 0 ], hw[ 1 ] );
	foreach( ref as; ass )
	{
		input.popFront;
		as = input.front.to!( char[] );
	}
	return tuple( ass );
}

auto solve( char[][] ass )
{
	// 黒マスの座標を配列化、白マスを数える
	Tuple!( long, long )[] bs;
	auto w = ass.length * ass[ 0 ].length;
	foreach( y, as; ass )
	{
		foreach( x, a; as )
		{
			if( a == '.' ) continue;
			bs ~= tuple( y.signed, x.signed );
			w--;
		}
	}
	
	// 黒マスを広げる
	for( auto i = 1L;; i++ )
	{
		foreach( b; bs )
		{
			for( auto dy = 0L, dx = i; dy <= i; dy++, dx-- )
			{
				auto y1 = b[ 0 ] - dy;
				auto y2 = b[ 0 ] + dy;
				auto x1 = b[ 1 ] - dx;
				auto x2 = b[ 1 ] + dx;
				
				if( 0 <= y1 )
				{
					if( 0 <= x1               && ass[ y1 ][ x1 ] == '.' ){ ass[ y1 ][ x1 ] = '#'; w--; }
					if( x2 < ass[ y1 ].length && ass[ y1 ][ x2 ] == '.' ){ ass[ y1 ][ x2 ] = '#'; w--; }
				}
				if( y2 < ass.length )
				{
					if( 0 <= x1               && ass[ y2 ][ x1 ] == '.' ){ ass[ y2 ][ x1 ] = '#'; w--; }
					if( x2 < ass[ y2 ].length && ass[ y2 ][ x2 ] == '.' ){ ass[ y2 ][ x2 ] = '#'; w--; }
				}
			}
		}
		if( w <= 0 ) return i;
	}
}
