Programación exponencialmente viscosa: apilando limos de Minecraft

108

Los limos son enemigos en forma de cubo en Minecraft que se rompen en múltiples versiones más pequeñas de sí mismos cuando son asesinados. A los fines de este desafío, los describiremos como una imagen de 8 × 8 píxeles con 3 colores:

Limo 64x64

Limo 8x8 ← Verdadera versión 8 × 8.

Los colores RGB precisos son:

  • 0, 0, 0 para los ojos y la boca
  • 110, 170, 90 para el verde central, más oscuro
  • 116, 196, 96 para el exterior, verde más claro

Desafío

Escriba un programa o función que tome un entero positivo N y genere una imagen de N tamaños de limos empaquetados en un rectángulo. Al ir de izquierda a derecha, la imagen debe seguir el patrón de tener:

  • Una pila de 2 (N-1) 8 × 8 limos.
  • Una pila de 2 (N-2) 16 × 16 limos.
  • Una pila de 2 (N-3) 32 × 32 limos.
  • Y así sucesivamente hasta que la pila solo contenga un limo.

Las imágenes de limo más grandes que la versión 8 × 8 ( Limo 8x8) son generadas por el muestreo ascendente del vecino más cercano (es decir, duplicando todos los píxeles). Tenga en cuenta que debe usar el diseño y los colores exactos del limo que se proporcionan aquí.

La imagen final contendrá 2 limos N -1 y tendrá 2 (N + 3) -8 píxeles de ancho y 2 (N + 2) píxeles de alto.

La imagen puede imprimirse en cualquier formato de archivo de imagen común, guardarse en un archivo o imprimirse / devolverse como un flujo de datos sin procesar o mostrarse directamente durante el tiempo de ejecución.

El código más corto en bytes gana.

Ejemplos

Su programa debe producir estos resultados exactos.

N = 1:

N = 1

N = 2:

N = 2

N = 3:

N = 3

N = 4:

N = 4

N = 5:

N = 5

N = 6:

N = 6

Un N más grande debería funcionar igual de bien.

Pasatiempos de Calvin
fuente
30
Votaría pero no me quedan votos. Estoy dejando este comentario, así que recordaré votar mañana.
NoOneIsHere
23
Estoy votando tu comentario porque también me he quedado sin votos.
trichoplax
44
"Las imágenes de limo más grandes que la versión 8 × 8 () son generadas por el muestreo superior del vecino más cercano (es decir, duplicando todos los píxeles)". ¿Quiso decir cuadruplicar todos los píxeles, convertir cada píxel en un cuadrado de 2x2?
Caridorc
1
@Caridorc ¿Doblar en cada dirección?
wizzwizz4
@ wizzwizz4 Sí, cada píxel se convierte en 4, ¿correcto?
Caridorc

Respuestas:

21

MATL , 77 76 74 bytes

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

El código funciona en esta confirmación , que es anterior al desafío.

Puedes probarlo en MATL en línea . Este intérprete aún es experimental. Si no funciona, intente actualizar la página y presione "Ejecutar" nuevamente.

Aquí hay un ejemplo que se ejecuta en el intérprete sin conexión:

ingrese la descripción de la imagen aquí

Explicación

:                     % 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
fuente
"Un N más grande debería funcionar igual de bien", pero el tuyo parece dar errores de memoria / índice sin memoria ya en n = 9. ¿Es esto solo el intérprete en línea, o esto también sucede en la versión fuera de línea?
David Mulder
1
@DavidMulder He probado sin conexión (compilador que se ejecuta en Matlab R2015b, Windows 7 de 64 bits, 4 GB de RAM) para entrada 11y funciona. Para 11el resultado es una imagen de 8192 × 16376. Para 12ello sería 16384 × 32760 (536 megapíxeles), que requieren más de 4 GB de RAM, que es más de lo que mi computadora portátil puede manejar.
Luis Mendo
2
Me gusta cómo el código comienza con una sonrisa que retiene las lágrimas debido a las intensas emociones que este código le hace sentir: "')
Tom Doodler
14

Dyalog APL, 118 113 bytes

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

asumiendo ⎕IO=0

De derecha a izquierda:

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

i{ }¨⌽iiterar sobre poderes (con ) y poderes invertidos ( )

⊤¨⍨⊂32⍴3 decodifica cada uno de los números de la izquierda como 32 dígitos ternarios

8 8⍴∊ aplanar y remodelar a 8 × 8

⍺⌿⍺/replicar cada fila y columna veces

⍵⍴⊂tomar copias

⊃⍪/ y apilarlos verticalmente

⊃,/ une todos los resultados horizontalmente

3↑(116 196 96)(110 170 90)colores; 3↑los extiende con(0 0 0)

[ ]indexar los colores con cada elemento de la matriz; el resultado es una matriz de RGB

('P3',⌽∘⍴,255,∊)es un "tren": una función que regresa 'P3'seguida de la forma invertida del argumento 255, y el argumento se aplana.

ngn
fuente
Creo que puede escribir su programa suponiendo ⎕IO←0y simplemente establecerlo como una condición, fuera del recuento de bytes. Muchos sistemas APL lo usan por defecto. (Incluyendo el tuyo jajaja)
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++,_,_)}}

Versión ES6 Ungolfed

Inténtalo tú mismo.

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

La única diferencia entre la versión ES7 y ES6 es usar en **lugar de Math.pow(). También puede ver cómo puede invocar la función, en este ejemplo con n=4.

Resultado

ingrese la descripción de la imagen aquí


Ediciones

  • guardado 1 byte : se encontró un punto y coma al final innecesario;

Esto es bastante lento y puede tomar algún tiempo para números mayores a 10.

insertusernamehere
fuente
2
los colores parecen ligeramente apagados en la imagen aquí. ¿Tal vez hiciste una captura de pantalla con f.lux activado?
Jezzamon
@Jezzamon Gracias por señalarlo, también lo noté. Hay una ligera posibilidad de que yo podría haber elegido " Convertir los colores del documento al espacio de trabajo ", mientras que la importación de la captura de pantalla en Photoshop. La imagen está arreglada ahora.
insertusernamehere
@Giles - Apreciamos su comentario, y en SO, eso sería totalmente apropiado, pero aquí, no cambiamos los programas de los demás, les decimos en los comentarios.
No es 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));}

Agregué nuevas líneas inútiles para facilitar la lectura, la puntuación es sin estas nuevas líneas.

Define una función f(n)que genera una imagen PPM simple en stdout.

orlp
fuente
1
Por alguna razón, las respuestas C son bastante elegantes en mi 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,#}]&

Guardado 29 42 bytes gracias a Martin Ender

Las sugerencias de golf son bienvenidas, especialmente para construir la matriz de 8 por 8 (por 3) s. Desafortunadamente, no hay un ArrayResizeanálogo " " para ImageResize, por lo que la matriz debe convertirse en una imagen ( Image) antes de cambiar el tamaño, y luego volver a una matriz ( ImageData) para hacer el Joining.

Sin golf:

(* 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
fuente
1
b=0g. Para generarlo s, podría ser más corto codificar los valores de píxeles como un número de base 3, pero tendría que intentar estar seguro. Mientras tanto, usted puede ahorrar bytes al no definir b, g, f, e, thasta que los necesite, y sno necesita un nombre en absoluto y tampoco lo hace c. Para 2^(j-1)8que puedas usar 4*2^j. Aplicando todo eso, termino en 225 bytes: pastebin.com/YnkUwvwV
Martin Ender
@MartinEnder ¡Muchas gracias, todas estas son muy buenas sugerencias! (Nota mental: evitar nombrar las cosas, si es posible, si no hace la asignación al (y no antes) la primera aparición.)
lastresort
No tengo tiempo para averiguarlo por completo en este momento, pero aquí es una idea para evitar la Image, ImageResize, ImageDatacosas. Este bit explota una matriz por un factor de 2: #&@@{##&@@{#,#}&//@x}dónde xestá la matriz. Entonces, si almacena la cuadrícula inicial de 8x8 en una variable x, y luego lo hace x=#&@@{##&@@{#,#}&//@x}después de cada uso, puede generar los mosaicos sucesivos con bastante facilidad.
Martin Ender
Vaya, son 4 bytes más largos de lo necesario:#&[##&[#,#]&//@x]
Martin Ender
Hm, todavía no estoy haciendo que esto funcione, pero puedes ahorrar un poco más a) usando ##~Join~2yb) f={g,a=##&[G,G,G],a,g}y luego reemplazar cada aparición adicional de G,G,Gcon a.
Martin Ender
4

Python 2.7: 424 412 405 376 357 bytes

Soy un poco nuevo en el golf ... aquí vamos

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

sin golf y longitud probada ..

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: eliminado sys.argv[1]a favor de raw_input()guardar una declaración de importación adicional

edit2: importación PIL acortada: eliminado from ImageagregadoPIL.

edit3: Gracias @ Sherlock9 por la codificación hexadecimal de la plantilla de limo

edit4: no necesitaba la función def y se usaba en input()lugar deraw_input()

Aaron
fuente
cualquier sugerencia es más que bienvenida :) especialmente para reducir la matriz de plantillas
Aaron
Algo como usar '0000100001111110111211100111111102211220022112200111111000001000'(su matriz al revés) convertido de base 3 a base 16 0x2df0777ca228b9c18447a6fb. Con ese número, use un código como este [0x2df0777ca228b9c18447a6fb//3**i%3 for i in range(64)]para obtener sus enteros en el orden correcto.
Sherlock9
Ah, en Python 2, [0x2df0777ca228b9c18447a6fb/3**i%3for i in range(64)]puede ser mejor.
Sherlock9
Gracias @ Sherlock9 por ser nuevo en el golf, ¿podría explicar cómo funciona (supongo) este cambio de código base?
Aaron
1
La segunda parte es recuperar su matriz de ese número 0x2df0777ca228b9c18447a6fb. Esto es simple. Para un ejemplo más simple, para obtener el 0enésimo dígito 01221100, simplemente divídalo entre 3 0veces y luego tome el último dígito (usando el mod 3) para obtenerlo 0. Para tomar el segundo dígito, divídalo entre 3 2veces, luego mod 3 para obtener 1. La comprensión de la lista solo se divide por 3 64veces para recuperar su matriz completa. Si tiene más preguntas, podemos discutirlas en el chat 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()}

Guarda como un archivo png. Sangrado, con saltos de línea:

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

Algunas explicaciones:

Aquí está la matriz que se está trazando (0 representa verde claro, 1 verde oscuro y 2 negro; la matriz está inclinada porque las columnas son el eje yy las filas el eje 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 llamada para imagetrazar esa matriz (con cada número entero correspondiente a un color). Para N = 4, aquí está L (la matriz de diseño, cada número único representa una sola gráfica), w (los anchos de las columnas de la matriz) yh (las alturas de las filas de la 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
fuente