Visualize uma matriz

26

Dada uma matriz de qualquer profundidade, desenhe seu conteúdo com bordas +-|ao redor de cada subarray. Esses são os caracteres ASCII para mais, menos e tubo vertical.

Por exemplo, se a matriz for [1, 2, 3], desenhe

+-----+
|1 2 3|
+-----+

Para uma matriz aninhada, como [[1, 2, 3], [4, 5], [6, 7, 8]], desenhe

+-----------------+
|+-----+---+-----+|
||1 2 3|4 5|6 7 8||
|+-----+---+-----+|
+-----------------+

Para uma matriz irregular, como [[[1, 2, 3], [4, 5]], [6, 7, 8]], desenhe

+-------------------+
|+-----------+-----+|
||+-----+---+|6 7 8||
|||1 2 3|4 5||     ||
||+-----+---+|     ||
|+-----------+-----+|
+-------------------+

Observe que há mais espaço após o desenho [6, 7, 8]. Você pode desenhar o conteúdo na linha superior, central ou inferior, mas, conforme a sua escolha, deve permanecer consistente.

Esse desafio foi inspirado no verbo caixa< de J.

Regras

  • Isso é então o código mais curto vence.
  • Builtins que resolvem isso não são permitidos.
  • A matriz de entrada conterá apenas valores inteiros não negativos ou matrizes. Cada matriz será homogênea, o que significa que seus elementos serão apenas matrizes ou apenas números inteiros, mas nunca uma mistura de ambos.
  • Cada sub-matriz pode ser aninhada em qualquer profundidade.
  • A saída pode ser uma string ou uma matriz de strings, onde cada string é uma linha de saída.

Casos de teste

[]
++
||
++

[[], []]
+---+
|+++|
|||||
|+++|
+---+

[[], [1], [], [2], [], [3], []]
+-----------+
|++-++-++-++|
|||1||2||3|||
|++-++-++-++|
+-----------+

[[[[[0]]]]]
+---------+
|+-------+|
||+-----+||
|||+---+|||
||||+-+||||
|||||0|||||
||||+-+||||
|||+---+|||
||+-----+||
|+-------+|
+---------+

[[[[[4, 3, 2, 1]]]], [[[3, 2, 1]]], [[2, 1]], [1]]
+---------------------------------+
|+-------------+---------+-----+-+|
||+-----------+|+-------+|+---+|1||
|||+---------+|||+-----+|||2 1|| ||
||||+-------+|||||3 2 1|||+---+| ||
|||||4 3 2 1|||||+-----+||     | ||
||||+-------+|||+-------+|     | ||
|||+---------+||         |     | ||
||+-----------+|         |     | ||
|+-------------+---------+-----+-+|
+---------------------------------+
milhas
fonte
Se meu idioma não tiver matrizes aninhadas, posso desconsiderar a definição do tipo de dados?
ThreeFx
1
@ThreeFx Você também pode pegar a entrada como uma string que representa a matriz aninhada
miles
Isso é realmente ineficiente (em Haskell). Eu teria que analisar números manualmente e assim por diante. Nesse caso, seria mais curto definir e usar o tipo de dados.
ThreeFx
@ThreeFx Ou você pode preencher a matriz com valores de sentinela, como -1desde que eu também limitei os números inteiros para não serem negativos. Depois, basta limpar a saída desses valores inválidos.
miles
1
@MitchSchwartz Claro, pegue a entrada em uma tupla aninhada ou em qualquer formato nativo do seu idioma. Sua saída é boa, desde que você permaneça consistente. Os números inteiros podem ser desenhados na parte superior, central ou inferior, e as caixas podem ser na parte superior, central, inferior ou esticada para preencher seu espaço, como no seu exemplo.
milhas

Respostas:

4

Dyalog APL , 56 bytes

Agradecemos ao ngn por ajudar a remover cerca de um terço dos bytes.

{⍵≡∊⍵:⍉⍪⍉⍕⍵⋄(⊢,⊣/)⊃,/(1⊖('++','|'⍴⍨≢),'-'⍪⍣2↑)¨↓↑↓¨∇¨⍵}⊂

TryAPL

Defina a função , execute cada caso de teste e compare com o ]Displayutilitário interno.
[1, 2, 3]
[[1, 2, 3], [4, 5], [6, 7, 8]]
[[[1, 2, 3], [4, 5]], [6, 7, 8]]
[]
[[], []]
[[], [1], [], [2], [], [3], []]
[[[[[0]]]]]
[[[[[4, 3, 2, 1]]]], [[[3, 2, 1]]], [[2, 1]], [1]]

Explicação

No geral, essa é uma função anônima {...}no topo de um anexo . O último apenas adiciona outro nível de aninhamento, solicitando que o primeiro adicione um quadro externo.

A função anônima com espaço em branco ( é o separador de instruções):

{
      ∊⍵:     
    (⊢ , ⊣/)  ,/ (1  ('++' , '|' ⍴⍨ ≢) , '-' ⍪⍣2 ↑)¨   ↓¨ ∇¨ 
}

Aqui está novamente, mas com funções utilitárias separadas:

CloseBox   , ⊣/
CreateVertical  '++' , '|' ⍴⍨ 
AddHorizontals  1  CreateVertical , '-' ⍪⍣2 
{
      ∊⍵:     
    CloseBox  ,/ AddHorizontals¨   ↓¨ ∇¨ 
}

Agora, deixe-me explicar cada função:

CloseBoxpega uma tabela e retorna a mesma tabela, mas com a primeira coluna da tabela anexada à direita da tabela. Assim, dada a tabela 1 por 3 XYZ, essa função retorna a tabela 1 por 4 XYZX, da seguinte forma:
 o argumento (lit. o que está à direita) é
, anexado à
⊣/ coluna mais à esquerda (lit. a redução esquerda de cada linha)

CreateVerticalpega uma tabela e retorna a string que consiste nos caracteres que caberiam |s nas laterais da tabela, mas com dois +s anexados para corresponder a duas linhas de -. Eventualmente, a tabela será rotacionada ciclicamente uma linha para obter uma única +---...linha acima e abaixo. Assim, dada qualquer tabela de três linhas, essa função retorna da ++|||seguinte forma:
'++' , duas vantagens acrescentadas a
'|' ⍴⍨ um estilo remodelado pela
 contagem (linhas) do argumento

AddHorizontalspega uma lista de listas, cria uma tabela, adiciona duas linhas de -s na parte superior, adiciona os caracteres correspondentes da borda esquerda à esquerda e gira uma linha para a parte inferior, para que a tabela tenha uma borda na parte superior , esquerda e inferior. Da seguinte maneira:
1 ⊖ gire uma linha (a linha superior vai para o fundo) da
CreateVertical , sequência ++|||...anexada (como uma coluna) para
'-' ⍪⍣2 menos adicionada duas vezes à parte superior do
 argumento transformada da lista de listas em tabela

{A função anônima }: se o argumento for uma lista simples (não aninhada), faça-o em uma tabela de caracteres (assim, dada a lista de 3 elementos 1 2 3, essa função retornará a tabela de 1 a 5 caracteres visualmente idêntica 1 2 3). Se o argumento não for uma lista simples, verifique se os elementos são tabelas de caracteres simples; coloque-os na mesma altura; enquadre cada um na parte superior, inferior e esquerda; combiná-los; e finalmente pegue a primeira coluna e adicione-a à direita. Da seguinte maneira:
{ começar a definição de uma função anônima
  ⍵ ≡ ∊⍵:se o argumento é idêntico ao argumento achatada (ou seja, é uma lista simples), então:
    transpor a
    em formato de colunas
    transpostas
   ⍕ ⍵ argumento Stringified; else:
  CloseBox Adicione a coluna mais à esquerda, à direita de
  ⊃ ,/ o divulgado (porque a redução encerra) concatenou-se
  AddHorizontals¨ add -s na parte superior e inferior de cada uma das
  ↓ ↑ ↓¨ alturas preenchidas à mesma altura *
  ∇¨ ⍵  dessa função anônima aplicada a cada um dos argumentos e
} termina a definição da função anônima
* transforme cada tabela em uma lista de listas, combine as listas de listas (preenchimento com cadeias vazias para preencher linhas curtas) em uma tabela e divida a tabela em uma lista de listas de listas

Adão
fonte
7

JavaScript (ES6), 223 203 bytes

f=(a,g=a=>a[0].map?`<${a.map(g).join`|`}>`:a.join` `,s=g([a]),r=[s],t=s.replace(/<[ -9|]*>|[ -9]/g,s=>s[1]?s.replace(/./g,c=>c>`9`?`+`:`-`):` `))=>t<`+`?r.join`\n`.replace(/<|>/g,`|`):f(a,g,t,[t,...r,t])

Porto da solução Ruby da @ MitchSchwartz. Versão anterior que funcionava agrupando recursivamente as matrizes (e, portanto, trabalhava para conteúdo arbitrário, não apenas números inteiros):

f=(...a)=>a[0]&&a[0].map?[s=`+${(a=a.map(a=>f(...a))).map(a=>a[0].replace(/./g,`-`)).join`+`}+`,...[...Array(Math.max(...a.map(a=>a.length)))].map((_,i)=>`|${a.map(a=>a[i]||a[0].replace(/./g,` `)).join`|`}|`),s]:[a.join` `]

Nota: Embora eu esteja usando o operador spread na minha lista de argumentos, para obter a saída desejada, forneça um único parâmetro da matriz original, em vez de tentar espalhar a matriz; isso tem o efeito de agrupar a saída na caixa externa desejada. Infelizmente, a caixa externa me custa 18 bytes e a separação de números inteiros me custa 8 bytes; caso contrário, a seguinte visualização alternativa seria suficiente para 197 bytes:

f=a=>a.map?[s=`+${(a=a.map(f)).map(a=>a[0].replace(/./g,`-`)).join`+`}+`,...[...Array(Math.max(0,...a.map(a=>a.length)))].map((_,i)=>`|${a.map(a=>a[i]||a[0].replace(/./g,` `)).join`|`}|`),s]:[``+a]
Neil
fonte
Isso lida com matrizes vazias? Eu recebo um erro Cannot read property 'map' of undefinedpara matrizes vazias, como []. Pois [1,2,[]], o último subarray não é exibido para mim.
miles
@miles Desculpe, eu tinha esquecido de verificar os casos de teste, e todos agora funcionam. Você não especificou a saída [1,2,[]]porque seus exemplos mostram apenas matrizes contendo números inteiros ou matrizes, mas não as duas.
Neil
Ótimo. Também não se esqueça disso, não o cobri nos casos de teste e o problema será mais simples (já que a sua é a única entrada em funcionamento até agora) se cada matriz for homogênea.
miles
3

Ruby, 104 bytes

->s{r=s=s.gsub'}{',?|
r=[s,r,s]*$/while s=s.tr('!-9',' ').gsub!(/{[ |]*}/){$&.tr' -}','-+'}
r.tr'{}',?|}

Função anônima que espera uma sequência. Por exemplo, {{{{{4 3 2 1}}}}{{{3 2 1}}}{{2 1}}{1}}produz

+---------------------------------+
|+-------------+---------+-----+-+|
||+-----------+|         |     | ||
|||+---------+||+-------+|     | ||
||||+-------+||||+-----+||+---+| ||
|||||4 3 2 1||||||3 2 1||||2 1||1||
||||+-------+||||+-----+||+---+| ||
|||+---------+||+-------+|     | ||
||+-----------+|         |     | ||
|+-------------+---------+-----+-+|
+---------------------------------+

Você pode usar este código para testar:

f=->s{r=s=s.gsub'}{',?|
r=[s,r,s]*$/while s=s.tr('!-9',' ').gsub!(/{[ |]*}/){$&.tr' -}','-+'}
r.tr'{}',?|}

a=[]

a<<'[1, 2, 3]'
a<<'[[1, 2, 3], [4, 5], [6, 7, 8]]'
a<<'[[[1, 2, 3], [4, 5]], [6, 7, 8]]'
a<<'[]'
a<<'[[], []]'
a<<'[[], [1], [], [2], [], [3], []]'
a<<'[[[[[0]]]]]'
a<<'[[[[[4, 3, 2, 1]]]], [[[3, 2, 1]]], [[2, 1]], [1]]'

a.map{|s|s.gsub! '], [','}{'
s.tr! '[]','{}'
s.gsub! ',',''
puts s
puts f[s],''}

Isso começa na linha do meio e funciona para o exterior. Primeiro, as instâncias de }{são substituídas por |. Então, enquanto ainda há chaves, todas as {...}cadeias mais internas são transformadas nas +-seqüências apropriadas , enquanto os caracteres que não |{}são transformados em espaços. No final, os aparelhos intermediários são transformados em tubos.

Mitch Schwartz
fonte
Tomei algumas liberdades com os requisitos de formatação de entrada aparentemente branda. O código pode ser facilmente modificado para manipular um formato de entrada diferente, se necessário.
Mitch Schwartz
Receber comentários mal pensados ​​é uma das grandes alegrias de participar deste site.
Mitch Schwartz
3

Brainfuck, 423 bytes

->>+>>,[[>+>+<<-]+++++[>--------<-]>[<+>-[[-]<-]]>[[-]<<[>>>>+<<<<<<-<[>-<-]>>>-
]<<<[-<<<<<<-<]>+>>>]<<<[>>+>>>>>+<<<<<<<-]>>>>>>>>>,]<<+[<<,++>[-[>++<,<+[--<<<
<<<<+]>]]<[-<+]->>>>[<++<<[>>>>>>>+<<<<<<<-]>>>-[<++>-[>>>>+<<<<<++<]<[<<]>]<[>>
+<<<<]>>>+>+>[<<<-<]<[<<]>>>>->+>[-[<-<-[-[<]<[<++<<]>]<[<++++<<]>]<[>+<-[.<<<,<
]<[<<]]>]<[-<<<<<]>>[-[<+>---[<<++>>+[--[-[<+++++++<++>>,]]]]]<+++[<+++++++++++>
-]<-.,>>]>>>>+>>>>]<<-]

Formatado com alguns comentários:

->>+>>,
[
  [>+>+<<-]
  +++++[>--------<-]
  >
  [
    not open paren
    <+>-
    [
      not paren
      [-]<-
    ]
  ]
  >
  [
    paren
    [-]
    <<
    [
      close paren
      >>>>+<<<<
      <<-<[>-<-]>>>
      -
    ]
    <<<
    [
      open paren directly after close paren
      -<<<<<<-<
    ]
    >+>>>
  ]
  <<<[>>+>>>>>+<<<<<<<-]>>>
  >>>>>>,
]
<<+
[
  <<,++>
  [
    -
    [
      >++<
      ,<+[--<<<<<<<+]
      >
    ]
  ]
  <[-<+]
  ->>>>
  [
    <++<<[>>>>>>>+<<<<<<<-]>>>-
    [
      at or before border
      <++>-
      [
        before border
        >>>>+<<<<
        <++<
      ]
      <[<<]
      >
    ]
    <
    [
      after border
      >>+<<
      <<
    ]
    >>>+>+>
    [
      column with digit or space
      <<<-<
    ]
    <[<<]
    >>>>->+>
    [
      middle or bottom
      -
      [
        bottom
        <-<-
        [
          at or before border
          -
          [
            before border
            <
          ]
          <
          [
            at border
            <++<<
          ]
          >
        ]
        <
        [
          after border
          <++++<<
        ]
        >
      ]
      <
      [
        middle
        >+<
        -[.<<<,<]
        <[<<]
      ]
      >
    ]
    <[-<<<<<]
    >>
    [
      border char or space
      -
      [
        not space
        <+>---
        [
          not plus
          <<++>>
          +
          [
            --
            [
              -
              [
                pipe
                <+++++++<++>>,
              ]
            ]
          ]
        ]
      ]
      <+++[<+++++++++++>-]<-.,>>
    ]
    > >>>+>>>>
  ]
  <<-
]

Experimente online.

Espera a entrada formatada como (((((4 3 2 1))))(((3 2 1)))((2 1))(1))em uma nova linha à direita e produz a saída do formulário:

+---------------------------------+
|+-------------+---------+-----+-+|
||+-----------+|+-------+|+---+| ||
|||+---------+|||+-----+|||   || ||
||||+-------+|||||     ||||   || ||
|||||4 3 2 1||||||3 2 1||||2 1||1||
||||+-------+|||||     ||||   || ||
|||+---------+|||+-----+|||   || ||
||+-----------+|+-------+|+---+| ||
|+-------------+---------+-----+-+|
+---------------------------------+

A idéia básica é calcular qual caractere imprimir com base na profundidade do aninhamento. O formato de saída é tal que o índice de linha da borda superior de uma caixa é igual à profundidade da matriz correspondente, com simetria na linha do meio.

A fita é dividida em nós de 7 células, com cada nó representando uma coluna na saída.

O primeiro loop consome a entrada e inicializa os nós, mantendo o controle de profundidade e se a coluna corresponde a um parêntese (isto é, se a coluna contém uma borda vertical) e ocorrências recolhidas )(em nós únicos.

O próximo loop gera uma linha por iteração. Dentro desse loop, outro loop percorre os nós e imprime um caractere por iteração; é aqui que a maior parte do trabalho ocorre.

Durante o loop de inicialização, o layout da memória de um nó no início de uma iteração é

x d 0 c 0 0 0

onde xé um sinalizador booleano para saber se o caractere anterior era parêntese de fechamento, dé profundidade (mais um) e cé o caractere atual.

Durante o loop de impressão de caracteres, o layout da memória de um nó no início de uma iteração é

0 0 d1 d2 c p y

onde d1indica a profundidade em comparação com o índice de linha da metade superior; d2é semelhante a d1mas para a metade inferior; cé o caractere de entrada para essa coluna, se dígito ou espaço, caso contrário, zero; pindica fase, ou seja, metade superior, média ou inferior; e yé uma bandeira que é propagada da esquerda para a direita, acompanhando se chegamos à linha do meio ainda. Observe que, como yse torna zero após o processamento de um nó, podemos usar a ycélula do nó anterior para obter mais espaço de trabalho.

Essa configuração permite evitar o cálculo explícito da profundidade máxima durante a fase de inicialização; o ysinalizador é propagado novamente para atualizar as pcélulas adequadamente.

Há uma -1célula à esquerda dos nós para facilitar a navegação e há uma célula à direita dos nós que controla se já imprimimos a última linha.

Mitch Schwartz
fonte
2

PHP + HTML, não competindo ( 170 141 135 130 bytes)

salvou 29 bytes inspirados em SteeveDroz

<?function p($a){foreach($a as$e)$r.=(is_array($e)?p($e):" $e");return"<b style='border:1px solid;float:left;margin:1px'>$r</b>";}

não competindo porque não há saída ASCII e porque deixei o navegador fazer todo o trabalho interessante

Titus
fonte
1
Você pode criar <b>tags em vez de <div>e não precisa especificar a cor do border. (Salvando 9 bytes)
SteeveDroz
Você não precisa colocar um <tag> em tudo, basta apresentar o resultado como texto simples, que vai salvar um monte de bytes (80 bytes para todo o código após HTML removendo)
ClementNerma
@SteeveDroz Com <b>, também posso remover o white-spaceatributo, salvando outros 19 bytes. ótimo! E eu posso substituir paddingpormargin
Titus
2

JavaScript (ES6), 221

Uma função não recursiva retornando uma matriz de seqüências de caracteres (ainda usando uma subfunção recursiva interna)

a=>[...(R=(a,l)=>a[r[l]='',0]&&a[0].map?'O'+a.map(v=>R(v,l+1))+'C':a.join` `)([a],l=-1,r=[],m='')].map(c=>r=r.map(x=>x+v[(k<0)*2+!k--],k=l,1/c?v='-- ':(v='-+|',c>'C'?k=++l:c>','&&--l,c='|'),m+=c))&&[...r,m,...r.reverse()]

Isso funciona em 2 etapas.

Etapa 1: crie recursivamente uma representação de seqüência de caracteres da matriz de entrada aninhada. Exemplo:

[[[1, 2, 3], [],[4, 5]], [6, 7, 8]] -> "OOO1 2 3,,4 5C,6 7 8CC"

Oe Cmarque abrir e fechar o subarray. Subarrays numéricos simples são renderizados com os elementos separados por espaço, enquanto que se os membros da matriz são subarrays, eles são separados por vírgulas. Essa string acompanha a estrutura multinível da matriz de entrada, enquanto eu posso obter a linha do meio da saída apenas substituindo OC,por |. Ao criar recursivamente essa sequência temporária, também encontro o nível máximo de profundidade e inicializo uma matriz de sequências vazias que conterão a metade da parte superior da saída.
Nota: a caixa externa é complicada, aninho a entrada dentro de outra matriz externa e solto a primeira linha de saída que não é necessária

Etapa 2: varra a string temp e construa a saída

Agora eu tenho uma matriz de cadeias vazias, uma para cada nível. Examino a string temp, mantendo o controle do nível atual, que aumenta para cada um Oe diminui para cada um C. Eu visualizo isso assim:

[[[1, 2, 3], [],[4, 5]], [6, 7, 8]]

OOO1 2 3,,4 5C,6 7 8CC
+                    +
 +            +     +
  +     ++   +
|||1 2 3||4 5||6 7 8||

O mais o sobe e desce segue o nível atual

Para cada caractere, adiciono um caractere a cada linha de saída, seguindo as regras:
- se dígito ou espaço, coloque um '-' no nível atual e abaixo, coloque um espaço acima
- caso contrário, coloque um '+' no nível atual, coloque '-' se abaixo e coloque '|' se acima

OOO1 2 3,,4 5C,6 7 8CC
+--------------------+
|+------------+-----+|
||+-----++---+|     ||
|||1 2 3||4 5||6 7 8||

Durante a varredura temporária, também construo a linha do meio substituindo OC,por|

No final desta etapa, tenho a metade superior e a linha do meio, só preciso espelhar a parte superior para obter a metade inferior e pronto

Código menos comentado e com menos golfe

a=>{
   r = []; // output array
   R = ( // recursive scan function
     a, // current subarray 
     l  // current level
   ) => (
     r[l] = '', // element of r at level r, init to ""
     a[0] && a[0].map // check if it is a flat (maybe empty) array or an array of arrays
     ? 'O'+a.map(v=>R(v,l+1))+'C' // mark Open and Close, recurse
     : a.join` ` // just put the elements space separated
   );
   T = R([a],-1)]; // build temp string
   // pass the input nested in another array 
   // and start with level -1 , so that the first row of r will not be visible to .map

   // prepare the final output
   m = '' // middle row, built upon the chars in T
   l = -1 // starting level
   [...T].map(c => // scan the temp string
         {
            k = l; // current level
            1/c // check if numeric or space
             ? v = '-- ' // use '-','-',' '
             : (
                 v = '-+|', // use '-','+','|'
                 c > 'C' 
                   ? k=++l // if c=='O', increment level and assign to k
                   : c>'A'&&--l, // if c=='C', decrement level (but k is not changed)
                 c='|' // any of O,C,comma must be mapped to '|'
               );
            m += c; // add to middle row
            r = r.map( (x,i) => // update each output row
                       // based on comparation between row index and level
                       // but in golfed code I don't use the i index
                       // and decrement l at each step  
                       x + v[(k<i)*2+!(k-i)]
                     )
         })
   // almost done!  
   return [...r,m,...r.reverse()]

)

Teste

F=
a=>[...(R=(a,l)=>a[r[l]='',0]&&a[0].map?'O'+a.map(v=>R(v,l+1))+'C':a.join` `)([a],l=-1,r=[],m='')].map(c=>r=r.map(x=>x+v[(k<0)*2+!k--],k=l,1/c?v='-- ':(v='-+|',c>'C'?k=++l:c>','&&--l,c='|'),m+=c))&&[...r,m,...r.reverse()]

out=x=>O.textContent = x+'\n'+O.textContent

;[[1,2,3]
,[[[1, 2, 3], [4, 5]], [6, 7, 8]]
,[]
,[[], []]
,[[], [1], [], [2], [], [3], []]
,[[[[[0]]]]]
,[[[[[4, 3, 2, 1]]]], [[[3, 2, 1]]], [[2, 1]], [1]]
].forEach(t=>
  out(JSON.stringify(t)+'\n'+F(t).join`\n`+'\n')
)  

function update()
{
  var i=eval(I.value)
  out(JSON.stringify(i)+'\n'+F(i).join`\n`+'\n')
}

update()
#I { width:90%}
<input id=I value='[[[1, 2, 3], [],[4, 5]], [6, 7, 8]]' oninput='update()'>
<pre id=O></pre>

edc65
fonte
2

Ruby, 245 241 bytes

A sobrecarga necessária para embrulhar tudo em caixas, bem como alinhar tudo, é bem pesada ...

Gera matrizes de strings, com uma string por linha, conforme a especificação. Alinhados na parte inferior em vez dos casos de teste de amostra alinhados na parte superior porque economizam 1 byte.

Experimente online!

V=->a{a==[*a]?(k=a.map(&V);k[0]==[*k[0]]?[h=?++?-*((k.map!{|z|z[1,0]=[' '*~-z[0].size+?|]*(k.map(&:size).max-z.size);z};f=k.shift.zip(*k).map{|b|?|+b.reduce{|r,e|r+e[1..-1]}+?|})[0].size-2)+?+,*f,h]:[h="+#{?-*(f=k*' ').size}+",?|+f+?|,h]):a}
Value Ink
fonte
@ Adám está consertado agora. Vou tentar o meu melhor para otimizar ainda mais depois ...
Valor Ink
Primeira resposta com alinhamento inferior. :-)
Adám
1

PHP, 404 bytes

Todas as soluções funcionam com profundidade máxima da matriz menor que 10. Para valores maiores, a profundidade deve armazenar em uma matriz e não em uma string.

<?foreach(str_split(json_encode($_GET[a]))as$j){$j!="]"?:$c--;$r=($j==",")?($l=="]"?"":" "):$j;$r=$r=="]"?"|":$r;$r=$r=="["?($v=="]"?"":"|"):$r;if($r!=""){$n.=$r;$d.=+$c;}$v=$l;$l=$j;$j!="["?:$c++;$m>=$c?:$m=$c;}for($x=0;$x<strlen($n);$x++)for($y=0;$y<$m;$y++)$z[$y].=$y==$d[$x]&&$n[$x]=="|"?"+":($y<$d[$x]?"-":($y>$d[$x]&&$n[$x]=="|"?"|":" "));echo join("\n",$z),"\n$n\n".(join("\n",array_reverse($z)));

Expandido

foreach(str_split(json_encode($_GET[a]))as$j){ # split JSON representation of the array
    $j!="]"?:$c--;
    $r=($j==",")?($l=="]"?"":" "):$j;
    $r=$r=="]"?"|":$r;
    $r=$r=="["?($v=="]"?"":"|"):$r;
    if($r!=""){
      $n.=$r;  # concanate middle string
      $d.=+$c; # concanate depth position
    }
    $v=$l;
    $l=$j;
    $j!="["?:$c++;
    $m>=$c?:$m=$c; # maximum depth of the array
}
for($x=0;$x<strlen($n);$x++)for($y=0;$y<$m;$y++)
$z[$y].=$y==$d[$x]&&$n[$x]=="|"?"+":($y<$d[$x]?"-":($y>$d[$x]&&$n[$x]=="|"?"|":" "));
# Build the strings before the middle string dependent of value middle string and depth 
echo join("\n",$z),"\n$n\n".(join("\n",array_reverse($z))); #Output

para 425 bytes, podemos fazer isso com o REGEX

<?$n=($p=preg_filter)("#\]|\[#","|",$r=$p("#\],\[#","|",$p("#,(\d)#"," $1",json_encode($_GET[a]))));preg_match_all("#.#",$r,$e,256);foreach($e[0] as$f){$f[0]!="]"&&$f[0]!="|"?:$c--;$d.=+$c;$f[0]!="|"&&$f[0]!="["?:$c++;$m>=$c?:$m=$c;}for($x=0;$x<strlen($n);$x++)for($y=0;$y<$m;$y++)$z[$y].=$y==$d[$x]&&$n[$x]=="|"?"+":($y<$d[$x]?"-":($y>$d[$x]&&$n[$x]=="|"?"|":" "));echo join("\n",$z),"\n$n\n".(join("\n",array_reverse($z)));

Expandido

$r=preg_filter("#\],\[#","|",preg_filter("#,(\d)#"," $1",json_encode($_GET[a])));
preg_match_all("#.#",$r,$e,256);
$n=preg_filter("#\]|\[#","|",$r); # concanate middle string
foreach($e[0] as$f){
    $f[0]!="]"&&$f[0]!="|"?:$c--;
    $d.=+$c; concanate depth position
    $f[0]!="|"&&$f[0]!="["?:$c++;
    $m>=$c?:$m=$c; # maximum depth of the array
}
# similar to the other ways
for($x=0;$x<strlen($n);$x++)
for($y=0;$y<$m;$y++)
$z[$y].=$y==$d[$x]&&$n[$x]=="|"?"+":($y<$d[$x]?"-":($y>$d[$x]&&$n[$x]=="|"?"|":" "));
echo join("\n",$z),"\n$n\n".(join("\n",array_reverse($z)));

455 bytes para uma solução recursiva

<?function v($x,$t=0,$l=1){global$d;$d.=$t;$s="|";$c=count($x);foreach($x as$k=>$v){if(is_array($v))$e=v($v,$t+1,$k+1==$c);else{$e=$v." "[$k+1==$c];$d.=str_pad("",strlen($e),$t+1);}$s.=$e;}$d.=$l?$t:"";$s.=$l?"|":"";return$s;}$n=v($_GET[a]);$m=max(str_split($d));for($x=0;$x<strlen($n);$x++)for($y=0;$y<$m;$y++)$z[$y].=$y==$d[$x]&&$n[$x]=="|"?"+":($y<$d[$x]?"-":($y>$d[$x]&&$n[$x]=="|"?"|":" "));echo join("\n",$z),"\n$n\n".(join("\n",array_reverse($z)));

Expandido

function v($x,$t=0,$l=1){
    global$d; # concanate depth position
    $d.=$t;
    $s="|";
    $c=count($x);
    foreach($x as$k=>$v){           
        if(is_array($v)){$e=v($v,$t+1,$k+1==$c);}
        else{$e=$v." "[$k+1==$c];$d.=str_pad("",strlen($e),$t+1);}
        $s.=$e;
    }
    $d.=$l?$t:"";
    $s.=$l?"|":"";
    return$s;
}
$n=v($_GET[a]); # concanate middle string
$m=max(str_split($d)); # maximum depth of the array
# similar to the other ways 
for($x=0;$x<strlen($n);$x++)
for($y=0;$y<$m;$y++)
$z[$y].=$y==$d[$x]&&$n[$x]=="|"?"+":($y<$d[$x]?"-":($y>$d[$x]&&$n[$x]=="|"?"|":" "));
echo join("\n",$z),"\n$n\n".(join("\n",array_reverse($z)));
Jörg Hülsermann
fonte
1) $j!="]"?:$c--;-> $c-=$j=="]";(-2). 2) ($l=="]"?"":" ")-> " "[$l==$j](-5). Provavelmente substituições semelhantes no segundo loop. 3) if($r!=""){$n.=$r;$d.=+$c;}-> $n.=$r;if($r>"")$d.=+$c;(-3). 4) $l=$j;$j!="["?:$c++;-> $c+="["==$l=$j;(-5). 5) $x=0não é necessário (-4). 6) for($y=0;$y<$m;$y++)-> for($y=$m;$y--;)(-4). 7) join("\n",$z),"\n$n\n".(join("\n",array_reverse($z)));-> join("\n",array_merge($z,[$n],array_reverse($z)));(-4) 8) espaço em branco desnecessário: foreach($e[0]as$f)(-1)
Titus
9) parênteses desnecessários em ($j==",")(-2). 10) if($r>"")$d.=+$c;-> $d.=$r>""?+$c:"";(-0)
Tito
versão recursiva: 1) $d.=$l?$t;é obsoleta (-10) 2) $s.=$l?"|":"";return$s;-> return$s."|"[$l];(-6). 3) aparelho obsoleto {$e=v($v,$t+1,$k+1==$c);}(-2). 4) {$e=$v." "[$k+1==$c];$d.=str_pad("",strlen($e),$t+1);}-> $d.=str_pad("",strlen($e=$v." "[$k+1==$c]),$t+1);(-5).
Titus