Edificio de bloques ASCII 3D

82

Desafío

Escriba un programa que tome una matriz de enteros de 11x11 y construya un edificio de bloques ASCII 3D, donde cada valor en la matriz representa la altura de una columna de bloques en las coordenadas que coinciden con la posición de la matriz. Una altura negativa es una columna "flotante": solo se ve el bloque superior.

Ejemplo

                                                        __________________
                                        ___            /\__\__\__\__\__\__\
 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,      /\__\          /\/\__\__\__\__\__\__\
 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /\/__/         /\/\/__/__/__/__/__/__/
 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,    /\/\__\        /\/\/\__\      /\/\/__/
 1, 0, 0, 7,-7,-7,-7,-7, 7, 0, 0,    \/\/\__\      /\/\/\/__/     /\/\/__/
 0, 0, 0, 7,-7,-7,-7,-7, 7, 0, 0,     \/\/__/     /\/\/\/\__\    /\/\/__/
 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0,      \/\__\    /\/\/\/\/__/   /\/\/__/
 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0,       \/__/    \/\/\/\/\__\_  \/\/__/
 1, 0, 0, 4, 3, 2, 1, 0, 0, 0, 1,                 \/\/\/\/__/_\_ \/__/
 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,            ___   \/\/\/__/__/_\_         ___
 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,           /\__\   \/\/__/__/__/_\       /\__\
 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,           \/\__\   \/__/__/__/__/       \/\__\
                                             \/\__\_________         ______\/\__\
                                              \/\__\__\__\__\       /\__\__\__\__\
                                               \/__/__/__/__/       \/__/__/__/__/

Entrada

La entrada será una lista de 121 enteros, ya sea leídos de stdin (la elección del separador depende de usted) o pasados ​​como una matriz (puede ser 1D o 2D).

Las alturas estarán en el rango de -11 a 11.

Salida

El edificio generado puede escribirse en stdout, mostrarse directamente en la pantalla o devolverse como una cadena separada por una nueva línea.

Se permiten espacios en blanco iniciales y finales.

Reglas de construcción

La forma de un bloque 3D individual se ve así:

 ___
/\__\
\/__/

Y un cubo de bloques de 2x2x2 se ve así:

  ______
 /\__\__\
/\/\__\__\
\/\/__/__/
 \/__/__/

Cuando los bloques se superponen, un bloque más alto tiene prioridad sobre uno más bajo, los bloques en el frente tienen prioridad sobre los que están más atrás, y los bloques a la izquierda tienen prioridad sobre los que están a la derecha. El único caso especial es que la línea superior de un bloque nunca debe sobrescribir ningún carácter que no sea espacio detrás de él.

La interpretación de las alturas de columna se puede explicar mejor mirando una representación 2D desde el lado.

HEIGHT:  1    2    3   -3   -2   -1
                  __   __
             __  |__| |__|  __
        __  |__| |__|      |__|  __
       |__| |__| |__|           |__|

Casos de prueba

Si desea probar su solución con algunas entradas más, he reunido un par de casos de prueba aquí .

Victorioso

Este es el , por lo que gana el envío más corto (en bytes).

James Holderness
fuente
99
Ohh boy, prepárate para más de 300 bytes de soluciones. Buen reto +1
totalmente humano
77
@totallyhuman Nah, Dennis tendrá una solución de 9 bytes para esto en 20 minutos.
Diácono
3
¿La perspectiva tiene que ser como se muestra con la parte inferior izquierda de los datos de entrada en primer plano? El hecho de que este no sea el primer o el último elemento de datos lo hace más difícil. ¿Es aceptable: 1. mantener el mapeo como está y dibujar la salida con la columna inferior derecha en primer plano o 2. dibujar una imagen reflejada o una rotación de 90 grados de los datos? Cualquiera de estos haría que el último elemento de datos se correspondiera con la columna en primer plano, lo que sería más fácil.
Level River St el
3
Me siento inclinado a usar un motor de juego real (o parte de él) para renderizar una foto y convertirla a ASCII
Stan Strum
@LevelRiverSt Esa parece una solicitud razonable: puede elegir el orden de los 121 elementos de entrada para que sea lo que tenga más sentido para su solución, siempre que su pedido sea coherente. Debe ser posible producir todo tipo de diseño que se pueda producir con el orden predeterminado.
James Holderness

Respuestas:

25

Carbón , 70 69 68 bytes

≔E¹¹⮌I⪪S,θF²F¹¹F¹¹F¹¹«J⁻⁻⁺λκ×μ³ι⁻λκ≔§§θλμη¿∨⁼±η⊕κ‹κη¿ι“↗⊟&⁹κUhnI”___

Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:

≔E¹¹⮌I⪪S,θ

Lea la matriz, divida cada línea en comas y convierta a entero, pero también invierta cada línea, ya que queremos dibujar de derecha a izquierda para que las columnas de la izquierda sobrescriban las columnas de la derecha. (Otras dimensiones ya han deseado el comportamiento de sobrescritura).

F²F¹¹F¹¹F¹¹«

Pase por i) las líneas superiores y los cuerpos k) la altura l) las filas m) las columnas. (Recorrer las primeras líneas superiores y luego los cuerpos evita sobrescribir los cuerpos con las líneas superiores).

J⁻⁻⁺λκ×μ³ι⁻λκ

Salta a la posición del cubo.

≔§§θλμη

Obtener la altura en la fila y columna actuales.

¿∨⁼±η⊕κ‹κη

Pruebe si se debe dibujar un cubo a esta altura para esta fila y columna.

¿ι“↗⊟&⁹κUhnI”___

Dibuja el cuerpo o la parte superior del cubo.

Neil
fuente
Cuando cambio el primero 3a a 33, solo obtengo 11 bloques en la torre. En general, las torres parecen estar limitadas a las 11. ¿Cómo sucede eso?
Fabian Röling
@Fabian, estoy un poco confundido, eso F¹¹F¹¹F¹¹no era una pista ...
Neil
No conozco este lenguaje de programación, solo jugué un poco con el enlace TIO.
Fabian Röling
30

C,  376   350   313   309  285 bytes

¡Gracias a @Jonathan Frech por guardar cuatro bytes!

#define F for(
char*t,G[26][67],*s;i,j,e,k,v,x,y;b(){F s="\\/__//\\__\\ ___ ";*s;--y,s+=5)F e=5;e--;*t=*s<33&*t>32?*t:s[e])t=G[y]+x+e;}f(int*M){F;e<1716;++e)G[e/66][e%66]=32;F k=0;++k<12;)F i=0;i<11;++i)F j=11;j--;v+k||b())x=i+j*3+k,y=14+i-k,(v=M[i*11+j])>=k&&b();F;++e<26;)puts(G+e);}

Pruébalo en línea!

Desenrollado:

#define F for(

char *t, G[26][67], *s;
i, j, e, k, v, x, y;

b()
{
    F s="\\/__//\\__\\ ___ "; *s; --y, s+=5)
        F e=5; e--; *t=*s<33&*t>32?*t:s[e])
            t = G[y]+x+e;
}

f(int*M)
{
    F; e<1716; ++e)
        G[e/66][e%66] = 32;

    F k=0; ++k<12;)
        F i=0; i<11; ++i)
            F j=11; j--; v+k||b())
                x = i+j*3+k,
                y = 14+i-k,
                (v=M[i*11+j])>=k && b();

    F; ++e<26;)
        puts(G+e);
}
Steadybox
fuente
No 26*66puede ser 1716?
Jonathan Frech
@ JonathanFrech Claro, me olvidé de eso.
Steadybox el
*s==32-> *s<33.
Jonathan Frech
for(e=k=1;e;++k)for(e=-> for(k=1;e;++k)for(e=.
Jonathan Frech
#define B b(...)&++e-> #define B++e&b(...)(suponiendo bque no depende de e, lo que creo que no).
Jonathan Frech
9

JavaScript (ES6), 277251 bytes

a=>(n=55,$=f=>[...Array(n)].map((_,i)=>f(i)),S=$(_=>$(_=>' ')),n=11,$(l=>$(z=>$(y=>$(x=>(x=10-x,X=x*3+y+z,Y=y-z+n,Z=a[y][x])<=z&&Z+z+1?0:l?['/\\__\\','\\/__/'].map(s=>S[++Y].splice(X,5,...s)):S[Y].splice(X+1,3,...'___'))))),S.map(r=>r.join``).join`
`)

Guardado 26 bytes de la sugerencia de @ Neil .

Sin golf

a=>(
    n=55,
    $=f=>[...Array(n)].map((_,i)=>f(i)),
    S=$(_=>$(_=>' ')),
    n=11,
    $(l=>
        $(z=>$(y=>$(x=>(
            x=10-x,
            X=x*3+y+z,
            Y=y-z+n,
            Z=a[y][x],
            Z<=z && Z+z+1 || (
                l
                ? ['/\\__\\','\\/__/'].map(s=>S[++Y].splice(X,5,...s))
                : S[Y].splice(X+1,3,...'___')
            )
        ))))
    ),
    S.map(r=>r.join``).join`\n`
)
Darrylyeo
fuente
2
,$(w=>$(z=>$(y=>$(x=>(Z=a[y][x=10-x,X=x*3+y+z,Y=y-z+n,x])<=z&&Z+z+1?0:w?['/\\__\\','\\/__/'].map(s=>S[++Y].splice(X,5,...s)):S[Y].splice(X+1,3,...'___'))))),parece ahorrar 26 bytes.
Neil
@Neil brillante! Dibujar todas las líneas superiores primero me ahorra la molestia de verificar si no hay espacios.
darrylyeo
6

Python 2 , 243 bytes

a=input()
s=eval(`[[' ']*55]*23`)
for h in range(7986):
 k=h%3;x=h/3%11;y=h/33%11;z=h/363%11;i=h/3993;u=y+z-x*3+30;v=y-z+10
 if~-(z>=a[y][10-x]!=~z):
	if i*k:s[v+k][u:u+5]='\//\____/\\'[k%2::2]
	if~-i:s[v][u+1+k]='_'
for l in s:print''.join(l)

Pruébalo en línea!

Una traducción de Python del enfoque de Neil's Charcoal.

Lynn
fuente
Es bueno ver una solución de Python con golf para esto. ¡Mi prueba de concepto de Python tenía más de 900 bytes!
James Holderness
3
+1+k-> -~k.
Jonathan Frech
5

APL (Dyalog Unicode) , 117 116 112 bytes SBCS

a23 550⋄{i11 0+⍵+.×3 23-7897⊤⍨65⋄(,2 5ia)←745366⊤⍨104⋄(3i1⌽¯1a)⌈←1j[⍋-/↑j←⍸↑⎕↑¨⊂⌽1,11/2]⋄' _/\'[a]

Pruébalo en línea!

ngn
fuente
5

Tcl, 380409 bytes

El usuario sergiol ha estado ocupado resolviendo esto muy bien:

set X [read stdin]
proc L {a b c d e s} {time {incr z
set y -1
time {incr y
set x -1
time {if {abs([set Z [lindex $::X [expr ($y+1)*11-[incr x]-1]]])==$z|$z<$Z} {set s [string repl [string repl $s [set i [expr -3*$x+57*$y-55*abs($z)+701]] $i+$b $a] [incr i $c] $i+$e $d]}} 11} 11} 12
set s}
puts [L /\\__\\ 4 56 \\/__/ 4 [L "" -1 -55 ___ 2 [string repe [string repe \  55]\n 23]]]

Pruébalo en línea!

Contenido original

set xs [read stdin]
proc L {a b c d e s} {set z 0
while {[incr z]<12} {set y -1
while {[incr y]<11} {set x -1
while {[incr x]<11} {set Z [lindex $::xs [expr ($y+1)*11-$x-1]]
if {abs($Z)==$z||$z<$Z} {set i [expr -3*$x+57*$y-55*abs($z)+701]
set s [string repl [string repl $s $i $i+$b $a] [incr i $c] $i+$e $d]}}}}
set s}
puts [L /\\__\\ 4 56 \\/__/ 4 [L "" -1 -55 ___ 2 [string repe [string repe \  55]\n 23]]]

Pruébalo en línea!

Por desgracia, es lo que es. Es solo un poco más fácil para los ojos cuando se "no tiene golf"

set s [string repeat [string repeat " " 55]\n 23]

proc loops {s0 i0 io s1 i1} {
  set z  0; while {[incr z] < 12} {
  set y -1; while {[incr y] < 11} {
  set x -1; while {[incr x] < 11} {
    set Z [lindex $::xs [expr {($y+1) * 11 - $x - 1}]]
    if {abs($Z) == $z || $z < $Z} {
        set i [expr {-3*$x + 57*$y - 55*abs($z) + 701}]
        set ::s [string replace $::s $i $i+$i0 $s0]
        incr i $io
        set ::s [string replace $::s $i $i+$i1 $s1]
    }
  } } }
}

loops ""      -1 -55 \
       ___     2
loops /\\__\\  4  56 \
      \\/__/   4

puts $s

Construye una cadena, según los requisitos. Toma la matriz de stdin. Va de abajo hacia arriba, de adelante hacia atrás, de derecha a izquierda sobre los datos de la cadena. Lo hace en dos pasadas, una para el borde superior y otra para el resto del cuerpo de cada cubo.

Traté de hacerlo más pequeño usando un dulce lambda mojo funcional, pero, por desgracia, eso lo hizo más grande.

Dúthomhas
fuente
Puedes jugar al golf: tio.run/…
sergiol
Más golf: tio.run/…
sergiol
Más: tio.run/…
sergiol
Aún más: tio.run/…
sergiol
Más aún: tio.run/##lVHtboJAEPx/…
sergiol