Programmazione esponenzialmente viscosa: impilare le melme di Minecraft


108

Le melme sono nemici a forma di cubo in Minecraft che si rompono in più versioni più piccole di se stessi quando vengono uccisi. Ai fini di questa sfida, li descriveremo come un'immagine di 8 × 8 pixel con 3 colori:

Melma 64x64

Melma 8x8 ← Versione 8 × 8 vera.

I colori RGB precisi sono:

  • 0, 0, 0 per gli occhi e la bocca
  • 110, 170, 90 per il verde centrale, più scuro
  • 116, 196, 96 per l'esterno, verde più chiaro

Sfida

Scrivi un programma o una funzione che accetta un numero intero positivo N e genera un'immagine di N dimensioni di melma racchiuse in un rettangolo. Passando da sinistra a destra, l'immagine dovrebbe seguire il modello di avere:

  • Una pila di 2 (N-1) 8 × 8 melme.
  • Una pila di 2 (N-2) 16 × 16 melme.
  • Una pila di 2 (N-3) 32 × 32 melme.
  • E così via fino a quando la pila contiene solo una melma.

Le immagini di melma più grandi della versione 8 × 8 ( Melma 8x8) sono generate dal upsampling del vicino più vicino (cioè raddoppiando semplicemente tutti i pixel). Si noti che è necessario utilizzare il design esatto della melma e i colori indicati qui.

L'immagine finale conterrà 2 N -1 melme e sarà larga 2 (N + 3) -8 pixel e alta 2 (N + 2) pixel.

L'immagine può essere emessa in qualsiasi formato di file immagine comune, salvata su un file o stampata / restituita come flusso di dati non elaborati o visualizzata direttamente durante il runtime.

Vince il codice più breve in byte.

Esempi

Il tuo programma dovrebbe produrre questi esatti risultati.

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 più grande dovrebbe funzionare altrettanto bene.


30
Voterei ma non mi sono rimasti voti. Lascio questo commento quindi mi ricorderò di votare domani.
— NoOneIsHere

23
Sto votando il tuo commento perché ho finito anche i voti.
— trichoplax,

4
"Le immagini di melma più grandi della versione 8 × 8 () sono generate dal upsampling del vicino più vicino (cioè raddoppiando semplicemente tutti i pixel)." Intendevi quadruplicare tutti i pixel, trasformare ogni pixel in un quadrato 2x2?
— Caridorc,

1
@Caridorc Raddoppiando in ogni direzione?
— wizzwizz4,

@ wizzwizz4 Sì, ogni pixel diventa 4, giusto?
— Caridorc,

Risposte:


21

MATL , 77 76 74 byte

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

Il codice funziona in questo commit , che è precedente alla sfida.

Puoi provarlo in MATL online . Questo interprete è ancora sperimentale. Se non funziona, prova ad aggiornare la pagina e premi nuovamente "Esegui".

Ecco un esempio eseguito nell'interprete offline:

inserisci qui la descrizione dell'immagine

Spiegazione

:                     % 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

"La N più grande dovrebbe funzionare altrettanto bene.", Ma la tua sembra dare errori di memoria insufficiente / indice già a n = 9. Questo è solo l'interprete online o succede anche nella versione offline?
— David Mulder,

1
@DavidMulder Ho testato offline (compilatore in esecuzione su Matlab R2015b, Windows 7 64 bit, 4 GB RAM) per l'input fino a 11e funziona. Per 11il risultato è un'immagine 8192 × 16376. Perché 12sarebbe 16384 × 32760 (536 megapixel), richiedendo oltre 4 GB di RAM, che è più di quanto il mio laptop possa gestire.
— Luis Mendo,

2
Mi piace come il codice inizi con una faccina che trattiene le lacrime a causa delle intense emozioni che questo codice gli fa provare: "')
— Tom Doodler,

14

Dyalog APL, 118 113 byte

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

supponendo ⎕IO=0

Da destra a sinistra:

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

i{ }¨⌽iiterare su poteri (con ⍺) e poteri invertiti ( ⍵)

⊤¨⍨⊂32⍴3 decodifica ciascuno dei numeri a sinistra come 32 cifre ternarie

8 8⍴∊ appiattire e rimodellare a 8 × 8

⍺⌿⍺/replicare ogni riga e colonna ⍺volte

⍵⍴⊂prendere ⍵copie

⊃⍪/ e impilarli verticalmente

⊃,/ unisci tutti i risultati in orizzontale

3↑(116 196 96)(110 170 90)colori; 3↑li estende con(0 0 0)

[ ]indicizza i colori con ciascun elemento della matrice; il risultato è una matrice di RGB

('P3',⌽∘⍴,255,∊)è un "treno" - una funzione che ritorna 'P3'seguita dalla forma invertita dell'argomento 255e l'argomento appiattito.


Penso che tu possa scrivere il tuo programma assumendolo ⎕IO←0e semplicemente dichiararlo come condizione, al di fuori del conteggio dei byte. Molti sistemi APL lo usano come predefinito. (Incluso il tuo LOL)
— Tobia,

11

JavaScript (ES7), 326 327 byte

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

Versione ES6 non golfata

Prova tu stesso.

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

L'unica differenza tra la versione ES7 e ES6 sta usando **invece di Math.pow(). Puoi anche vedere come puoi invocare la funzione, in questo esempio con n=4.

Risultato

inserisci qui la descrizione dell'immagine


Le modifiche

  • salvato 1 byte - trovato un punto e virgola finale non necessario;

Questo è piuttosto lento e potrebbe richiedere del tempo per numeri maggiori di 10.


2
i colori sembrano leggermente off nell'immagine qui. Hai forse fatto uno screenshot con f.lux acceso?
— Jezzamon,

@Jezzamon Grazie per averlo sottolineato - L'ho notato anche io. C'è una leggera possibilità che avrei potuto scegliere " Converti i colori del documento nello spazio di lavoro " durante l'importazione dello screenshot in Photoshop. L'immagine è stata riparata ora.
— inserireusernamehere il

@Giles - Apprezzo il tuo commento, e in SO, sarebbe del tutto appropriato, ma qui, non cambiamo i programmi degli altri - diciamo loro nei commenti.
— Non che Charles il

7

C, 220 byte

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

Ho aggiunto newline inutili per la leggibilità, il punteggio è senza queste newline.

Definisce una funzione f(n)che genera un'immagine PPM semplice su stdout.


1
Per qualche ragione, le risposte C sono piuttosto eleganti nella mia mente.
— downrep_nation

7

Mathematica, 267 255 254 225 212 byte

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

Risparmiato 29 42 byte grazie a Martin Ender

Suggerimenti di golf benvenuti, in particolare per la costruzione dell'array 8 per 8 (per 3) s. Sfortunatamente, non esiste un " ArrayResize" analogo per ImageResize, quindi l'array deve essere convertito in un'immagine ( Image) prima di ridimensionare e quindi di nuovo in un array ( ImageData) per eseguire l' 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, #}] &

1
b=0g. Per generarlo spotrebbe essere più breve codificare i valori dei pixel come numero base-3 ma dovrei provare ad esserne sicuro. Nel frattempo, è possibile salvare i byte non definendo b, g, f, e, tfino a quando ne avete bisogno, e snon bisogno di un nome a tutti e nessuno fa c. Per 2^(j-1)8te puoi usare 4*2^j. Applicando tutti questi, finisco a 225 byte: pastebin.com/YnkUwvwV
— Martin Ender

@MartinEnder Tanta gratitudine, questi sono tutti ottimi suggerimenti! (Nota a se stesso: evita di nominare le cose se possibile, altrimenti
— esegui

Non ho tempo per capirlo completamente in questo momento, ma qui è un'idea per evitare il Image, ImageResize, ImageDataroba. Questo bit fa esplodere un array di un fattore 2: #&@@{##&@@{#,#}&//@x}dov'è xl'array. Quindi, se memorizzi la griglia 8x8 iniziale in una variabile x, e poi lo fai x=#&@@{##&@@{#,#}&//@x}dopo ogni utilizzo, puoi generare abbastanza facilmente le tessere successive.
— Martin Ender,

Spiacenti, sono 4 byte più lunghi del necessario:#&[##&[#,#]&//@x]
— Martin Ender,

Hm, non sto ricevendo questo lavoro ancora, ma si può risparmiare un po 'di più da a) utilizzando ##~Join~2e b) f={g,a=##&[G,G,G],a,g}e quindi sostituire ogni occorrenza di ulteriori G,G,Gcon apure.
— Martin Ender,

4

Python 2.7: 424 412 405 376 357 byte

Sono un po 'nuovo nel golf .... eccoci

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

non golfato e testato in lunghezza ..

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: rimosso sys.argv[1]in favore di raw_input()per salvare una dichiarazione di importazione extra

edit2: importazione PIL abbreviata: rimossa from ImageaggiuntaPIL.

edit3: Grazie @ Sherlock9 per la codifica esadecimale del modello melma

edit4: non è stata necessaria la funzione def e utilizzata al input()posto diraw_input()


tutti i suggerimenti sono più che benvenuti :) soprattutto per ridurre l'array template
— Aaron

Qualcosa come usare '0000100001111110111211100111111102211220022112200111111000001000'(l'array all'indietro) convertito dalla base 3 alla base 16 0x2df0777ca228b9c18447a6fb. Con quel numero, usa un codice come questo [0x2df0777ca228b9c18447a6fb//3**i%3 for i in range(64)]per ottenere i tuoi numeri interi nell'ordine corretto.
— Sherlock9,

Ah, in Python 2, [0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)]potrebbe essere migliore.
— Sherlock9,

Grazie a Sherlock9 che non conosce il golf, potresti spiegare come funziona questo (presumo) cambiamento del codice di base?
— Aaron,

1
La seconda parte è recuperare l'array da quel numero 0x2df0777ca228b9c18447a6fb. Questo è semplice Per un esempio più semplice, per ottenere la 0cifra da 01221100, basta dividere per 3 0volte, quindi prendere l'ultima cifra (usando la mod 3) per ottenere 0. Per prendere la seconda cifra, dividi per 3 2volte, quindi mod 3 per ottenere 1. La comprensione dell'elenco si divide solo per 3 64volte per ripristinare l'intero array. Se hai altre domande, possiamo discuterne nella chat di PPCG .
— Sherlock9,

1

R, 378 356 346 334 byte

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 come file png. Rientrato, con avanzamenti di riga:

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

Alcune spiegazioni:

Ecco la matrice che viene tracciata (0 rappresentano verde chiaro, 1 verde scuro e 2 nero; la matrice è inclinata perché le colonne sono l'asse y e le righe sull'asse 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

Ogni chiamata per imagetracciare quella matrice (con ogni numero intero corrispondente a un colore). Per N = 4, ecco L (la matrice del layout, ogni numero univoco rappresenta un singolo diagramma), w (le larghezze delle colonne della matrice) e h (le altezze delle righe della matrice):

> 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.