namespace AGC033.A
{
    using System.Collections.Generic;
    using System.Linq;
    using static System.Console;

    public struct Index
    {
        public int I;
        public int J;

        public override string ToString() => $"{I,3}  {J,3}";
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            var height = int.Parse(ReadLine().Split(' ')[0]);

            WriteLine(Solve(ReadLinesAsBool(height).ToList()));
        }

        /// <summary>
        /// Returns Black and White squares as ListListbool. **Black** is <see langword="true"/> 
        /// </summary>
        /// <param name="lines"></param>
        /// <returns></returns>
        public static IEnumerable<List<bool>> ReadLinesAsBool(int lines)
        {
            for (int i = 0; i < lines; i++)
            {
                // black == true
                yield return ReadLine().Select(c => c == '#').ToList();
            }
        }

        public static IEnumerable<List<bool>> WrapInput(List<List<bool>> m)
        {
            var hashi = Enumerable.Repeat(false, m[0].Count + 2).ToList();
            yield return hashi;
            foreach (var item in m)
            {
                var ret = new List<bool> { false };
                ret.AddRange(item);
                ret.Add(false);
                yield return ret;
            }
            yield return hashi;
        }
        /// <summary>
        /// returns surrounding square's address except edge
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private static IEnumerable<Index> GetSurroundingPoints(Index index)
        {
            if (index.I > 1)
                yield return new Index { I = index.I - 1, J = index.J };
            if (index.I < WidenMaxI - 1)
                yield return new Index { I = index.I + 1, J = index.J };
            if (index.J > 1)
                yield return new Index { I = index.I, J = index.J - 1 };
            if (index.J < WidenMaxJ - 1)
                yield return new Index { I = index.I, J = index.J + 1 };
        }

        private static int WidenMaxI;
        private static int WidenMaxJ;
        public static int Solve(List<List<bool>> _matrix)
        {
            return Impl3(_matrix);
        }
        //private static List<Poi>
        private static int Impl3(List<List<bool>> matrix)
        {
            var matrix_widen = WrapInput(matrix).ToList();
            WidenMaxI = matrix_widen.Count - 1;
            WidenMaxJ = matrix_widen[0].Count - 1;

            var count = 0;
            var blackList = new List<Index>();
            var nextBlackList = new List<Index>();
            for (int i = 0;
                i < matrix_widen.Count;
                i++)
            {
                blackList.AddRange(
                matrix_widen[i].Select((x, j) => new { V = x, Idx = new Index { I = i, J = j } })
                    .Where(x => x.V)
                    .Select(x => x.Idx)
                );
            }

            for (; ; count++)
            {
                foreach (var item in blackList)
                {
                    GetSurroundingPoints(item).Where(idx => !matrix_widen[idx.I][idx.J])
                        .ToList()
                        .ForEach(
                        idx =>
                        {
                            matrix_widen[idx.I][idx.J] = true;
                            nextBlackList.Add(idx);
                        }
                        );

                }
                if (nextBlackList.Count == 0) return count;

                blackList = nextBlackList;
                nextBlackList = new List<Index>();

            }
        }
    }
}


Measured memory_bytes: 38452