No puedo ver el bosque por las llaves

16

Escriba un programa o función que tome una lista no vacía de enteros en cualquier formato conveniente razonable como 4, 0, -1, -6, 2o [4 0 -1 -6 2].

Imprima o devuelva una cadena que represente la lista como un bosque de arte ASCII donde cada número se convierte en un árbol de altura proporcional. Cada árbol ocupa cuatro columnas de texto en la salida de la siguiente manera:

  • Un entero positivo N se convierte en un árbol cuya base es __|_y la parte superior es ^ , con N capas / \intermedias.

    Por ejemplo, cuando N = 1 el árbol es

      ^
     / \
    __|_
    

    cuando N = 2 el árbol es

      ^
     / \
     / \
    __|_
    

    cuando N = 3 el árbol es

      ^
     / \
     / \
     / \
    __|_
    

    y así.

  • Un entero negativo N se convierte en el árbol positivo correspondiente, excepto que hay una barra vertical entre las barras diagonales en lugar de un espacio.

    Por ejemplo, cuando N = -1 el árbol es

      ^
     /|\
    __|_
    

    cuando N = -2 el árbol es

      ^
     /|\
     /|\
    __|_
    

    cuando N = -3 el árbol es

      ^
     /|\
     /|\
     /|\
    __|_
    

    y así.

  • Cuando el número entero es 0, técnicamente no hay árbol, solo un espacio vacío de cuatro guiones bajos:

    ____
    

Los guiones bajos en la base de cada árbol deben alinearse en la salida, es decir, todos los árboles deben tener sus bases en el mismo nivel. Además, se agrega un guión bajo al final de la línea de guiones bajos después del último árbol. Esto hace que cada árbol tenga una columna vacía de "aire" a cada lado.

Como ejemplo, la salida para 4 0 -1 -6 2sería

              ^
             /|\
  ^          /|\
 / \         /|\
 / \         /|\  ^
 / \      ^  /|\ / \
 / \     /|\ /|\ / \
__|_______|___|___|__

Observe cómo los patrones de árbol siempre tienen una columna inicial de espacio vacío, pero se debe agregar un guión bajo para rellenar el lado derecho del último árbol.

También:

  • Los espacios finales en cualquier línea están bien, pero no debe haber espacios iniciales innecesarios.
  • No se permiten nuevas líneas iniciales (el árbol más alto debe tocar la parte superior de la cuadrícula de texto de salida) y solo se permite hasta una nueva línea final.
  • La lista puede contener enteros de -250 a 250 inclusive. No se requiere el manejo de árboles más altos.

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

Más ejemplos

3:

  ^
 / \
 / \
 / \
__|__

-2:

  ^
 /|\
 /|\
__|__

0:

_____

0, 0:

_________

0, 1, 0:

      ^
     / \
______|______

0, -1, 2, -3, 4:

                  ^
              ^  / \
          ^  /|\ / \
      ^  / \ /|\ / \
     /|\ / \ /|\ / \
______|___|___|___|__
Pasatiempos de Calvin
fuente

Respuestas:

6

Pyth, 48 bytes

j_.t+sm.i,J\_?d++\|sm?>d0\ \|d\^Jms+Jmkd"/\\"QJd

Pruébelo en línea: Demostración o conjunto de pruebas

Demasiado perezoso para una explicación completa. Aquí solo una breve descripción:

Genero las columnas primero. Entonces la imagen:

      ^ 
  ^  /|\
 / \ /|\
__|___|__

se genera como:

["_", "_/", "| ^", "_\", "_", "_//", "|||^", "_\\", "_"]

Tenga en cuenta que solo estoy generando la parte inferior (todo sin los espacios). Y también los estoy generando de abajo hacia arriba. Esto se hace bastante sencillo.

Entonces puedo usar el .tmétodo para agregar espacios a las cadenas, de modo que cada cadena tenga la misma longitud. Y luego invierto el orden e imprimo.

Jakube
fuente
Como nota: si esta es una salida real, es posible que haya olvidado agregar un final _(guión bajo) después del último árbol.
insertusernamehere
1
@insertusernamehere Gracias, pasé por alto completamente el final _.
Jakube
7

Python 2, 165 bytes

a=input()
l=max(map(abs,a))
while l+2:s=' _'[l<0];print(s+s.join((([' ^ ','//| \\\\'[x>0::2],'   '][cmp(abs(x),l)],'_|_')[l<0],s*3)[x==0]for x in a)+s).rstrip();l-=1

Este es un programa completo que acepta una lista como entrada. Todavía estoy jugando al golf este horrible desastre.

xsot
fuente
4

PHP, 231 277 bytes

Este desafío tiene una salida hermosa.

$x=fgetcsv(STDIN);for(;$i<2+max(array_map(abs,$x));$i++)for($j=0;$j<count($x);){$_=$x[$j++];$o[$i].=!$i?$_?'__|_':____:(abs($_)>=$i?0>$_?' /|\\':' / \\':($i-1&&abs($_)==$i-1?'  ^ ':'    '));}echo implode("
",array_reverse($o))."_";

Lee una lista separada por comas (los espacios en blanco son opcionales) de STDIN:

$ php trees.php
> 1, 2, 0, -4, 6

Sin golf

$x=fgetcsv(STDIN);
for(;$i<2+max(array_map(abs,$x));$i++)
    for($j=0;$j<count($x);){
        $_=$x[$j++];
        $o[$i] .= !$i ? $_?'__|_':____
                      : (abs($_)>=$i ? 0>$_?' /|\\':' / \\'
                                     : ($i-1&&abs($_)==$i-1 ? '  ^ ' : '    '));
    }
echo implode("\n",array_reverse($o))."_";

Ediciones

  • Guardado 46 bytes . Inicialización de matriz descartada, reemplazada if/elsepor operadores ternarios y movió algunas de las variables para guardar algunos bytes.
insertusernamehere
fuente
2

Rubí, 157 156 153 caracteres

->h{r=[]
h.map{|i|j=i.abs
r+=[s=?_,?/*j+s,i==0?s:?^+(i>0?' ':?|)*j+?|,?\\*j+s].map{|l|l.rjust(h.map(&:abs).max+2).chars}}
r.transpose.map{|l|l*''}*$/+?_}

Escrito solo porque inicialmente Array.transposeparecía una buena idea. Ya no.

Ejecución de muestra:

2.1.5 :001 > puts ->h{r=[];h.map{|i|j=i.abs;r+=[s=?_,?/*j+s,i==0?s:?^+(i>0?' ':?|)*j+?|,?\\*j+s].map{|l|l.rjust(h.map(&:abs).max+2).chars}};r.transpose.map{|l|l*''}*$/+?_}[[4, 0, -1, -6, 2]]
              ^     
             /|\    
  ^          /|\    
 / \         /|\    
 / \         /|\  ^ 
 / \      ^  /|\ / \
 / \     /|\ /|\ / \
__|_______|___|___|__
hombre trabajando
fuente
Recolectar las piezas en una matriz separada en lugar de devolverlas desde el primer mapa debería permitir evitar el uso de reducir.
manatwork
0

C #, 318 bytes

Traté de transponer la matriz. No estoy seguro de si esa fue la mejor solución.

string F(int[]a){int i=a.Length,j,w=i*4+1,h=0;string f="",o=f;for(;i-->0;){j=a[i];f+=","+" _,".PadLeft(j=j>0?j+3:-j+3,'\\')+(j>3?"^"+"|_,".PadLeft(j,a[i]<0?'|':' '):"_,")+" _,_".PadLeft(j+1,'/');h=h<j?j:h;}f="_".PadLeft(h=h>3?h:2,'\n')+f;for(i+=h<3?1:0;++i<h;)for(j=w;j-->0;)o+=f.Split(',')[j].PadLeft(h)[i];return o;}

Sangría y nuevas líneas para mayor claridad:

string F(int[]a)
{
    int i=a.Length,
        j,
        w=i*4+1,
        h=0;
    string f="",o=f;
    for(;i-->0;){
        j=a[i];
        f+=","+" _,".PadLeft(j=j>0?j+3:-j+3,'\\')+(j>3?"^"+"|_,".PadLeft(j,a[i]<0?'|':' '):"_,")+" _,_".PadLeft(j+1,'/');
        h=h<j?j:h;
    }
    f="_".PadLeft(h=h>3?h:2,'\n')+f;
    for(i+=h<3?1:0;++i<h;)
        for(j=w;j-->0;)
            o+=f.Split(',')[j].PadLeft(h)[i];
    return o;
}
Hand-E-Food
fuente