Programação exponencialmente viscosa: empilhamento de slimes do Minecraft

108

Slimes são inimigos em forma de cubo no Minecraft que se dividem em várias versões menores de si mesmos quando mortos. Para os propósitos deste desafio, vamos descrevê-los como uma imagem de 8 × 8 pixels com 3 cores:

Lodo de 64x64

Lodo 8x8 ← Verdadeira versão 8 × 8.

As cores RGB precisas são:

  • 0, 0, 0 para os olhos e boca
  • 110, 170, 90 para o verde central mais escuro
  • 116, 196, 96 para o exterior, verde mais claro

Desafio

Escreva um programa ou função que receba um número inteiro positivo N e produza uma imagem de N tamanhos de slimes compactados em um retângulo. Indo da esquerda para a direita, a imagem deve seguir o padrão de ter:

  • Uma pilha de 2 (N-1) 8 × 8 limos.
  • Uma pilha de 2 (N-2) 16 × 16 limos.
  • Uma pilha de 2 (N-3) 32 x 32 limos.
  • E assim por diante até que a pilha contenha apenas um lodo.

As imagens de slime maiores que a versão 8 × 8 ( Lodo 8x8) são geradas pela upsampling do vizinho mais próximo (ou seja, apenas dobrando todos os pixels). Observe que você deve usar o design exato do lodo e as cores fornecidas aqui.

A imagem final conterá 2 N -1 slimes e terá 2 (N + 3) -8 pixels de largura e 2 (N + 2) pixels de altura.

A imagem pode ser impressa em qualquer formato de arquivo de imagem comum, salva em um arquivo ou impressa / retornada como um fluxo de dados brutos ou exibida diretamente durante o tempo de execução.

O código mais curto em bytes vence.

Exemplos

Seu programa deve produzir esses resultados exatos.

N = 1:

N = 1

N = 2:

N = 2

N = 3:

N = 3

N = 4:

N = 4

N = 5:

N = 5

N = 6:

N = 6

N maior deve funcionar da mesma forma.

Passatempos de Calvin
fonte
30
Gostaria de votar, mas não tenho mais votos. Estou deixando este comentário, então lembrarei de votar amanhã.
NoOneIsHere
23
Estou votando positivamente no seu comentário, porque também fiquei sem votos.
Trichoplax
4
"As imagens de lodo maiores que a versão 8 × 8 () são geradas pela upsampling do vizinho mais próximo (ou seja, apenas dobrando todos os pixels)." Você quis dizer quadruplicar todos os pixels, transformar cada pixel em um quadrado 2x2?
Caridorc 21/08/16
11
@Caridorc Dobrando em cada direção?
Wizzwizz4
@ wizzwizz4 Sim, cada pixel se torna 4, correto?
Caridorc 21/08/16

Respostas:

21

MATL , 77 76 74 bytes

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

O código funciona nesse commit , que é anterior ao desafio.

Você pode experimentá-lo online no MATL . Este intérprete ainda é experimental. Se não funcionar, tente atualizar a página e pressione "Executar" novamente.

Aqui está um exemplo executado no interpretador offline:

insira a descrição da imagem aqui

Explicação

:                     % 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
Luis Mendo
fonte
"N maior deve funcionar da mesma maneira.", Mas o seu parece apresentar erros de falta de memória / índice já em n = 9. Esse é apenas o intérprete on-line ou também acontece na versão off-line?
David Mulder
11
@DavidMulder Testei offline (compilador em execução no Matlab R2015b, Windows 7 64 bits, 4 GB de RAM) para entrada 11e funciona. Para 11o resultado, há uma imagem 8192 × 16376. Pois 12seria 16384 × 32760 (536 megapixels), exigindo mais de 4 GB de RAM, o que é mais do que meu laptop pode suportar.
Luis Mendo
2
Eu gosto de como o código começa com um smiley que está escondendo suas lágrimas por causa das emoções intensas que esse código o faz sentir: "')
Tom Doodler em 22/08/16
14

Dyalog APL, 118 113 bytes

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

assumindo ⎕IO=0

Da direita para esquerda:

i←2*⍳⎕ potências 1 2 4 ... 2 n-1

i{ }¨⌽iitera sobre potências (com ) e potências reversas ( )

⊤¨⍨⊂32⍴3 decodificar cada um dos números à esquerda como 32 dígitos ternários

8 8⍴∊ achatar e remodelar para 8 × 8

⍺⌿⍺/replicar cada linha e coluna vezes

⍵⍴⊂tirar cópias

⊃⍪/ e empilhá-los verticalmente

⊃,/ juntar todos os resultados horizontalmente

3↑(116 196 96)(110 170 90)cores; 3↑estende-os com(0 0 0)

[ ]indexe as cores com cada elemento da matriz; resultado é uma matriz de RGBs

('P3',⌽∘⍴,255,∊)é um "trem" - uma função que retorna 'P3'seguida pela forma invertida do argumento 255, e o argumento é achatado.

ngn
fonte
Eu acho que você pode escrever seu programa assumindo ⎕IO←0e apenas declará-lo como uma condição, fora da contagem de bytes. Muitos sistemas APL usam isso como padrão. (Incluindo o seu LOL)
Tobia
11

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++,_,_)}}

Versão ES6 Ungolfed

Tente você mesmo.

(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);

A única diferença entre a versão ES7 e ES6 é usar em **vez de Math.pow(). Você também pode ver como pode chamar a função - neste exemplo com n=4.

Resultado

insira a descrição da imagem aqui


Editar% s

  • economizou 1 byte - encontrou um ponto e vírgula desnecessário;

Isso é bem lento e pode levar algum tempo para números maiores que 10.

insertusernamehere
fonte
2
as cores parecem um pouco desbotadas na imagem aqui. Você talvez capturou a tela com o f.lux on?
precisa saber é
@ Jezzamon Obrigado por apontar - eu notei isso também. Há uma pequena possibilidade de que eu poderia ter escolhido " Conversão de cores do documento no espaço de trabalho " ao importar a imagem em Photoshop. A imagem está corrigida agora.
usar o seguinte comando
@Giles - aprecie seu comentário e, em SO, isso seria totalmente apropriado, mas aqui, não mudamos os programas de outras pessoas - dizemos a eles nos comentários.
Não que Charles
7

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

Eu adicionei novas linhas inúteis para facilitar a leitura, a pontuação é sem essas novas linhas.

Define uma função f(n)que gera uma imagem PPM simples no stdout.

orlp
fonte
11
Por alguma razão, as respostas C são bastante elegantes em minha mente.
downrep_nation
7

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

Economizou 29 42 bytes graças a Martin Ender

Sugestões de golfe são bem-vindas, especialmente para a construção da matriz 8 por 8 (por 3) s. Infelizmente, não há " ArrayResize" analógico para ImageResize, portanto, a matriz precisa ser convertida em uma imagem ( Image) antes de redimensionar e, em seguida, voltar a uma matriz ( ImageData) para fazer isso Join.

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, #}] &
último recurso
fonte
11
b=0g. Para gerá- slo, pode ser mais curto codificar os valores de pixel como um número base 3, mas eu teria que tentar ter certeza. Enquanto isso, você pode salvar bytes por não definir b, g, f, e, taté que você precisa deles, e snão precisa de um nome em tudo e nem c. Para 2^(j-1)8você poder usar 4*2^j. Aplicando tudo isso, acabo com 225 bytes: pastebin.com/YnkUwvwV
Martin Ender
@MartinEnder Muita gratidão, essas são todas muito boas sugestões! (Note to self: evitar nomear as coisas, se possível, caso contrário, fazer a atribuição em (e não antes) a primeira ocorrência.)
LastResort
Eu não tenho tempo para descobrir isso completamente agora, mas aqui está uma ideia para evitar o Image, ImageResize, ImageDatamaterial. Este bit explode uma matriz por um fator de 2: #&@@{##&@@{#,#}&//@x}onde xestá a matriz. Portanto, se você armazenar a grade 8x8 inicial em uma variável xe x=#&@@{##&@@{#,#}&//@x}depois de cada uso, poderá gerar os blocos sucessivos facilmente.
Martin Ender
Opa, isso é 4 bytes a mais do que precisa ser:#&[##&[#,#]&//@x]
Martin Ender
Hm, eu não estou recebendo este trabalho ainda, mas você pode economizar um pouco mais por um) usando ##~Join~2e b) f={g,a=##&[G,G,G],a,g}e, em seguida, substituir cada ocorrência de ainda mais G,G,Gcom abem.
Martin Ender
4

Python 2.7: 424 412 405 376 357 bytes

Eu sou um pouco novo no golfe .... aqui vamos nós

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 e comprimento testado ..

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: removido sys.argv[1]em favor de raw_input()para salvar uma declaração de importação extra

edit2: importação PIL reduzida: removido from ImageadicionadoPIL.

edit3: Obrigado @ Sherlock9 pela codificação hexadecimal do modelo slime

edit4: não precisava da função def e usada em input()vez deraw_input()

Aaron
fonte
Todas as sugestões são muito bem-vindos :) especialmente para encolher a matriz modelo
Aaron
Algo como usar '0000100001111110111211100111111102211220022112200111111000001000'(sua matriz para trás) convertido da base 3 para a base 16 0x2df0777ca228b9c18447a6fb. Com esse número, use um código como esse [0x2df0777ca228b9c18447a6fb//3**i%3 for i in range(64)]para obter seus números inteiros na ordem correta.
Sherlock9
Ah, no Python 2, [0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)]pode ser melhor.
Sherlock9
Obrigado @ Sherlock9 por ser novo no golfe, você poderia explicar como essa alteração (presumo) do código base funciona?
30516 Aaron
11
A segunda parte é recuperar sua matriz desse número 0x2df0777ca228b9c18447a6fb. Isto é simples. Para um exemplo mais simples, para obter o 0th-dígito 01221100, divida por 3 0vezes e, em seguida, pegue o último dígito (usando o mod 3) para obter 0. Para pegar o segundo dígito, divida por 3 2vezes e depois mod 3 para obter 1. A compreensão da lista é dividida em 3 64vezes para recuperar toda a sua matriz. Se você tiver mais perguntas, podemos discuti-las no chat do PPCG .
Sherlock9
1

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()}

Salva como um arquivo png. Recuado, com alimentação de linha:

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:N = 2
N = 3
N = 4

Algumas explicações:

Aqui está a matriz que está sendo plotada (0 representa verde claro, 1 verde escuro e 2 preto; a matriz é inclinada porque as colunas são o eixo y e enfileira o eixo x):

     [,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

Cada chamada para imageplotar essa matriz (com cada número inteiro correspondente a uma cor). Para N = 4, aqui está L (a matriz de layout, cada número único representa um único gráfico), w (as larguras das colunas da matriz) eh (as alturas das linhas da matriz):

> 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
plannapus
fonte