# Chain reaction of bombs

## Introduction:

Before the task, here is what every element does on the map:

Plain land (X): This does nothing.

Destroyed land (-): This is the same as plain land, but destroyed by a bomb.

The active bomb (!): On a map, this will destroy everything in a 3x3 square:

XXXXX                         XXXXX
XXXXX                         X---X
XX!XX     > will become >     X---X
XXXXX                         X---X
XXXXX                         XXXXX

The passive bomb (@): It does nothing, until it is detonated by another bomb. This also has a 3x3 square explosion radius:

XXXXX                         XXXXX
XXXXX                         XXXXX
XX@XX     > will become >     XX@XX (nothing happened)
XXXXX                         XXXXX
XXXXX                         XXXXX

But:

XXXXX                         XXXXX
XXXXX                         X---X
XX@XX     > will become >     ----X (both bombs have exploded)
X!XXX                         ----X
XXXXX                         ---XX

The nuke (~): It does nothing, until it is detonated by another bomb. The difference is that this bomb has a 5x5 square explosion radius:

XXXXX                         XXXXX
XXXXX                         XXXXX
XX~XX     > will become >     XX~XX (nothing happened)
XXXXX                         XXXXX
XXXXX                         XXXXX

But:

XXXXX                         -----
XXXXX                         -----
XX~XX     > will become >     ----- (both bombs have exploded)
X!XXX                         -----
XXXXX                         -----

• Given a 9x9 map, output the map after the chain reaction.
• You may provide a function or a program.
• This is , so the submission with the least amount of bytes wins!

## Test cases

Test case 1 (3 steps):

XXXXXXXXX           XXXXXXXXX
----XXXXX           ----XXXXX
XXXX@XXXX           XXXX@XXXX
XXXXXXXX-           XXX---XX-
XXXX@XXXX     >     ------XXX
XXXXXXXX-           ------XX-
XX~XXXXXX           -----XXXX
X!XXXXXX-           -----XXX-
XXXXXXXXX           -----XXXX

Test case 2 (2 steps):

XXXXXXXXX           XXXXXXXXX
XXXXXXXXX           XXXXXXXXX
XX~XXXXXX           XX~XXXXXX
---------           ---------
XXXX!XXXX     >     XXX---XXX
XXXXXXXXX           XXX------
XXX@@X@!X           XXX@@----
XXXXXXXXX           XXXXX----
XXXXXXXXX           XXXXXXXXX

Test case 3 (2 steps):

XXXXXXXXX           XXXXXXXXX
XXXXXXXXX           XXXXXXXXX
XX~XXXXXX           XX~XXXXXX
XXXXXXXXX           XXX---XXX
XXXX!XXXX     >     XXX---XXX
XXXXXXXXX           XXX------
XXX@@X@!X           XXX@@----
XXXXXXXXX           XXXXX----
XXXXXXXXX           XXXXXXXXX

Test case 4 (1 step):

XXXXXXXXX           XXXXXXXXX
XXXX-XXXX           XXXX-XXXX
XXXXXXXXX           XXX---XXX
XX-X!X-XX           XX-----XX
XXXXXXXXX     >     XXX---XXX
XX-----XX           XX-----XX
XXXX-XXXX           XXXX-XXXX
XXXXXXXXX           XXXXXXXXX
XXXXXXXXX           XXXXXXXXX

Test case 5 (9 steps):

!XXXXXXXX           ---XXXXXX
X@XXXXXXX           ----XXXXX
XX@XXXXXX           -----XXXX
XXX@XXXXX           X-----XXX
XXXX@XXXX     >     XX-----XX
XXXXX@XXX           XXX-----X
XXXXXX@XX           XXXX-----
XXXXXXX@X           XXXXX----
XXXXXXXX@           XXXXXX---

Test case 6 (9 steps):

XX@@@XXXX           ------XXX
XXXXXXXXX           ------XXX
~XXXXXXXX           ---XXXXXX
XXXXXXXXX           ---XXXXXX
~XXXXXXXX     >     ---XXXXXX
XXXXXXXXX           ---XXXXXX
~XXXXXXXX           ---XXXXXX
@XXXXXXXX           ---XXXXXX
!XXXXXXXX           ---XXXXXX

Test case 7 (3 steps):

!XXXXXXXX           ---XXXXXX
X@XXXXXXX           ----XXXXX
XX@XXXXXX           ----XXXXX
XXXXXXXXX           X---X----
XXXXXX@@!     >     XXXXX----
XXXXXXXXX           X---X----
XX@XXXXXX           ----XXXXX
X@XXXXXXX           ----XXXXX
!XXXXXXXX           ---XXXXXX
• My answer is significantly shorter than the accepted one. – Adám Jul 3 '17 at 22:30
• May base part of a workshop on this challenge? – Adám Jul 3 '19 at 19:01

# 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, 188168154 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

'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]

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.

• in the tio link, input (to the left of ">") is the same as output (to the right of ">"), is it supposed to look like that? – ngn Sep 25 '17 at 19:26
• @ngn Nicely spotted. The Disp function could never have worked. Updated to be an operator. Thanks. – Adám Sep 25 '17 at 19:41
• ...and a question: does @ count as 1 byte in classic? my guess is yes – ngn Sep 25 '17 at 19:42
• @ngn Yes. – Adám Sep 25 '17 at 19:43
• here's an idea for 61 bytes: '-'@({i/⍨∨⌿↑(↓⌈/¨|⍵∘.-i)≤3|'X@~-'⍳a[⍵]}⍣≡('!'=,a)/i←,⍳⍴a)⊢a←⎕ (⎕io←0) – ngn Sep 25 '17 at 19:47

# Java, 574562558549525 523 bytes

import java.util.*;interface B{static char[][]g=new char[9][9];static void d(int i,int j,int r){g[i][j]=45;for(int x=Math.max(i-r,0);x<Math.min(i+r+1,9);x++)for(int y=Math.max(j-r,0);y<Math.min(j+r+1,9);y++)if(g[x][y]==64){d(x,y,1);}else if(g[x][y]>99){d(x,y,2);}else g[x][y]=45;}static void main(String[]a){Scanner q=new Scanner(System.in);for(int i=0;i<9;i++){int j=0;for(char c:q.nextLine().toCharArray())g[i][j++]=c;}for(int j=0;j<9;j++)for(int k=0;k<9;k++)if(g[j][k]==33)d(j,k,1);for(char[]z:g)System.out.println(z);}}
• I know it's been quite a while since you've posted this. But you can golf a few things: Both '-' can be 45. Both Math.max(...,0) can be ...>0?...:0 (same could be done with Math.min(...,9) but it's the exact same amount of bytes. for(int i=0;i<9;i++){int j=0;for(char c:q.nextLine().toCharArray())g[i][j++]=c;}for(int j=0;j<9;j++)for(int k=0;k<9;k++)if(g[j][k]==33)d(j,k,1); can be int i=0,j;for(;i<9;i++){j=0;for(char c:q.nextLine().toCharArray())g[i][j++]=c;}for(i=0;i<9;i++)for(j=0;j<9;j++)if(g[i][j]<34)d(i,j,1);. And maybe you could make a function out of it instead of program. – Kevin Cruijssen Sep 25 '17 at 13:35

# APL (Dyalog Classic), 61 bytes

'-'@({i/⍨∨⌿↑(↓⌈/¨|⍵∘.-i)≤3|'X@~-'⍳a[⍵]}⍣≡('!'=,a)/i←,⍳⍴a)⊢a←⎕

Try it online!

a←⎕ evaluate input and assign to a

i←,⍳⍴a the indices (pairs of coords) of all cells

('!'=,a)/ filter only the initially active bombs

{ }⍣≡ perform a transformation on the list until it stabilizes

• 'X@~-'⍳a[⍵] substitute 0 for X, 1 for @, etc, 4 for anything else (!)

• 3| mod 3 to get the "radius" of impact; it must be greater or equal to the...

• (↓⌈/¨|⍵∘.-i)≤ ...Manhattan distances between cells in the list and all cells

• i/⍨∨⌿↑ get bitmask of which cells are affected and select those from i

'-'@( )⊢a put - at those positions