# Let's draw some Atari ST bombs!

### Introduction

The Atari ST was a rather popular personal computer from the mid 80's to early 90's era, powered by a Motorola 68000 microprocessor. On this machine, the default behavior of the operating system for uncaught CPU exceptions was to display a row of bombs on the screen, as shown in the following picture:

Source: https://commons.wikimedia.org/wiki/File:Row_of_bombs.png
NB: Depending on the OS version, the bomb graphics may vary slightly. But let's take this one as reference.

The number of bombs depends on the exception vector, the most common ones being:

• ($008) Bus Error : 2 bombs • ($00c) Address Error : 3 bombs
• ($010) Illegal Instruction : 4 bombs ### Goal Your goal is to write a program or function that prints or outputs an ASCII art of such Atari ST bombs. ### Input An integer representing the number of bombs to display. Your code must support the most common values: 2, 3 and 4. Supporting less and/or more bombs is fine, but it is neither required nor subject to a bonus. ### Output The original bomb consists of a 16x16 pixel tile, represented here in both ASCII and binary: ....##.......... 0000110000000000 .#.#..#......... 0101001000000000 .......#........ 0000000100000000 #..#....#....... 1001000010000000 ..#...#####..... 0010001111100000 ......#####..... 0000001111100000 ....#########... 0000111111111000 ...###########.. 0001111111111100 ...###########.. 0001111111111100 ..#############. 0011111111111110 ..########.####. 0011111111011110 ...#######.###.. 0001111111011100 ...######.####.. 0001111110111100 ....#########... 0000111111111000 .....#######.... 0000011111110000 .......###...... 0000000111000000  In this challenge, each ASCII bomb must be stretched to twice its original width for a better rendering. Therefore, it will consist of 16 rows of 32 characters, using ## for 'ON' pixels and two spaces for 'OFF' pixels. All bomb tiles must be put side by side. Leading spaces are forbidden. Trailing spaces are also forbidden, except the ones that are actually part of the bomb tile (i.e. the 31st and 32nd columns) which must be present. You may include no more than one leading line-break and no more than one trailing line-break. ### Example Below is the reference output for two bombs, where mandatory line-breaks are marked as \n and tolerated extra line-breaks are marked as (\n): (\n) #### #### \n ## ## ## ## ## ## \n ## ## \n ## ## ## ## ## ## \n ## ########## ## ########## \n ########## ########## \n ################## ################## \n ###################### ###################### \n ###################### ###################### \n ########################## ########################## \n ################ ######## ################ ######## \n ############## ###### ############## ###### \n ############ ######## ############ ######## \n ################## ################## \n ############## ############## \n ###### ###### (\n)  (Of course, other line-break formats such as \r or \r\n may be used just as well.) ### Rules This is code-golf, so the shortest answer in bytes wins. Standard loopholes are forbidden. • I notice you've excluded non-ASCII-art forms, so an Atari ST machine-code function that crashes with the right number of bombs doesn't count. (The bomb isn't in the font, but the Atari ST has fun/easter-egg glyphs in its native character set, including characters 28–31 that are 4 pieces that form the image of J. R. "Bob" Dobbs from the satirical Church of the SubGenius. I remember writing a program that spammed those 4 glyphs at random screen positions, as a very early exercise in using text-drawing system calls :) – Peter Cordes Oct 5 '16 at 2:32 • @PeterCordes - That's right, it must be ASCII. However, you'd be allowed to read the bomb graphics from the ST ROM since there's no rule that prevents you from doing it. (Just mention the TOS version this is supposed to work on.) – Arnauld Oct 5 '16 at 11:48 • Oh WOW, that brings back memories. My first computer was an Atari ST. I remember those bombs with dread. – Rod Oct 6 '16 at 15:27 • Aside: "The number of bombs depends on the exception vector" - say what?! Any reason why they couldn't output the actual code/error? (Never had an ST, I'm from the Amiga camp... "Guru Meditation" and all that.) – MrWhite Oct 6 '16 at 21:02 ## 31 Answers # Jelly, 43 44 bytes +1 byte - forgot to double the characters (not that anyone noticed!) “¥vẏ)X;ndĊɓ¡ẹ3ċi}Ịɲ¡P"¦ḊƥṾ’b⁴‘ĖŒṙị⁾ #Ḥs⁴ẋ€³Y  TryItOnline ### How? Preparation was to compress the data as a run-length encoding of the original image: • Count the length of each run of 1s (space) or 0s (hash) in the image, ignoring new lines - yields a list: [4,2,11,1,1,...]; • Subtract one from each number - this gives a range of [0,15]; • Treat this as a base-16 number (enumerate the values, v, with index i in reverse and sum up 16**i*v = 19468823747267181273462257760938030726282593096816512166437); • Convert this to base-250: [5,119,249,42,...]; • Map into Jelly's code page as indexes: ¥vẏ)X;ndĊɓ¡ẹ3ċi}Ịɲ¡P Now the code evaluates this number, maps the 1s and 0s to space and hash characters*, doubles each, splits into lines and repeats each the appropriate number of times. * actually the implementation is performed modulo 2 to save bytes, so spaces are odd and hashes are even: “¥vẏ)X;ndĊɓ¡ẹ3ċi}Ịɲ¡P"¦ḊƥṾ’b⁴‘ĖŒṙị⁾ #Ḥs⁴ẋ€³Y - Main link: n “¥vẏ)X;ndĊɓ¡ẹ3ċi}Ịɲ¡P"¦ḊƥṾ’ - base 250 number, as above b⁴ - convert to base 16 (the run length - 1 list) ‘ - increment (vectorises) (the run length list) Ė - enumerate (pairs each with 1,2,3...) Œṙ - run length decode ([1,1,1,1,2,2,3,3,3,3,3,3,3,3,3,3,3,4,5,...]) ⁾ # - string " #" ị - index into (1 based and modular) (makes a bomb without line feeds) Ḥ - double (each char becomes a list of 2 chars) s⁴ - split into slices of length 16 ẋ€³ - repeat each input, n, times Y - join with line feeds  # 05AB1E, 575553 50 bytes Uses CP-1252 encoding. •ø6ŒY2l½î€ÈSL<eÆô‚˜3ª½¨ºE»D2Âô3•b15ôvy1J€D„# è¹×,  Try it online! Explanation As the output image only consists of 2 characters we can represent it as a binary number. We can ignore newlines as every line has the same length. We can ignore the last char of each row as it the same for all rows. We use the thinner image as it takes up less space and we can easily duplicate each character later. Using 1 to represent space and 0 to represent # we get the binary number: 111100111111111101011011111111111111101111111011011110111111110111000001111111111000001111111100000000011111000000000001111000000000001110000000000000110000000010000111000000010001111000000100001111100000000011111110000000111111111100011111 We then convert this to base-10 and then compress it to base 214, the maximum base in 05AB1E. The result of this is: •ø6ŒY2l½î€ÈSL<eÆô‚˜3ª½¨ºE»D2Âô3•  The meat of the program then consist of the following: <base encoded string> b # convert to binary 15ô # slice into pieces of 15 v # for each slice 1J # append a 1 €D # duplicate each character „# # push the string "# " è # use the list of binary digits to index into the string ¹× # repeat string input number of times , # and print with newline  # Pyth, 5756545351 50 bytes The code contains unprintable characters, so here's a reversible xxd hexdump. 00000000: 6a2a 4c51 6331 3673 2e65 2a79 6240 2220 j*LQc16s.e*yb@" 00000010: 2322 6b6a 4322 4c49 c142 3c60 0cca 9437 #"kjC"LI.B<...7 00000020: b383 76bb c246 c86d 4c04 99bd 3614 7022 ..v..F.mL...6.p" 00000030: 3137 17  Try it online. # JavaScript (ES6), 159154140 136 bytes Saved lots of bytes thanks to @Hedi and @Arnauld n=>[..."ￏﾵｿﻶ쀇쀇考萃쐇숇ﱿ"].map(x=>(f=q=>q?(q&1?" ":"##")+f(q>>1):"")(x.charCodeAt()).repeat(n)).join   That's 104 chars, but (sadly) 136 UTF-8 bytes. The string was generated with this snippet: console.log([ 0b1111111111001111, 0b1111111110110101, 0b1111111101111111, 0b1111111011110110, 0b1111100000111011, 0b1111100000111111, 0b1110000000001111, 0b1100000000000111, 0b1100000000000111, 0b1000000000000011, 0b1000010000000011, 0b1100010000000111, 0b1100001000000111, 0b1110000000001111, 0b1111000000011111, 0b1111110001111111 ].map(x=>(65535-x).toString(16)).join(",")) Using .replace instead of [...string].map is equally long: n=>"ￏﾵｿﻶ쀇쀇考萃쐇숇ﱿ".replace(/./g,x=>(f=q=>q?(q&1?" ":"##")+f(q>>1):"")(x.charCodeAt()).repeat(n)+ )  ### How it works Since each row of the raw data can be represented as a 16-bit number, we can store the entire file in a 16-char string. The compression algorithm takes each binary row, flips it and reverses it (since every row in the original ends in a 0, every row in the modified version now starts with a 1), then turns it into a char, and concatenates the resulting characters. To decompress it, we need to extract the charcode and turn its binary representation into a string of hashes and spaces. This can be done with a recursive function, like so: (f=q=>q?(q&1?" ":"##")+f(q>>1):"")(x.charCodeAt())  f repeatedly takes the last bit of q, selecting two spaces if it's 1 or two hashes if it's 0, then concatenates that with the result of running f in the rest of q. This is run on x.charCodeAt(), turning the char-code into the correct string of spaces and hashes. (There was a lot more drama here before, but the 4-byte-saving technique erased all of that.) After that, we can just repeat the string n times and add a newline. This is the shortest decompression method I have found, but feel free to suggest any possibly shorter methods. Other attempts at compressing the string: n=>[48,74,128,265,1988,1984,8176,16376,16376,32764,31740,15352,15864,8176,4064,896].map(x=>(f=q=>q?(q&1?" ":"##")+f(q>>1):"")(65535-x).repeat(n)).join  n=>"1c,22,3k,7d,1j8,1j4,6b4,cmw,cmw,pa4,oho,bug,c8o,6b4,34w,ow".split,.map(x=>(f=q=>q?(q&1?" ":"##")+f(q>>1):"")(65535-parseInt(x,36)).repeat(n)).join  n=>"30,4a,80,109,7c4,7c0,1ff0,3ff8,3ff8,7ffc,7bfc,3bf8,3df8,1ff0,fe0,380".split,.map(x=>(f=q=>q?(q&1?" ":"##")+f(q>>1):"")('0x'+x^65535)).repeat(n)).join   The first of these is 153 bytes, so none of them come anywhere near 136... • Could save some bytes with +x?'##':' ' instead of " #"[x].repeat(2) – Hedi Oct 3 '16 at 20:24 • @Hedi thanks, I knew there was a way to golf that bit. – ETHproductions Oct 3 '16 at 20:28 • Could you directly test the bits of x.charCodeAt() rather than converting it to binary? (I think that would save about 8 bytes.) – Arnauld Oct 3 '16 at 20:36 • Your compression algorithm sounds almost cryptographic. – Justin Oct 4 '16 at 17:29 • @Justin Damn, I was just about to comment that. – immibis Oct 6 '16 at 6:04 ## MS-DOS .COM file, 84 bytes OK. Just for fun because I cannot beat the 50 bytes... Tried under DOSbox as well as under MS-DOS 6.22 in a virtual machine. Under DOSbox the program works fine however under real MS-DOS the output will not be displayed correctly because DOS requires CR-LF instead of LF at the end of the line. (However the output is correct.) A 88 byte variant would use CR-LF at the end of the line. Here is the file: 0000 be 32 01 fc ad 89 c3 8a 36 82 00 80 ee 30 b9 10 0010 00 d1 c3 18 d2 80 ca 20 80 e2 23 b4 02 cd 21 cd 0020 21 e2 ee fe ce 75 e7 b2 0a cd 21 ad 85 c0 75 d5 0030 cd 20 00 0c 00 52 00 01 80 90 e0 23 e0 03 f8 0f 0040 fc 1f fc 1f fe 3f de 3f dc 1f bc 1f f8 0f f0 07 0050 c0 01 00 00  The assembler code (in AT&T syntax) looks like this: start: # Read data from "image:" mov$image,%si
cld
# Read the first 16 bytes
lodsw
nextLine:
# Use bx as shift register
mov %ax, %bx
# Read the number of bombs
mov 0x82,%dh
sub $'0',%dh nextBombInThisLine: # Number of characters mov$16, %cx
nextCharacter:
# Rotate the data# get the next bit to CY
rol $1, %bx # This results in 0x23 ('#') if CY is set, to 0x20 (' ') otherwise sbb %dl, %dl or$0x20, %dl
and $0x23, %dl # Print result character twice mov$2, %ah
int $0x21 int$0x21
# more Characters in this line?
loop nextCharacter
# More bombs to draw?
dec %dh
jnz nextBombInThisLine
# Print a newline
#        mov $13, %dl # <- Additional 4 bytes needed for "\r\n" # int$0x21    #    at the end of the line!
mov $10, %dl int$0x21
# Read the next 16 bytes# 0x0000 means: EOF
lodsw
test %ax,%ax
jnz nextLine
# End of program
int $0x20 image: # Here 34 bytes follow: # 16 16-bit-words "bitmap" for the bombs followed # by 0x0000 indicating the end of the bitmap  --- Edit --- I forgot to mention: The program must be started with the following command line: Name of the COM file + exactly one space character + Number of bombs (1-9) • Nice. We're still lacking a 68000 answer, but this one is getting closer. :-) – Arnauld Oct 4 '16 at 19:49 • objdump -dw output is a good way to show the raw binary, since you see which bytes are which instruction. I did that for gcd and adler32 answers. (As well as including commented source code for people to try themselves.) – Peter Cordes Oct 5 '16 at 2:53 # Python, 223 179 bytes ### Second approach: f=lambda n:'\n'.join(''.join(2*' #'[int(d)]for d in bin(int('0c0052000100908023e003e00ff81ffc1ffc3ffe3fde1fdc1fbc0ff807f001c0'[i:i+4],16))[2:].zfill(16))*n for i in range(0,64,4))  Try it on repl.it! Rather than creating a list of strings on-the-fly, there is a hard-coded hexadecimal string which is indexed and converted to binary; then each binary digit is turned into either ' ' or '#', which is duplicated and joined together ... etc. ### First approach: s=' ';b='##';f=lambda n:'\n'.join(n*l.ljust(32)for l in[s*4+b*2,(s+b)*2+s*2+b,s*7+b,b+s*2+b+s*4+b,s*2+b+s*3+b*5,s*6+b*5,s*4+b*9,s*3+b*11,s*3+b*11,s*2+b*13,s*2+b*8+s+b*4,s*3+b*7+s+b*3,s*3+b*6+s+b*4,s*4+b*9,s*5+b*7,s*7+b*3])  Try it on repl.it! This contains a hard-coded list of the strings of each line (not including trailing spaces) created by duplicating either ' ' or '##' a number of times. For each of these strings, they are padded with spaces until 32 characters in length, duplicated n times, then joined with newlines. • You can save a byte by switching to printing an unrolled generator, instead of joining on '\n'. So, lambda n:print(*(''.join(2*' #'[int(d)]for d in bin(int('0c0052000100908023e003e00ff81ffc1ffc3ffe3fde1fdc1fbc0ff807f001c0'[i:i+4],16))[2:].zfill(16))*n for i in range(0,64,4))). Also, you don't have to count the bytes needed to assign the lambda a name. So your score can be 176. – Morgan Thrapp Oct 5 '16 at 17:38 # C, 250240208 188 bytes d[]={3072,20992,256,36992,9184,992,4088,8188,8188,16382,16350,8156,8124,4088,2032,448,0},m,c,*i=d;f(k){for(;*i;i++,puts(""))for(c=k;c--;)for(m=32768;m;write(1,&"## "[m&*i?0:2],2),m>>=1);}  Switch to using a function. m,d[]={3072,20992,256,36992,9184,992,4088,8188,8188,16382,16350,8156,8124,4088,2032,448,0},*i=d;main(c,v)char**v;{for(;*i;puts(""),i++)for(c=atoi(v[1]);c--;)for(m=32768;m;write(1,&"## "[m&*i?0:2],2),m>>=1);}  Test like this.  main(c,v)char**v; { f(atoi(v[1])); }  a.exe 2 #### #### ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ########## ## ########## ########## ########## ################## ################## ###################### ###################### ###################### ###################### ########################## ########################## ################ ######## ################ ######## ############## ###### ############## ###### ############ ######## ############ ######## ################## ################## ############## ############## ###### ######  • You can save a few bytes by using the decimal representations of those hex numbers to lose the 0x. – Copper Oct 4 '16 at 11:34 • @Copper Thanks, I managed to shave quite a few bytes also using write in place of putchar. – cleblanc Oct 4 '16 at 13:20 # ///, 539 532 + no. of bombs bytes The first /// answer, displaying 4 bombs. The end four 1's can be replaced with any unary representation of the number of bombs you want to print (11 for 2, 111 for 3) /-/?|X//y/\/X//xy|//|/\/\///+/%@!|$/bcd|%/efg|@/hij|!/klm|?/nop|b/Bxc/Cxd/Dxe/Exf/Fxg/Gxh/Hxi/Ixj/Jxk/Kxl/Lxm/Mxn/Nxo/Oxp/Pxq/ss|r/tt|s/SS|t/TT|S/  |T/##|1/AX$+-$+?AXyAX$+-cd+?by$+-d+?cycd+-+?dyd+-fg@!?ey+-g@!?fyfg@!-@!?gyg@!-ij!?hy@!-j!?iyij!-!?jyj!-lm?ky!-m?lylm-?mym-opny-poyop|AXA/AA|bB/BB|cC/CC|dD/DD|eE/EE|fF/FF|gG/GG|hH/HH|iI/II|jJ/JJ|kK/KK|lL/LL|mM/MM|nN/NN|oO/OO|pP/PP|A/qtqqs|B/STSTsTqqS|C/qsSTqq|D/TsTqTqsS|E/sTsSrTqS|F/qsrTqS|G/qrrTsS|H/sSrrtTs|I/sSrrtTs|J/srrrTS|K/srrSrS|L/sSrtTStTs|M/sSrtSrs|N/qrrTsS|O/qSrtTq|P/qsStTqs|X/
/1111


Try it online!

If the input must be decimal, the following has 555 548 bytes (where the last digit can be changed to 1, 2, 3 or 4):

/-/?|X//y/\/X//xy|//|/\/\///4/13|3/12|2/11|^/tT|&/rr|*/sS|+/%@!|$/bcd|%/efg|@/hij|!/klm|?/nop|b/Bxc/Cxd/Dxe/Exf/Fxg/Gxh/Hxi/Ixj/Jxk/Kxl/Lxm/Mxn/Nxo/Oxp/Pxq/ss|r/tt|s/SS|t/TT|S/ |T/##|1/AX$+-$+?AXyAX$+-cd+?by$+-d+?cycd+-+?dyd+-fg@!?ey+-g@!?fyfg@!-@!?gyg@!-ij!?hy@!-j!?iyij!-!?jyj!-lm?ky!-m?lylm-?mym-opny-poyop|AXA/AA|bB/BB|cC/CC|dD/DD|eE/EE|fF/FF|gG/GG|hH/HH|iI/II|jJ/JJ|kK/KK|lL/LL|mM/MM|nN/NN|oO/OO|pP/PP|A/qtqqs|B/STSTsTqqS|C/q*Tqq|D/TsTqTq*|E/sT*rTqS|F/qsrTqS|G/q&T*|H/*&^s|I/*&^s|J/s&rTS|K/s&SrS|L/*r^S^s|M/*rtSrs|N/q&T*|O/qSr^q|P/q*^qs|X/ /4  Try it online! The most important parts of the code are that: | means // ABCDEFGHIJKLMNOP mean each line of the bomb respectively S means 2 spaces s means 4 spaces * means 6 spaces q means 8 spaces T means ## (2) t means #### (4) ^ means ###### (6) r means ######## (8) & means ################ (16) Most of the code is making sure that the bombs are printed side-by-side, not on top of each other. # CJam, 66 bytes "^a1{9\b aZ5w7qQAwndIUffO"136b2b1Ser0'#erG/ri*z{:_N}%  Try it online! (note that there are some unprintable characters in the code.) The bomb in encoded in as a number in binary using 1 for spaces (the leading space as 1 ensures we don't have to pad the binary representations), transposed, and then converted to string in base-136 (which produced the shortest string without wide-characters). These steps can be played with here. This answer then reverses the encoding, the main trick being to repeat the bomb before transposing, effectively concatenating each line of the bomb at once. The characters in each line can be then be doubled up with newlines inserted for the final output. # PHP, 138 104+32=136 bytes I had never thought that file was binary safe. I only wish I would have found a more interesting way to store the data; but nothing I tried beat raw binary. foreach(unpack("v*",file(b)[0])as$v)echo"
",str_repeat(strtr(sprintf("%016b",$v),[" ","##"]),$argv[1]);

• read binary data from file, unpack from little endian 16bit to array of int
• loop through array: print 16 digit binary to string, replace 0 with 2 spaces, 1 with ##,
repeat $argv[1] times, print result + newline run with -r binary data in file b: 0000000 0c00 5200 0100 9080 23e0 03e0 0ff8 1ffc 0000010 1ffc 3ffe 3fde 1fdc 1fbc 0ff8 07f0 01c0  code to generate the file: $f=fopen(b,wb);foreach(array_map(bindec,explode("
",
"0000110000000000
0101001000000000
0000000100000000
1001000010000000
0010001111100000
0000001111100000
0000111111111000
0001111111111100
0001111111111100
0011111111111110
0011111111011110
0001111111011100
0001111110111100
0000111111111000
0000011111110000
0000000111000000"))as$c)fputs($f,pack("v*",$c));fclose($f);

• You can save 2 bytes by using a leading line break rather than a trailing one and thus not having the space after the echo and by using an actual line break rather than the \n. – user59178 Oct 4 '16 at 8:13
• @user59178 I know. not so verbose please. – Titus Oct 4 '16 at 11:02

# MATL, 64636059 58 bytes

49:',cxJr(v9hW&waHBU=NL%)C9[$aoAN'F16ZaQEY"32e!' #'w)liX"  Try it online! ### Explanation The code uses a pre-compressed version of the 16×16 binary matrix. The pre-compressing (not part of the program) used two steps: 1. Run-length encoding of the matrix read in row-major order (first across, then down). 2. The resulting run-lengths range from 1 to 16, so the vector of run-lengths minus 1 was converted from base 16 to base 94 (to use all printable ASCII codes except single quote, which is not used because it would need escaping). The compressed string,  ',cxJr(v9hW&waHBU=NL%)C9[$aoAN'


is decompressed from base 94 to base 16:

                                   F16Za


The obtained vector of run-lenghts plus 1 is multipled by 2:

                                        QE


to perform the horizontal stretching.

The vector of run-lenghts contains 49 values. The original numbers to be repeated with those lengths should be [0 1 0 1 ... 0] (49 entries). But instead of that, it's shorter to use the vector [1 2 ... 49], which will be equally valid thanks to modular indexing. So the run-length decoding is

49:                                       Y"


The generated vector containis the runs of 1, 2, ...49, for a total of 512 entries. This is reshaped into a 16×32 matrix:

                                            32e!


and used as modular indices into the string ' #' to produce a single bomb:

                                                ' #'w)


Finally, horizontal repetition by a factor given by the input produces the desired result:

                                                      liX"


# Python 2: 143 bytes

n=input()
j=2
while j<258:print''.join(2*'# '[b>'0']for b in bin(int('62XI2JG3U2Q0COCDFCZAMC8A9LAP6W1ZMM4A59GC43M49ENF3Z',36))[j:j+16])*n;j+=16


It's at ideone

(I realised that direct encoding of the original bomb in base 36 made for shorter code in Python.)

The string was formed by treating spaces as 1s and hashes as 0s, and then converting to base 36. The program then converts back to binary and slices into lengths of 16 (with an offset of 2 for the '0b' at the front of Python's binary string) , converts to double spaces and double hashes, joins them up, repeats the string n times and prints.

Previous: Python 2, 169 166 163 bytes

n=input()
j=0
while j<512:print''.join(' #'[i%2]*2*(v+1)for i,v in enumerate(int(c,16)for c in'31A00010F07010308024A4885A4A3C2703360245035876A25'))[j:j+32]*n;j+=32


It's at ideone

Almost a port of my Jelly answer.

• Inefficient is good if it is shorter. Nice +1 – ElPedro Oct 4 '16 at 21:51

# Python 2.7, 144 141 bytes

x=input()
for i in range(16):print"".join(" #"[b<"1"]*2for b in bin(int("5ZCAZKAVTP6J04W4VZJ2BQDH5DASIKRS524V8SWRSIVWZEWC8V",36))[2+i::16]*x)


The bomb is written in binary with 1 for space, the leading 1 removes the need to pad binary representations. The bomb is transposed (much like in my CJam answer) and stored in base 36.

The program decodes the bomb to binary and iterates bits by a step of 16 effectively following the transposition (which is saves bytes over slicing a given line). The resultant line is concatenated, bits are replaced with doubled or #, and joined into a singe string.

• You can drop the leading zero from your base 36 number. – Jonathan Allan Oct 5 '16 at 0:48
• @JonathanAllan: Nice catch. I thought that was an O for some reason... – Linus Oct 5 '16 at 1:00

# C (gcc), 216 204 183 165 134 bytes

b(n,i){for(n*=16,i=--n*16;i--;i%n||puts(""))printf(L"àϸ\x7fc\xfde\xfee`\x1fff\xffe\xffe\x7fcǰᇰ䡀\x80⤀\x600"[i/n]&1<<i%n%16?"##":"  ");}


Try it online!

Written as a standalone program (201 183 151 bytes)

i=16;main(j,l)char**l;{for(;i--;puts(""))for(j=*l[1]*16-769;j--;printf(L"àϸ\x7fc\xfde\xfee`\x1fff\xffe\xffe\x7fcǰᇰ䡀\x80⤀\x600"[i]&1<<j%16?"##":"  "));}


Try it online!

This segfaults if a command line parameter is not supplied.

## Batch, 415 bytes

@echo off
set h=#####
set s=
for %%a in ("    ##%s%%s%" " # #  #%s%    " "%s%  #%s%   " "#  #    #%s%  " "  #%h%%s%" "%s% %h%%s%" "    %h%####   " "   %h%%h%#  " "   %h%%h%#  " "  %h%%h%### " "  %h%### #### " "   %h%## ###  " "   %h%# ####  " "    %h%####   " "%s%%h%##    " "%s%  ###%s% ")do call:l %1 %%a
exit/b
:l
set r=
for /l %%i in (1,1,%1) do call set r=%%r%%%~2
set r=%r: =  %
echo %r:#=##%


Note: the line set s= ends in 5 spaces. Accepts the count as a command-line parameter. Simply loops through each line of the bomb (compressed very slightly by removing runs of 5 identical characters) then repeats the bomb as many times as desired before finally duplicating each character.

# Python 2, 206205203199191188186184 160 bytes

z=input()
for y in 3072,20992,256,36992,9184,992,4088,8188,8188,16382,16350,8156,8124,4088,2032,448:print"".join(" #"[e>0]*2for e in map(int,bin(y+8**6)[5:]))*z


Looked at Hex for the number list but it didn't seem to save enough to make it worth the effort. Was hoping to be able to golf the code down but seem to have got as far as I can with this approach. Any additional hints gratefully received.

EDIT

-1 by changing e==1 to e>0. I always forget that one.

-2 by ignoring the length of the binary string, prepending 7 0's and taking only the last 16 elements. Works as there are never more than 7 leading 0's.

-4 because now that I have lost the second reference to the variable b I can use bin(y)[2:] directly in the map function taking it below the magic 200 :-)

-8 by using slice assignment on the second list. Learned something new this evening.

-3 with thanks to @Jonathan

-2 by using c=d=([0]*7+map(int,bin(y)[2:]))[-16:] instead of having c=d;

-2 again thanks to @Jonathan

-24 with thanks to @Linus

Output

python bombs.py
2
####                            ####
##  ##    ##                    ##  ##    ##
##                              ##
##    ##        ##              ##    ##        ##
##      ##########              ##      ##########
##########                      ##########
##################              ##################
######################          ######################
######################          ######################
##########################      ##########################
################  ########      ################  ########
##############  ######          ##############  ######
############  ########          ############  ########
##################              ##################
##############                  ##############
######                          ######

• " #"[e>0]*2 will work – Jonathan Allan Oct 4 '16 at 21:29
• DOH! How did I miss that one??? Thanks @ Jonathan – ElPedro Oct 4 '16 at 21:32
• ...the parentheses (...) can go too (RE: per my previous comment). – Jonathan Allan Oct 4 '16 at 21:53
• You can take it down to 170 with for y in ...:print"".join(" #"[e>0]*2for e in(([0]*7+map(int,bin(y)[2:]))[-16:]))*z – Jonathan Allan Oct 4 '16 at 22:02
• @Jonathan Thanks again. it's getting late here so I'll save that change for tomorrow so I don't mess it up completely. – ElPedro Oct 4 '16 at 22:05

# RProgN, 210 193 Bytes

Saved some bytes by switching 0=' ' 1='##' to 1=' ' 0=' ', this means i don't need to add the extra zeros back. Also, this means that now the B64 string that used to say "MAFIA" does not, This is sad.

'n' = => 64 -B 2 B ] 1 16 sub n rep \ 17 32 sub n rep '
' \ . . '1' '  ' replace '0' '##' replace } a'' = D4D/4/'' a DgQ/AH'' a DAIeAj'' a DgA8AB'' a DwB+AD'' a DcH/wf'' a D+/29/'' a Dz/63/'' a


## Explanation

'n' =                   # Associate the input with "n"
=>                      # Push a new function to the stack.
64 -B               # Take the value from the top of the stack, convert it to an integer from Base64
2 B                 # Take the value from the top of the stack, convert it from an integer to binary
]                   # Duplicate the top of the stack.
1 16 sub            # Push the substring from the top of the stack between 1 and 16, 1 indexed.
n                   # Push the input.
rep                 # Repeat, this gives us 'n' bombs, essentially.
\                   # Flip the values such that REPEATEDBOMB_ROW TEXT
17 32 sub           # Push the substring between 17 and 32.
n                   # Push the input
rep                 # Repeat
'                   # Push a new line
'                       # RProgN doesn't actually have escapes, so the raw newline is represented as a newline between qoutes.
\ . .               # Flip the values so we have LINE1 NEWLINE LINE2, then concatenate them all into one string.
'1' '  ' replace    # Replace all the 1's in the binary string with two spaces.
'0' '##' replace    # Replace all the 1's with two '#'s
} a'' =                 # Associate the function with 'a'
D4D/4/'' a              # Bottom two lines,
DgQ/AH'' a              # Next two up,
DAIeAj'' a              # Etc...
DgA8AB'' a              # Once This is done, the memory stack is implicitly printed from top to bottom.
DwB+AD'' a              # As such, the bomb is upside down.
DcH/wf'' a              # Each of these numbers represents two lines, which is why we do the substringing to split it.
D+/29/'' a              # This works out saving a few bytes.
Dz/63/'' a              # Implicitly printed output. Yay.


Pretty long, The expanding, printing and such of the compressed string is 105 of the bytes. Might be a bit more golfable, but atleast it works.

Input is implicitly on the stack, stack is implicitly printed.

## Output

        ####                            ####                            ####
##  ##    ##                    ##  ##    ##                    ##  ##    ##
##                              ##                              ##
##    ##        ##              ##    ##        ##              ##    ##        ##
##      ##########              ##      ##########              ##      ##########
##########                      ##########                      ##########
##################              ##################              ##################
######################          ######################          ######################
######################          ######################          ######################
##########################      ##########################      ##########################
################  ########      ################  ########      ################  ########
##############  ######          ##############  ######          ##############  ######
############  ########          ############  ########          ############  ########
##################              ##################              ##################
##############                  ##############                  ##############
######                          ######                          ######


## Try it!

<style>
#frame{
width:60em;
height:60em;
border:none;
}
</style>
<iframe id='frame' src="https://tehflamintaco.github.io/Reverse-Programmer-Notation/RProgN.html?rpn=%27n%27%20%3D%20%3D%3E%2064%20-B%202%20B%20%5D%201%2016%20sub%20n%20rep%20%5C%2017%2032%20sub%20n%20rep%20%27%0A%27%20%5C%20.%20.%20%271%27%20%27%20%20%27%20replace%20%270%27%20%27%23%23%27%20replace%20%7D%20a%27%27%20%3D%20D4D%2F4%2F%27%27%20a%20DgQ%2FAH%27%27%20a%20DAIeAj%27%27%20a%20DgA8AB%27%27%20a%20DwB%2BAD%27%27%20a%20DcH%2Fwf%27%27%20a%20D%2B%2F29%2F%27%27%20a%20Dz%2F63%2F%27%27%20a&input=1">Sorry, You need to support IFrame. Why don't you..?</iframe>

# PHP, 144140139138 136 bytes

Note: uses Windows-1252 encoding

for(;$j%=32*$argn or$r=intval(substr("01c02203k07d1j81j46b4cmwcmwpa4ohobugc8o6b434w0ow",$i++*3,3),36)*print~õ;)echo~ßÜ[$r>>$j++/2%16&1];


Run like this:

echo 2 | php -nR 'for(;$j%=32*$argn or$r=intval(substr("01c02203k07d1j81j46b4cmwcmwpa4ohobugc8o6b434w0ow",$i++*3,3),36)*print~õ;)echo~ßÜ[$r>>$j++/2%16&1];'


Or using IBM-850 encoding (135 bytes and prettier result):

echo 2 | php -nR 'for(;$j%=32*$argn or$r=intval(substr(~¤╬£¤══¤╠ö¤╚ø╬òÃ╬ò╦╔Ø╦£Æê£ÆêÅ×╦ÉùÉØèÿ£ÃÉ╔Ø╦╠╦ê¤Éê,$i++*3,3),36)*print~§;)echo~▀M[$r>>$j++/2%16&1];'

▓▓▓▓                            ▓▓▓▓
▓▓  ▓▓    ▓▓                    ▓▓  ▓▓    ▓▓
▓▓                              ▓▓
▓▓    ▓▓        ▓▓              ▓▓    ▓▓        ▓▓
▓▓      ▓▓▓▓▓▓▓▓▓▓              ▓▓      ▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓                      ▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓          ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓          ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓      ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓▓▓      ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓          ▓▓▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓▓▓          ▓▓▓▓▓▓▓▓▓▓▓▓  ▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓              ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓▓▓▓▓▓▓▓▓                  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓
▓▓▓▓▓▓                          ▓▓▓▓▓▓


# Explanation

This doesn't do any binary stuff and doesn't require an external file.

Every 16 bit number is reversed, then encoded as a base-36 number, padded with a leading 0 if necessary, so every 16 bits result in 3 bytes. Concatenating those results in 01c02203k07d1j81j46b4cmwcmwpa4ohobugc8o6b434w0ow. The code reverses the process so the bombs are printed correctly N times.

# Tweaks

• Saved 4 bytes by using only a single for-loop
• Saved a byte by printing a single char for each iteration and using string index instead of ternary
• Saved a byte by getting resetting $j to zero on line boundaries with %=. This gets rid of parentheses • Saved 2 bytes by using $argn

# GCC C 129 bytes

### ISO8859/ASCII

f(r,i,d){
for(;i<32;i+=2,puts(""))
for(d=15*r;--d;)
printf((*(int*)&("ÿóÿ­ÿþoÜüðààÀ!ÀCÀCàðø?þ"[i]))&(1<<d%15)?"  ":"##");
}


In one line:

f(r,i,d){for(;i<32;i+=2,puts(""))for(d=15*r;--d;)printf((*(int*)&("ÿóÿ­ÿþoÜüðààÀ!ÀCÀCàðø?þ"[i]))&(1<<d%15)?"  ":"##");}


Run with:

main(c,v)char**v;{f(atoi(v[1]),0)}


Compile source as ISO8859-x (ASCII).

NB óÿ­ÿþÿoÜüðààÀÀ!ÀCàCðøþ? should contain the invisible ASCII Codes but it has been broken due to the way StackExchange presents its content. Please see the ideaone link for proper test encoding Alternatively the original ASCII String is at : https://github.com/claydonkey/AtariBombs/blob/master/ISO8859_REPR2.txt

## Explanation

First a conversion of the hex representation of bombs [f3 ff ad ff fe ff 6f 7f dc 1f fc 1f f0 07 e0 03 e0 03 c0 01 c0 21 c0 43 e0 43 f0 07 f8 0f fe 3f] to UTF-8 (in the UTF-8 version the compiler stores the string as Wide Char Array - 2 or 4 bytes for each character at runtime but this is academic). Whereas UTF-8 characters would be stored as 2-4 bytes, these values are all within ISO-8859-1 (ASCII) and thus only require 1 byte. Also it is safe to be stored as ISO-8859-x (there are no 0x8_ or 0x9_ values). Therefore the text consumes 32 bytes in ISO-8859 and the routine consumes 135 bytes in total.

(NB wide chars are stored as a 16 bit integer in windows and 32bit in linux but again this is irrelevant to the task at hand)

Caveat: Not all the characters are displayable (the control characters below 0x20) .They are, however still present . Most web pages are utf-8/ 8859/1253 (https://w3techs.com/technologies/overview/character_encoding/all) so I reckon this is legit(shifting all values below 0x20 to printable ASCII should fix that).

### UTF-8

Here is the version closer to the original posting with UTF-8 encoded source. This consumes 173 bytes. The string itself being 50 bytes of the source. The routine is also longer as the ASCII bytes are now stored with padding 0's for the 16bit/32bit Wide Chars and have to be shifted instead of casted to uint16_t as above. I have kept this up as it can be verified with ideone which uses UTF-8 encoding.

*w=L"óÿ­ÿþÿoÜüðààÀÀ!ÀCàCðøþ?";
f(r,i,j,m){
for(i;i<32;i+=2,puts(""))
for(j=r;j--;)
for(m=65536;m>1;(m\=2,printf(((w[i]<<8)+w[i+1]&m)?"  ":"##")));}


Run with:

main(c,v)char**v;{f(atoi(v[1]),0)}


If you can set the implicit value to a 16bit integer in your complier you can omit the wchar_t type declaration of the Wide Char. Ideone doesn't complain so I reckon it's good to go.

Try it out on ideone

• Impressive. What encoding does this use? – DJMcMayhem Oct 7 '16 at 18:01
• Its compiled on MinGW GCC where a wide character is an uint16. Therefore the encoding is [16-bit type holding UTF-16 Unicode]. However, I think that because the characters are within 0xFF (16bit) they are extended ASCII. + So nothing special – claydonkey Oct 7 '16 at 18:19
• Sorry I have learnt a tad more about the encoding and may have been wrong about it being stored as UTF-16.please refer to the overhauled answer. – claydonkey Oct 14 '16 at 5:28

As a function with type Int -> String:

b z=concat$do y<-[0..15];"\n":[if odd$div 0x3800FE01FF03DF83BF87BFC7FFC3FF83FF81FF007C007C401090080004A0030(2^(16*y+x))then"##"else"  "|x<-[1..z]>>[0..15]]


Printing to IO directly will cost 5 bytes (or 6 if we prefer to return IO () rather than IO [()]):

b z=mapM putStr$do y<-[0..15];"\n":[if odd$div 0x3800FE01FF03DF83BF87BFC7FFC3FF83FF81FF007C007C401090080004A0030(2^(16*y+x))then"##"else"  "|x<-[1..z]>>[0..15]]


### C, 175 bytes

 x[]={48,74,128,265,1988,1984,8176,16376,16376,32764,31740,15352,15864,8176,4064,896};f(z,p){while(z++<16){p=1;while(p<<=1){printf("%s",p&(x[z]<<16|x[z])?"##":" ");}puts("");}}


concatenates each x to itself and makes p overflow to end each line.

• ah, I changed printf() to write when golfing and that broke it. test here ideone.com/JtHInD – user60119 Oct 5 '16 at 20:25

## Java, 228 bytes

import static java.lang.System.out;

public class Bombs
{
public static void main(String[] args)
{
new Bombs().d(2);
new Bombs().d(3);
new Bombs().d(4);
}

void d(int n){String s="";for(int x=16,r=0;r<16*n;x=16,s+=(++r%n==0?"\n":""))while(--x>=0)s+=((new int[]{1536,10496,128,18496,4592,496,2044,4094,4094,8191,8175,4078,4062,2044,1016,224}[r/n])&(1<<x))==0?"  ":"##";out.println(s);}

}

• I know it's been a year, but you can golf it to this: n->{String s="";for(int x,r=0;r<16*n;s+=(++r%n<1?"\n":""))for(x=16;x-->0;)s+=((new int[]{1536,10496,128,18496,4592,496,2044,4094,4094,8191,8175,4078,4062,2044,1016,224}[r/n])&(1<<x))<1?" ":"##";return s;} (205 bytes) Apart from using a Java 8 lambda, I've reduced more bytes by changing: the position of the x=16 (and changed while to for); 2x ==0 to <1; returning s instead of printing it (imports are also part of the byte-count btw..); --x>=0 to x-->0. Still, great answer, so +1! – Kevin Cruijssen Oct 4 '17 at 14:09
• @KevinCruijssen Thanks (consider posting this as an own answer). I'm not sooo active here on codegolf, and thus am not sure about the rules, but I think that in most cases, only counting the bytes of the function (and ignoring the imports) is allowed. – Marco13 Oct 4 '17 at 16:18
• It's a bit too similar to post as a separated answer, but I can understand if you don't want to edit your answer of over a year ago. :) I'll just leave it in the comment. And I'm afraid imports do indeed count toward the byte-count. – Kevin Cruijssen Oct 4 '17 at 17:32

# J, 89 bytes

|:@;@#&(<' #'{~2#|:16 16$}.2#.inv 95#.32x-~3 u:'u,:C>%}UwPXHn_C9wF.|U ap<{jH%O9 9wRThGs')  Encodes the string as a base-95 number, increments each digit by 32, then represents it by an ascii string. ## Explanation This is composed of two main parts. There is the constructing of the bomb, and the actual repetition. Let's for the moment refer to the bomb as b. Then, the code looks like: |:@;@#&(b)  When called with input k, this is equivalent to: |: ; (k#b)  b is a boxed bomb, so k#b makes k repetitions of b, ; flattens it vertically, and |: transposes the result. (The bomb b is itself constructed transposed.) Now, here is the bomb: <' #'{~2#|:16 16$}.2#.inv 95#.32x-~3 u:'u,:C>%}UwPXHn_C9wF.|U ap<{jH%O9 9wRThGs'


The string following is a base-95 encoded string with an offset of 32, so that all the characters fall into the ASCII range, and thankfully there are no 's that need to be escaped. 3 u: gets the char codes of the string, 32x-~ makes each number an extended number and subtracts 32 from it; 95#. converts to a base-95 number an 2#.inv converts it to a binary digit array. I added a leading 1 to the binary in order to make it a solid number, so I take it off with }.. I shape the array into a 16x16 table with 16 16$ then transpose it using |:. (Possible golf for later: transpose the literal encoded string.) 2# duplicates each character width-wise. We are left with a table of 0s and 1s. ' #'{~ maps 0s to ' ' and 1 to '#'. As thus, we are left with our bomb. ## Test case  |:@;@#&(<' #'{~2#|:16 16$}.2#.inv 95#.32x-~3 u:'u,:C>%}UwPXHn_C9wF.|U ap<{jH%O9 9wRThGs') 3
####                            ####                            ####
##  ##    ##                    ##  ##    ##                    ##  ##    ##
##                              ##                              ##
##    ##        ##              ##    ##        ##              ##    ##        ##
##      ##########              ##      ##########              ##      ##########
##########                      ##########                      ##########
##################              ##################              ##################
######################          ######################          ######################
######################          ######################          ######################
##########################      ##########################      ##########################
################  ########      ################  ########      ################  ########
##############  ######          ##############  ######          ##############  ######
############  ########          ############  ########          ############  ########
##################              ##################              ##################
##############                  ##############                  ##############
######                          ######                          ######


# BaCon, 229 227 195 bytes

A contribution in BASIC for sake of nostalgia. The variable 'a' determines the amount of bombs.

a=2:FOR x=0 TO 15:FOR y=1 TO a:FOR i=15 DOWNTO 0:?IIF\$(v[x]&INT(POW(2,i)),"##","  ");:NEXT:NEXT:?:NEXT:LOCAL v[]={3072,20992,256,36992,9184,992,4088,8188,8188,16382,16350,8156,8124,4088,2032,448}


Output:

        ####                            ####
##  ##    ##                    ##  ##    ##
##                              ##
##    ##        ##              ##    ##        ##
##      ##########              ##      ##########
##########                      ##########
##################              ##################
######################          ######################
######################          ######################
##########################      ##########################
################  ########      ################  ########
##############  ######          ##############  ######
############  ########          ############  ########
##################              ##################
##############                  ##############
######                          ######


f n=h n:f(div n 2)
h n|odd n=' '
h _='#'
g b=mapM_ putStrLn[[f 0xfc7ff01fe00fc207c40784038003c007c007e00ff83ff83bfef6ff7fffb5ffcf!!(xmod32div2+y*16)|x<-[0..32*b-1]]|y<-[0..15]]


# C (Atari TOS 2.06 US), 129 124 117 113 bytes

short*a=0xe013b0;main(j,l)char**l;{for(;*a++-224;puts(""))for(j=*l[1]*16-768;j--;printf(*a&1<<j%16?"##":"  "));}


This uses the bomb bitmap from the TOS ROM, which is slightly different from the one in the question. For other versions of TOS, you'll have to adjust the address pointed to by *a. Note that some emulator roms don't include the bomb bitmap!

If you don't provide a command line argument, several high resolution bitmapped bombs may be displayed :-)

### C++11, 252 bytes

#include <iostream>
using namespace std;string d("01c02203k07d1j81j46b4cmwcmwpa4ohobugc8o6b434w0ow");int main(){for(int i=0;i!=45;i+=3){int z=stoi(d.substr(i,3),NULL,36);for(unsigned long p=1;p!=1<<31;p<<=1){cout<<(((z<<16|z)&p)?"##":"  ");}puts("");}}


# SmileBASIC, 127 bytes

INPUT N
FOR J=0TO 15FOR K=1TO N
FOR I=0TO 14?" #"[1AND ASC("xxxxxxxxxxxxxxx"[I])>>J]*2;
NEXT
NEXT?NEXT


(Screenshot of version without doubled characters)
SB has a square font, so doubling the characters looks bad (and doesn't fit on the screen)
Non-ASCII characters have been replaced by x's.
Hex values: 0008,0002,0610,1F8A,3FC1,7FC1,7FF2,FFF4,FFF8,EFF0,73F0,7FC0,3FC0,1F80,0600
Since SB saves files in UTF-8, some of these count as 2 or 3 bytes.

• @Arnauld I don't know much about SmileBASIC, but given that there's a loop FOR K=1TO N with INPUT N, I think it displays the number of bombs given in the input. However, I must say that despite the square font, I believe the characters should still be doubled to keep consistent with the requirements (to avoid an advantage over other answers). You could keep the current one for a nicer-looking solution, but I think you should still add a correct solution.Once you add that, I'll upvote for the creative use of the UTF-8 characters! – HyperNeutrino Feb 5 '17 at 23:18
• @AlexL. Yes, my comment was prior to the code update. – Arnauld Feb 5 '17 at 23:22

# Ruby 2.x (lambda) - 157 bytes

Can probably be golfed further, but I like this version:

->n{puts "0c0052000100908023e003e00ff81ffc1ffc3ffe3fde1fdc1fbc0ff807f001c0".scan(/.{4}/).map{|x|(("%016b"%x.to_i(16)).tr("10","# ").chars.map{|c|c+c}*"")*n}}


Similar idea as the python version(s): break the string of hexadecimal encoded bombs into sections of 4 characters, convert to binary, translate 1 to # and 0 to , double every character, and print the resulting array.

Note that puts is used to print the array. This will print the array out one line per element.

# Excel VBA, 204 Bytes

Anonymous VBE Immediate window function that takes input from the range [A1] and outputs to the ActiveSheet Object

Cells.RowHeight=48:For i=0To[A1-1]:[A4,B2,C5,D4,D2,E1:F1,G2,H3,I4,G5:K6,E7:M7,D8:N9,C10:J11,K10:O10,O11,L11:N13,K13:K15,L14:L15,M14,D12:I13,J12,E14:G14,F15:G15,H14:J16].Offset(,16*i).Interior.Color=0:Next
`