# Exponentially Slimy Programming: Stacking Minecraft Slimes

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:

← 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 () 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 = 2:

N = 3:

N = 4:

N = 5:

N = 6:

Larger N should work just as well.

• I would upvote but I have no votes left. I'm leaving this comment so I'll remember to upvote tomorrow. Aug 20 '16 at 17:55
• I'm upvoting your comment because I've run out of upvotes too. Aug 20 '16 at 18:13
• "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? Aug 21 '16 at 11:06
• @Caridorc Doubling in each direction? Aug 21 '16 at 14:51
• @wizzwizz4 Yes, each pixel becomes 4, correct? Aug 21 '16 at 14:52

# MATL, 7776 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: ### 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

• "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? Aug 22 '16 at 10:04
• @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. Aug 22 '16 at 11:14
• 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 :"') Aug 22 '16 at 13:07

# 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.

• 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) Aug 22 '16 at 13:30

# JavaScript (ES7), 326 327 bytes

n=>{x=(d=document).body.appendChild(c=d.createElementcanvas).getContext2d;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.createElementcanvas).getContext2d;
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

Edits

• saved 1 byte - found an unnecessary trailing semicolon ;

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

• the colours seem slightly off in the image here. Did you perhaps screenshot with f.lux on? Aug 22 '16 at 4:39
• @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. Aug 22 '16 at 9:22
• @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. Aug 25 '16 at 18:12

# 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));}


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

• For some reason C answers are pretty elegant in my mind. Aug 22 '16 at 23:31

# Mathematica, 267255254225 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, #}] &

• 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 Aug 22 '16 at 7:35
• @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.)
– user58632
Aug 22 '16 at 8:09
• 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. Aug 22 '16 at 8:27
• Whoops, that's 4 bytes longer than it needs to be: #&[##&[#,#]&//@x] Aug 22 '16 at 8:30
• 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. Aug 22 '16 at 11:54

# Python 2.7: 424412405376 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\xc4n\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\xc4n\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\xc4n\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()

• any suggestions are more than welcome :) especially to shrink the template array Aug 22 '16 at 20:40
• 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. Aug 27 '16 at 8:48
• Ah, in Python 2, [0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)] may be better. Aug 27 '16 at 9:02
• Thanks @Sherlock9 being new to golfing, could you explain how this (I assume) change of base code works? Aug 30 '16 at 13:01
• 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. Aug 30 '16 at 13:48

# R, 378356346 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=3:
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


# Java 8, 512 bytes

import java.awt.*;n->new Frame(){{add(new Panel(){public void paint(Graphics g){for(int N=n,o=0,p=1,t,q,u;N-->0;o+=8*p,p*=2)for(t=(int)Math.pow(2,N);t-->0;g.setColor(new Color(116,196,96)),g.fillRect(o,q=u*t,u,u),g.setColor(new Color(110,170,90)),g.fillRect(p+o,p+q,6*p,6*p),g.fillRect(o,4*p+q,p,p),g.fillRect(3*p+o,q,p,p),g.fillRect(7*p+o,5*p+q,p,p),g.fillRect(3*p+o,7*p+q,p,p),g.setColor(Color.BLACK),g.fillRect(p+o,2*p+q,2*p,2*p),g.fillRect(5*p+o,2*p+q,2*p,2*p),g.fillRect(4*p+o,5*p+q,p,p))u=8*p;}});show();}}


Results for $$\n=4,5,6\$$:

Explanation:

import java.awt.*;       // Required import for almost everything
n->                      // Method with integer parameter and Frame return-type
new Frame(){           //  Create the Frame
{                     //   In an inner code-block:
public void paint(Graphics g){
//     Overwrite its paint method:
for(int N=n,    //      Create a copy of the (effectively final) input
o=0,    //      Offset integer, starting at 0
p=1,    //      Power integer, starting at 1
t,      //      Inner loop integer, starting uninitialized
q,u;    //      Temp integers, starting uninitialized
N-->0       //      Loop N in the range (n, 0]:
;           //        After every iteration:
o+=8*p,    //         Increase the offset by 8 times the power
p*=2)      //         And go to the next power by doubling it
for(t=(int)Math.pow(2,N);
//       Set t to 2^N
t-->0     //       Inner loop t in the range (2^N, 0]:
;         //         After every iteration:
g.setColor(new Color(116,196,96)),
//          Set the color to the lighter green
g.fillRect(o,q=u*t,u,u),
//          Draw the background rectangle,
//          and set q to u*t to save bytes
g.setColor(new Color(110,170,90)),
//          Change the color to the darker green
g.fillRect(p+o,p+q,6*p,6*p),
//          Draw the inner rectangle
g.fillRect(o,4*p+q,p,p),
//          Draw the left dot
g.fillRect(3*p+o,q,p,p),
//          Draw the top dot
g.fillRect(7*p+o,5*p+q,p,p),
//          Draw the right dot
g.fillRect(3*p+o,7*p+q,p,p),
//          Draw the bottom dot
g.setColor(Color.BLACK),
//          Change the color to black
g.fillRect(p+o,2*p+q,2*p,2*p),
//          Draw the left eye
g.fillRect(5*p+o,2*p+q,2*p,2*p),
//          Draw the right eye
g.fillRect(4*p+o,5*p+q,p,p))
//          Draw the mouth
u=8*p;}});  //        Set u to 8*p to save bytes
show();}}           //    And afterwards show the Frame
`