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.