Chain reaction of bombs

Matlab, 120 111 bytes

function f=c(f);c=@(x,i)conv2(x+0,ones(i),'s');a=c(f<34,3);for k=f;a=c(a&f<65,3)|a;a=c(a&f>99,5)|a;end;f(a)='-'

Convolution is the key to success.

The idea is following: Find the active bomb. Enlarge this area to a 3x3 square. Find new affected bombs, enlarge the correspoding areas to the corresponding size and add those to the previously destroyed area. Repeat this enough times (in my case as many times as we have input characters, just because that is the shortest variant) to be sure that we reached a stationary point (=no more exploding bombs). Then set all the destroyed area to - and display the result.

The input is assumed to be a matrix of characters, e.g.

['!XXXXXXXX';
'X@XXXXXXX';
'XX@XXXXXX';
'XXX@XXXXX';
'XXXX@XXXX';
'XXXXX@XXX';
'XXXXXX@XX';
'XXXXXXX@X';
'XXXXXXXX@'];

Retina, 188 168 154 152 bytes

Bytes counted as ISO 8859-1.

+Tm`@~X!:`!:\-`(.)?.?.(.?(?<1>.)?)(?<=(:|(?(1)_)!|^(?(5)_)(?<-5>.)*(:|(?(1)_)!)(?<1>.*¶)?.*¶(.)*.|(?=(.)*¶.*(?<1>¶.*)?(:|(?(1)_)!)(?<-6>.)*(?(6)_)$))\2)

Try it online!

This is more of a proof of concept. There is a horrible amount of duplication between bombs and nukes, which I'll try to get rid of before adding an explanation. Well, I got rid of that duplication but it increased the complexity significantly so it didn't actually result in huge savings...


APL (Dyalog), 56 chars or 62 bytes*

My colleague Marshall came up with an elegant solution, 21 characters shorter than mine:

{'-'@(({1∊⍵≥∘.⌈⍨5⍴1+4↑1}⌺5 5×∘(('X'≠⍵)+'~'=⍵))⍣≡'!'∘=)⍵}

Try it online!

{} anonymous function where the argument is represented by

'-'@()⍵dash at the positions masked by the following tacit function:

  '!'∘= Boolean where exclamation point equals the argument

  ()⍣≡ apply the following tacit function until nothing more changes:

   ×∘() multiply by the following constant:

    '~'=⍵ Boolean where tilde equals the original argument

    ()+ to that, add:

     'X'≠⍵ Boolean where X is different from the original argument

   {}⌺5 5 for each, apply the following function on the 5×5 area centered on it:

    4↑1 take the first four elements of one, padding with zeros [1,0,0,0]

    1+ add one [2,1,1,1]

    5⍴ reshape cyclically into length five [2,1,1,1,2]

    ∘.⌈⍨ maximum table with itself on both axes

    ⍵≥ Boolean where the corresponding neighbours are greater than or equal to that

    1∊ Boolean if any is true


* Just replace with ⎕U233A under Classic for single byte per character.