108
\$\begingroup\$

Slimes are cube shaped enemies in Minecraft that break into multiple smaller versions of themselves when killed. For the purposes of this challenge we'll depict them as an 8×8 pixel image with 3 colors:

64x64 slime

8x8 slime ← True 8×8 version.

The precise RGB colors are:

  • 0, 0, 0 for the eyes and mouth
  • 110, 170, 90 for the central, darker green
  • 116, 196, 96 for the outer, lighter green

Challenge

Write a program or function that takes in a positive integer N and outputs an image of N sizes of slimes packed into a rectangle. Going from left to right, the image should follow the pattern of having:

  • A stack of 2(N-1) 8×8 slimes.
  • A stack of 2(N-2) 16×16 slimes.
  • A stack of 2(N-3) 32×32 slimes.
  • And so on until the stack only contains one slime.

The slime images larger than the 8×8 version (8x8 slime) are generated by nearest-neighbor upsampling (i.e. just doubling all the pixels). Note that you must use the exact slime design and colors given here.

The final image will contain 2N-1 slimes and be 2(N+3)-8 pixels wide and 2(N+2) pixels tall.

The image may be output in any common image file format, saved to a file or printed/returned as a raw data stream, or directly displayed during runtime.

The shortest code in bytes wins.

Examples

Your program should produce these exact results.

N = 1:

N = 1

N = 2:

N = 2

N = 3:

N = 3

N = 4:

N = 4

N = 5:

N = 5

N = 6:

N = 6

Larger N should work just as well.

\$\endgroup\$
  • 30
    \$\begingroup\$ I would upvote but I have no votes left. I'm leaving this comment so I'll remember to upvote tomorrow. \$\endgroup\$ – NoOneIsHere Aug 20 '16 at 17:55
  • 23
    \$\begingroup\$ I'm upvoting your comment because I've run out of upvotes too. \$\endgroup\$ – trichoplax Aug 20 '16 at 18:13
  • 4
    \$\begingroup\$ "The slime images larger than the 8×8 version () are generated by nearest-neighbor upsampling (i.e. just doubling all the pixels)." Did you mean quadruple all the pixels, make each pixel into a 2x2 square? \$\endgroup\$ – Caridorc Aug 21 '16 at 11:06
  • 1
    \$\begingroup\$ @Caridorc Doubling in each direction? \$\endgroup\$ – wizzwizz4 Aug 21 '16 at 14:51
  • \$\begingroup\$ @wizzwizz4 Yes, each pixel becomes 4, correct? \$\endgroup\$ – Caridorc Aug 21 '16 at 14:52
21
\$\begingroup\$

MATL, 77 76 74 bytes

:"')^.,9&Xze`}+.E=p'F3ZaQ8e@qWt3$Y"G@-W1X"]&h[OOO;11 17E]5*29 7U24hhE&vEYG

The code works in this commit, which is earlier than the challenge.

You can try it in MATL online. This interpreter is still experimental. If it doesn't work, try refreshing the page and pressing "Run" again.

Here's an example run in the offline interpreter:

enter image description here

Explanation

:                     % Input N implicitly. Generate range [1 2 ... N]
"                     % For each k in [1 2 ... N]
  ')^.,9&Xze`}+.E=p'  %   Compressed string
  F3Za                %   Decompress with target alphabet [0 1 2]
  Q                   %   Add 1
  8e                  %   Reshape into 8×8 array containing values 1, 2, 3
  @qW                 %   Push 2 raised to k-1
  t                   %   Duplicate
  3$Y"                %   Repelem: interpolate image by factor 2 raised to k-1
  G@-W                %   Push 2 raised to N-k
  1X"                 %   Repmat: repeat the array vertically. Gives a vertical strip
                      %   of repeated subimages
]                     % End for each
&h                    % Concatenate all vertical strips horizontally. This gives a big
                      % 2D array containing 1, 2, 3, which represent the three colors
[OOO;11 17E]5*        % Push array [0 0 0; 11 17 9] and multiply by 5
29 7U24hhE            % Push array [29 49 24] and multiply by 2
&vE                   % Concatenate the two arrays vertically and multiply by 2.
                      % This gives the colormap [0 0 0; 110 170 90; 116 196 96]
YG                    % Take the array and the colormap and display as an image
\$\endgroup\$
  • \$\begingroup\$ "Larger N should work just as well.", but yours seems to give Out Of Memory/index errors already at n = 9. Is this only the online interpreter, or does this happen in the offline version as well? \$\endgroup\$ – David Mulder Aug 22 '16 at 10:04
  • 1
    \$\begingroup\$ @DavidMulder I have tested offline (compiler running on Matlab R2015b, Windows 7 64 bits, 4 GB RAM) for input up to 11 and it works. For 11 the result is an 8192×16376 image. For 12 it would be 16384×32760 (536 megapixels), requiring over 4 GB of RAM, which is more than my laptop can handle. \$\endgroup\$ – Luis Mendo Aug 22 '16 at 11:14
  • 2
    \$\begingroup\$ I like how the code starts with a smiley that is holding back his tears because of the intense emotions this code makes him feel :"') \$\endgroup\$ – Tom Doodler Aug 22 '16 at 13:07
14
\$\begingroup\$

Dyalog APL, 118 113 bytes

('P3',⌽∘⍴,255,∊)(3↑(116 196 96)(110 170 90))[⊃,/i{⊃⍪/⍵⍴⊂⍺⌿⍺/8 8⍴∊22923813097005 926134669613412⊤¨⍨⊂32⍴3}¨⌽i←2*⍳⎕]

assuming ⎕IO=0

From right to left:

i←2*⍳⎕ powers 1 2 4 ... 2n-1

i{ }¨⌽i iterate over powers (with ) and reversed powers ()

⊤¨⍨⊂32⍴3 decode each of the numbers on the left as 32 ternary digits

8 8⍴∊ flatten and reshape to 8×8

⍺⌿⍺/ replicate each row and column times

⍵⍴⊂ take copies

⊃⍪/ and stack them vertically

⊃,/ join all results horizontally

3↑(116 196 96)(110 170 90) colours; 3↑ extends them with (0 0 0)

[ ] index the colours with each element of the matrix; result is a matrix of RGBs

('P3',⌽∘⍴,255,∊) is a "train" - a function that returns 'P3' followed by the reversed shape of the argument, 255, and the argument flattened.

\$\endgroup\$
  • \$\begingroup\$ I think you can write your program assuming ⎕IO←0 and just state it as a condition, outside of byte count. Many APL systems use that as a default. (Including yours LOL) \$\endgroup\$ – Tobia Aug 22 '16 at 13:30
11
\$\begingroup\$

JavaScript (ES7), 326 327 bytes

n=>{x=(d=document).body.appendChild(c=d.createElement`canvas`).getContext`2d`;c.width=2*(c.height=4*(p=2**n)));for(i=0;i<n;i++){c=-1;for(j of[...'0001000001111110022112200221122011111110011121110111111000010000'])for(x.fillStyle=['#74c460','#6eaa5a','#000'][j],c++,k=0;k<p;)x.fillRect(c%8*(_=2**i)+_*8,~~(c/8)*_+_*8*k++,_,_)}}

Ungolfed ES6 Version

Try it yourself.

(n=>{
    x=(d=document).body.appendChild(c=d.createElement`canvas`).getContext`2d`;
    c.width=2*(c.height=4*(p=Math.pow(2,n)));
    for(i=0;i<n;i++){
        c=-1;
        for(j of[...'0001000001111110022112200221122011111110011121110111111000010000'])
            for(x.fillStyle=['#74c460','#6eaa5a','#000'][j],c++,k=0;k<p;)
                x.fillRect(c%8*(_=Math.pow(2,i))+_*8,~~(c/8)*_+_*8*k++,_,_)
    }
})(4);

The only difference between the ES7 and ES6 version is using ** instead of Math.pow(). You can also see, how you can invoke the function – in this example with n=4.

Result

enter image description here


Edits

  • saved 1 byte - found an unnecessary trailing semicolon ;

This is pretty slow and might take some time for numbers greater 10.

\$\endgroup\$
  • 2
    \$\begingroup\$ the colours seem slightly off in the image here. Did you perhaps screenshot with f.lux on? \$\endgroup\$ – Jezzamon Aug 22 '16 at 4:39
  • \$\begingroup\$ @Jezzamon Thanks for pointing it out – I did notice that, too. There's a slight possibility that I might have chosen "Convert document's colors to the working space" while importing the screenshot into Photoshop. The image is fixed now. \$\endgroup\$ – insertusernamehere Aug 22 '16 at 9:22
  • \$\begingroup\$ @Giles - Appreciate your comment, and in SO, that'd be totally appropriate, but here, we don't change others' programs - we tell them in comments. \$\endgroup\$ – Not that Charles Aug 25 '16 at 18:12
7
\$\begingroup\$

C, 220 bytes

x,y,r;f(n){
printf("P3 %d %d 255 ",(8<<n)-8,4<<n);
for(y=0;y<4<<n;++y)for(r=0;r<n;++r)for(x=0;x<8<<r;++x)
puts("110 170 90\0 116 196 96\0 0 0 0"+12*
(117-"` t5L\rL\ru5tst5` "[x>>r+2|(y>>r)%8*2]>>(x>>r)%4*2&3));}

I added useless newlines for readability, score is without these newlines.

Defines a function f(n) that outputs a plain PPM image on stdout.

\$\endgroup\$
  • 1
    \$\begingroup\$ For some reason C answers are pretty elegant in my mind. \$\endgroup\$ – downrep_nation Aug 22 '16 at 23:31
7
\$\begingroup\$

Mathematica, 267 255 254 225 212 bytes

G=10{11,17,9};Image@Join[##,2]&@@Table[Join@@Table[ImageData@ImageResize[Image[{t={g=G+{6,26,6},g,g,G,g,g,g,g},f={g,a=##&[G,G,G],a,g},e={g,b=0g,b,G,G,b,b,g},e,{a,a,G,g},{g,a,b,a},f,t}/255],4*2^j],2^(#-j)],{j,#}]&

Saved 29 42 bytes thanks to Martin Ender

Golfing suggestions welcome, especially for constructing the 8 by 8 (by 3) array s. Unfortunately, there is no "ArrayResize" analogue for ImageResize, so the array needs to be converted to an image (Image) before resizing, and then back to an array (ImageData) to do the Joining.

Ungolfed:

(* dark green, light green, black *)
G = 10 {11, 17, 9};
g = G + {6, 26, 6};
b = 0 g;

(* abbreviation for triple G sequence, top row, forehead, eye level *)
a = ##&[G, G, G];
t = {g, g, g, G, g, g, g, g};
f = {g, a, a, g};
e = {g, b, b, G, G, b, b, g};

(* slime *)
s =
  {
    t,
    f,
    e,
    e,
    {a, a, G, g},
    {g, a, b, a},
    f,
    t
  }/255;

(* jth column *)
c[n_, j_] := Join @@ Table[ImageData@ImageResize[Image[s], 4*2^j], 2^(n - j)]

(* final program *)
Image@Join[##, 2] & @@ Table[c[#, j], {j, #}] &
\$\endgroup\$
  • 1
    \$\begingroup\$ b=0g. To generate s it might be shorter to encode the pixel values as a base-3 number but I'd have to try to be sure. In the meantime, you can save bytes by not defining b, g, f, e, t until you need them, and s doesn't need a name at all and neither does c. For 2^(j-1)8 you can use 4*2^j. Applying all of those, I end up at 225 bytes: pastebin.com/YnkUwvwV \$\endgroup\$ – Martin Ender Aug 22 '16 at 7:35
  • \$\begingroup\$ @MartinEnder Much gratitude, these are all very good suggestions! (Note to self: avoid naming things if possible, otherwise do the assignment at (rather than before) the first occurrence.) \$\endgroup\$ – lastresort Aug 22 '16 at 8:09
  • \$\begingroup\$ I don't have time to figure it out completely right now, but here is an idea to avoid the Image, ImageResize, ImageData stuff. This bit blows up an array by a factor of 2: #&@@{##&@@{#,#}&//@x} where x is the array. So if you do store the initial 8x8 grid in a variable x, and then do x=#&@@{##&@@{#,#}&//@x} after each use, you can generate the successive tiles quite easily. \$\endgroup\$ – Martin Ender Aug 22 '16 at 8:27
  • \$\begingroup\$ Whoops, that's 4 bytes longer than it needs to be: #&[##&[#,#]&//@x] \$\endgroup\$ – Martin Ender Aug 22 '16 at 8:30
  • \$\begingroup\$ Hm, I'm not getting this to work yet, but you can save some more by a) using ##~Join~2 and b) f={g,a=##&[G,G,G],a,g} and then replace every further occurrence of G,G,G with a as well. \$\endgroup\$ – Martin Ender Aug 22 '16 at 11:54
4
\$\begingroup\$

Python 2.7: 424 412 405 376 357 Bytes

I'm a bit new to golfing.... here we go

from numpy import*
import PIL
def c(n,col):e=log2((col+8)/8)//1;r=2**e;t=2**(n-e-1);return tile(repeat(array([0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)],dtype=int8).reshape([8,8])[:,(col-(8*r-8))//r],r),t)
n=input();i=PIL.Image.fromarray(column_stack([c(n,col) for col in range(2**(n+3)-8)]),mode='P');i.putpalette('t\xc4`n\xaaZ'+' '*762);i.show()

ungolfed and length tested..

from numpy import*
import PIL

def c(n,col): #creates array for a given column
    s = array([0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)],dtype=int8).reshape([8,8]) #slime template (golfed inline)
    e=log2((col+8)/8)//1 #exponent for tiles and repititions
    r=2**e #number of repitions (scale factor)
    t=2**(n-e-1) #number of tiles (vertically)
    return tile(
            repeat(
             s[:,(col-(8*r-8))//r] #select appropriate column from template
              ,r) #repeat it r times
               ,t) #tile it t times

n = input()
arr = column_stack([c(n,col) for col in range(2**(n+3)-8)]) #create image array by stacking column function
i=PIL.Image.fromarray(arr,mode='P'); #colormap mode
i.putpalette('t\xc4`n\xaaZ'+' '*762); #set colormap
i.show()

s = r'''from numpy import*
import PIL
def c(n,col):e=log2((col+8)/8)//1;r=2**e;t=2**(n-e-1);return tile(repeat(array([0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)],dtype=int8).reshape([8,8])[:,(col-(8*r-8))//r],r),t)
n=input();i=PIL.Image.fromarray(column_stack([c(n,col) for col in range(2**(n+3)-8)]),mode='P');i.putpalette('t\xc4`n\xaaZ'+' '*762);i.show()'''

print len(s)

edit1: removed sys.argv[1] in favor of raw_input() to save extra import statement

edit2: shortened PIL import: removed from Image added PIL.

edit3: Thanks @Sherlock9 for the hex encode of the slime template

edit4: didn't need function def and used input() instead of raw_input()

\$\endgroup\$
  • \$\begingroup\$ any suggestions are more than welcome :) especially to shrink the template array \$\endgroup\$ – Aaron Aug 22 '16 at 20:40
  • \$\begingroup\$ Something like using '0000100001111110111211100111111102211220022112200111111000001000' (your array backwards) converted from base 3 to base 16 0x2df0777ca228b9c18447a6fb. With that number, use code like this [0x2df0777ca228b9c18447a6fb//3**i%3 for i in range(64)] to get your integers in the correct order. \$\endgroup\$ – Sherlock9 Aug 27 '16 at 8:48
  • \$\begingroup\$ Ah, in Python 2, [0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)] may be better. \$\endgroup\$ – Sherlock9 Aug 27 '16 at 9:02
  • \$\begingroup\$ Thanks @Sherlock9 being new to golfing, could you explain how this (I assume) change of base code works? \$\endgroup\$ – Aaron Aug 30 '16 at 13:01
  • 1
    \$\begingroup\$ The second part is to get your array back from that number 0x2df0777ca228b9c18447a6fb. This is simple. For a simpler example, to get the 0th digit from 01221100, just divide by 3 0 times, and then take the last digit (using mod 3) to get 0. To take the 2nd digit, divide by 3 2 times, then mod 3 to get 1. The list comprehension just divides by 3 64 times to get your full array back. If you have any more questions, we can discuss them in the PPCG chat. \$\endgroup\$ – Sherlock9 Aug 30 '16 at 13:48
1
\$\begingroup\$

R, 378 356 346 334 bytes

f=function(n){r=rep;k=r(0,4);m=r(1,6);L=c();for(i in 1:n)L=cbind(L,r(max(L,0)+2^(n-i):1,e=2^(i-1)));png(w=sum(w<-4*2^(1:n)),h=sum(h<-r(8,2^(n-1))));layout(L,w,h);for(i in 1:max(L)){par(mar=k);image(matrix(c(0,0,0,1,k,0,m,0,0,1,1,1,2,r(1,10),0,0,r(r(c(2,1,2,0),e=2),2),m,k,1,k),nr=8),col=c("#74C460","#6EAA5A",1),ax=F,an=F)};dev.off()}

Saves as a png file. Indented, with linefeeds:

f=function(n){
    r=rep
    k=r(0,4)
    m=r(1,6)
    L=c()
    for(i in 1:n)L=cbind(L,r(max(L,0)+2^(n-i):1,e=2^(i-1)))
    png(w=sum(w<-4*2^(1:n)),h=sum(h<-r(8,2^(n-1))))
    layout(L,w,h)
    for(i in 1:max(L)){
        par(mar=k)
        image(matrix(c(0,0,0,1,k,0,m,0,
                       0,1,1,1,2,r(1,10),0,
                       0,r(r(c(2,1,2,0),e=2),2),
                       m,k,1,k),
                     nr=8),
              col=c("#74C460","#6EAA5A",1),ax=F,an=F)
    }
    dev.off()
}

N=2: N=2
N=3: N=3
N=4: N=4

Some explanations:

Here's the matrix that's being plotted (0 represent lightgreen, 1 darkgreen and 2 black; the matrix is tilted because columns are the y-axis and rows the x-axis):

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    0    0    0    1    0    0    0    0
[2,]    0    1    1    1    2    2    1    0
[3,]    0    1    1    1    2    2    1    0
[4,]    1    1    1    1    1    1    1    1
[5,]    0    1    2    1    1    1    1    0
[6,]    0    1    1    1    2    2    1    0
[7,]    0    1    1    1    2    2    1    0
[8,]    0    0    1    0    0    0    0    0

Each call to image plot that matrix (with each integer corresponding to a color). For N=4, here is L (the layout matrix, each unique number represents one single plot), w (the widths of the matrix columns) and h (the heights of the matrix rows):

> L
     [,1] [,2] [,3] [,4]
[1,]    8   12   14   15
[2,]    7   12   14   15
[3,]    6   11   14   15
[4,]    5   11   14   15
[5,]    4   10   13   15
[6,]    3   10   13   15
[7,]    2    9   13   15
[8,]    1    9   13   15
> w
[1]  8 16 32 64
> h
[1] 8 8 8 8 8 8 8 8
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.