Não consigo ver a floresta para as chaves

16

Escreva um programa ou função que inclua uma lista não vazia de números inteiros em qualquer formato conveniente razoável como 4, 0, -1, -6, 2ou [4 0 -1 -6 2].

Imprima ou retorne uma sequência que representa a lista como uma floresta artística ASCII, em que cada número se torna uma árvore de altura proporcional. Cada árvore ocupa quatro colunas de texto na saída da seguinte maneira:

  • Um número inteiro positivo N se torna uma árvore cuja base é __|_e é o topo ^ , com N camadas / \intermediárias.

    Por exemplo, quando N = 1, a árvore é

      ^
     / \
    __|_
    

    quando N = 2 a árvore é

      ^
     / \
     / \
    __|_
    

    quando N = 3 a árvore é

      ^
     / \
     / \
     / \
    __|_
    

    e assim por diante.

  • Um número inteiro negativo N se torna exatamente como a árvore positiva correspondente, exceto que uma barra vertical está entre as barras, em vez de um espaço.

    Por exemplo, quando N = -1, a árvore é

      ^
     /|\
    __|_
    

    quando N = -2 a árvore é

      ^
     /|\
     /|\
    __|_
    

    quando N = -3 a árvore é

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

    e assim por diante.

  • Quando o número inteiro é 0, tecnicamente não há árvore, apenas um espaço vazio de quatro sublinhados:

    ____
    

Os sublinhados na base de cada árvore devem estar alinhados na saída, ou seja, todas as árvores devem ter suas bases no mesmo nível. Além disso, um único sublinhado é adicionado ao final da linha de sublinhados após a última árvore. Isso faz com que cada árvore tenha uma coluna vazia de "ar" em ambos os lados.

Como exemplo, a saída para 4 0 -1 -6 2seria

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

Observe como os padrões da árvore sempre têm uma coluna à esquerda de espaço vazio, mas um sublinhado precisa ser adicionado para preencher o lado direito da última árvore.

Além disso:

  • Os espaços à direita em qualquer linha são bons, mas não deve haver espaços à esquerda desnecessários.
  • Novas linhas iniciais não são permitidas (a árvore mais alta deve tocar na parte superior da grade de texto de saída) e apenas uma linha nova é permitida.
  • A lista pode conter números inteiros de -250 a 250, inclusive. Não é necessário manusear árvores mais altas.

O código mais curto em bytes vence.

Mais exemplos

3:

  ^
 / \
 / \
 / \
__|__

-2:

  ^
 /|\
 /|\
__|__

0:

_____

0, 0:

_________

0, 1, 0:

      ^
     / \
______|______

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

                  ^
              ^  / \
          ^  /|\ / \
      ^  / \ /|\ / \
     /|\ / \ /|\ / \
______|___|___|___|__
Passatempos de Calvin
fonte

Respostas:

6

Pitão, 48 bytes

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

Experimente on-line: Demonstration or Test Suite

Com preguiça de uma explicação completa. Aqui está apenas uma breve visão geral:

Eu gero as colunas primeiro. Então a imagem:

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

é gerado como:

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

Observe que estou gerando apenas a parte inferior (tudo sem espaços). E eu também os estou gerando de baixo para cima. Isso é feito de maneira bem direta.

Então eu posso usar o .tmétodo para acrescentar espaços às seqüências, para que cada sequência tenha o mesmo comprimento. E depois inverto a ordem e imprimo.

Jakube
fonte
Observação: se essa é uma saída real, você pode ter esquecido de adicionar um _sublinhado à direita após a última árvore.
usar o seguinte comando
1
@insertusernamehere Obrigado, ignorou completamente a trilha _.
Jakube 7/12
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 é um programa completo que aceita uma lista como entrada. Eu ainda estou jogando essa bagunça horrível.

xsot
fonte
4

PHP, 231 277 bytes

Este desafio tem uma saída bonita.

$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))."_";

Lê uma lista separada por vírgula (os espaços em branco são opcionais) em STDIN:

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

Ungolfed

$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))."_";

Editar% s

  • 46 bytes salvos . Inicialização de matriz descartada, substituída if/elsepor operadores ternários e moveu algumas das variáveis ​​para economizar alguns bytes.
insertusernamehere
fonte
2

Ruby, 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 apenas porque inicialmente Array.transposeparecia uma boa ideia. Não mais.

Exemplo de execução:

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]]
              ^     
             /|\    
  ^          /|\    
 / \         /|\    
 / \         /|\  ^ 
 / \      ^  /|\ / \
 / \     /|\ /|\ / \
__|_______|___|___|__
homem a trabalhar
fonte
Coletar as peças em uma matriz separada, em vez de retorná-las do primeiro mapa, deve evitar o uso de reduzir.
manatwork
0

C #, 318 bytes

Eu tentei transpor a matriz. Não tenho certeza se essa foi a melhor solução.

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

Recuo e novas linhas para maior clareza:

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;
}
Mão-E-Comida
fonte