Fill in the lakes, 2D The one-dimensional version of this problem was pretty easy, so here's a harder 2D version.

You are given a 2D array of land heights on standard input, and you have to figure out where the lakes will form when it rains.  The height map is just a rectangular array of the numbers 0-9, inclusive.

8888888888
5664303498
6485322898
5675373666
7875555787


You must output the same array, replacing all locations that would be underwater with *.

8888888888
566*****98
6*85***898
5675*7*666
7875555787


Water can escape diagonally, so there would be no lake in this configuration:

888
838
388


shortest code wins.  Your code must handle sizes up to 80 wide and 24 high.

Three more examples:

77777    77777
75657    7*6*7
75757 =&gt; 7*7*7
77677    77677
77477    77477

599999    599999
933339    9****9
936639 =&gt; 9*66*9
935539    9*55*9
932109    9****9
999999    999999

88888888    88888888
84482288    8**8**88
84452233 =&gt; 8**5**33
84482288    8**8**88
88888888    88888888
Haskell, 258 characters

a§b|a&lt;b='*'|1&lt;3=a
z=[-1..1]
l m=zipWith(§)m$(iterate(b.q)$b(\_ _-&gt;'9'))!!(w*h)where
 w=length m`div`h
 h=length$lines m
 q d i=max$minimum[d!!(i+x+w*y)|x&lt;-z,y&lt;-z]
 b f=zipWith(\n-&gt;n`divMod`w¶f n)[0..]m
 (j,i)¶g|0&lt;i&amp;&amp;i&lt;w-2&amp;&amp;0&lt;j&amp;&amp;j&lt;h-1=g|1&lt;3=id
main=interact l


Example run:

$&gt; runhaskell 2638-Lakes2D.hs &lt;&lt;TEST
&gt; 8888888888
&gt; 5664303498
&gt; 6485322898
&gt; 5675373666
&gt; 7875555787
&gt; TEST
8888888888
566*****98
6*85***898
5675*7*666
7875555787


Passes all unit tests. No arbitrary limits on size.




Edit (281 → 258): don't test for stability, just iterate to the upper bound; stop passing constant argument m