T minus time to ransom!

Python 2, 90 bytes

g=lambda a:min(min(a))or-~g(map(lambda*c:map(max,(0,)+c[:-1],c,c[1:]),*a))
lambda a:g(a)/2

Try it online!

Accepts a matrix as a list of lists of 0 and 1.

How it works

g=lambda a:min(min(a))or…

If the smallest element of the matrix is 1 (it is completely infected), return 1; otherwise…

                        -~g(…                                            )

return 1 plus the recursive result on the following modified matrix…

                            map(lambda*c:…                           ,*a)

for each old column c

                                         map(max,(0,)+c[:-1],c,c[1:])

produce a new row by zipping max over the down-shifted, original, and up-shifted versions of c. (map fills in the gap at the end of c[1:] with None, which is falsy and smaller than both 0 and 1.)

Each iteration of g computes all vertical infections, then transposes the matrix. This way, every 2 iterations of g compute all horizontal, vertical, and diagonal infections.

lambda a:g(a)/2

Because the base case of g with a fully infected matrix gave 1 rather than 0, the parity works out such that floored division by 2 always gives the correct result.

Tags:

Code Golf