1P5: caixas aninhadas

53

Essa tarefa faz parte do Primeiro envio periódico de quebra-cabeça de programação Premier .

Você obtém uma hierarquia de itens no seguinte formato:

2
Hat
1
Gloves

que precisam ser colocados em caixas, assim:

.------------.
| Hat        |
| .--------. |
| | Gloves | |
| '--------' |
'------------'

No formato de entrada, os números iniciam uma caixa com tantos itens quanto o número especificado. A primeira caixa contém dois itens (o chapéu e a caixa que contém as luvas); a segunda contém apenas um único item - as luvas.

Como pode ser visto, as caixas também podem viver dentro de caixas. E eles são sempre arredondados ... mais ou menos (cantos pontiagudos são um risco de ferimento e não queremos isso).

Abaixo estão os detalhes desagradáveis ​​para aqueles que desejam utilizar cada minúsculo espaço de manobra que a especificação fornece. Lembre-se, não ler as especificações não é desculpa para enviar soluções erradas. Há um script de teste e alguns casos de teste no final.


Especificação

  • As caixas são construídas com os seguintes caracteres:

    • | (U + 007C) é usado para construir as arestas verticais.
    • - (U + 002D) é usado para construir as arestas horizontais.
    • ' (U + 0027) são os cantos inferiores arredondados.
    • . (U + 002E) são os cantos superiores redondos.

    Uma caixa, portanto, fica assim:

    .--.
    |  |
    '--'
    

    Observe que, embora o Unicode também tenha cantos arredondados e caracteres de desenho de caixa adequados, essa tarefa é apenas em ASCII. Por mais que eu goste do Unicode, percebo que existem idiomas e ambientes por aí que ainda não chegaram na segunda à última década.

  • As caixas podem conter uma sequência de itens que são texto ou outros itens. Itens individuais em uma caixa são renderizados de cima para baixo. A sequência A, B, C é processada da seguinte maneira:

    .---.
    | A |
    | B |
    | C |
    '---'
    

    É claro que isso também se aplica às caixas aninhadas, que são um item como o texto. Portanto, a sequência A, B, Caixa (C, Caixa (D, E)), F renderizará da seguinte maneira:

    .-----------.
    | A         |
    | B         |
    | .-------. |
    | | C     | |
    | | .---. | |
    | | | D | | |
    | | | E | | |
    | | '---' | |
    | '-------' |
    | F         |
    '-----------'
    
  • As caixas ajustam seu tamanho ao conteúdo e as caixas aninhadas sempre se estendem ao tamanho de seus pais. Sempre existe um espaço antes e depois do conteúdo, para que nem o texto nem as caixas aninhadas fiquem muito perto da borda da caixa externa. Em resumo, o seguinte está errado:

    .---.
    |Box|
    '---'
    

    E o seguinte está correto:

    .-----.
    | Box |
    '-----'
    

    Parece muito melhor também :-)

  • Os itens de texto (consulte Entrada abaixo) devem ser reproduzidos exatamente.

  • Sempre há uma única caixa de nível superior (cf. XML). No entanto, uma caixa pode conter várias outras caixas.

Entrada

  • A entrada é dada na entrada padrão; para um teste mais fácil, provavelmente redirecionado de um arquivo.

  • A entrada é fornecida em linha, com cada linha representando um item de texto para colocar na caixa atual ou abrindo uma nova caixa.

  • Cada linha é terminada por uma quebra de linha.

  • Os itens de texto são marcados por uma linha que não consiste em um número (veja abaixo). O texto usa caracteres alfabéticos, o espaço e a pontuação ( .,-'"?!()). O texto não inicia nem termina com um espaço e sempre terá pelo menos um caractere.

  • Uma caixa começa com uma única linha com um número. O número indica o tamanho da caixa, ou seja, o número dos seguintes itens que são colocados nela:

    2
    A
    B
    

    gera uma caixa com dois itens de texto:

    .---.
    | A |
    | B |
    '---'
    

    Uma caixa sempre conterá pelo menos um item.

  • O final das caixas não é explicitamente marcado com uma linha; em vez disso, as caixas são fechadas implicitamente após o número especificado de itens ser colocado nelas.

  • Uma caixa é sempre apenas um item, independentemente de quantos itens contenham. Por exemplo

    3
    A
    4
    a
    b
    c
    d
    B
    

    produzirá uma caixa com três itens, o segundo dos quais é outra caixa com quatro itens.

    O aninhamento também não afeta o fato de uma caixa ser apenas um item.

Limites

  • O nível máximo de aninhamento é cinco . Ou seja, existem no máximo cinco caixas uma dentro da outra. Isso inclui o mais externo.

  • Há um máximo de dez itens por caixa.

  • Os itens de texto têm um comprimento máximo de 100 caracteres.

Resultado

  • Saída é a caixa renderizada, incluindo todos os itens contendo e aninhados de acordo com as regras descritas acima.
  • A saída deve ser fornecida na saída padrão e deve corresponder exatamente. Nenhum espaço em branco à esquerda ou à direita é permitido.
  • Cada linha deve ser finalizada com uma quebra de linha, incluindo a última.

Condição vencedora

  • O código mais curto vence (ou seja, obtém a resposta aceita).

Entrada de amostra 1

3
This is some text!
Oh, more text?
Just text for now, as this is a trivial example.

Saída de amostra 1

.--------------------------------------------------.
| This is some text!                               |
| Oh, more text?                                   |
| Just text for now, as this is a trivial example. |
'--------------------------------------------------'

Entrada de amostra 2

4
Extreme
nesting
3
of
boxes
4
might
lead
to
2
interesting
1
visuals.
Indeed!

Saída de amostra 2

.--------------------------.
| Extreme                  |
| nesting                  |
| .----------------------. |
| | of                   | |
| | boxes                | |
| | .------------------. | |
| | | might            | | |
| | | lead             | | |
| | | to               | | |
| | | .--------------. | | |
| | | | interesting  | | | |
| | | | .----------. | | | |
| | | | | visuals. | | | | |
| | | | '----------' | | | |
| | | '--------------' | | |
| | '------------------' | |
| '----------------------' |
| Indeed!                  |
'--------------------------'

Entrada de amostra 3

1
1
1
1
1
Extreme nesting Part Two

Saída de amostra 3

.------------------------------------------.
| .--------------------------------------. |
| | .----------------------------------. | |
| | | .------------------------------. | | |
| | | | .--------------------------. | | | |
| | | | | Extreme nesting Part Two | | | | |
| | | | '--------------------------' | | | |
| | | '------------------------------' | | |
| | '----------------------------------' | |
| '--------------------------------------' |
'------------------------------------------'

Entrada de amostra 4

3
Foo
2
Bar
Baz
2
Gak
1
Another foo?

Saída de amostra 4

.----------------------.
| Foo                  |
| .------------------. |
| | Bar              | |
| | Baz              | |
| '------------------' |
| .------------------. |
| | Gak              | |
| | .--------------. | |
| | | Another foo? | | |
| | '--------------' | |
| '------------------' |
'----------------------'

Script de teste

Como acertar os detalhes pode ser difícil às vezes nós ( Ventero e eu) preparamos um script de teste com o qual você pode executar sua solução para verificar se está correto. Está disponível como um script do PowerShell e um script do bash . A invocação é: <test-script> <program invocation>.

UPDATE: Os scripts de teste foram atualizados; houve vários casos de teste que não respeitavam os limites que eu defini. O script de teste do PowerShell não usou comparação com distinção entre maiúsculas e minúsculas para verificar o resultado. Espero que esteja tudo bem agora. O número de casos de teste foi reduzido para 156, embora o último agora seja bastante ... grande.

ATUALIZAÇÃO 2: Carreguei meu gerador de casos de teste . Escrito em C # , visando o tempo de execução do .NET 2. Funciona em mono. Isso pode ajudar as pessoas a testar sua implementação. Como pior caso definitivo, considerando os limites da tarefa, você pode tentar:

nb.exe 1 10 10 5 100 100 | my invocation

que gerará apenas caixas até o nível mais interno e utilizará o número máximo de itens por caixa e o comprimento máximo de itens de texto. Porém, não incluí este caso de teste no script de teste, pois é muito grande e a saída ainda maior.

ATUALIZAÇÃO 3: Atualizei o script de teste do PowerShell, que estava propenso a gerar erros, dependendo de como as terminações de linha estavam no script e de que termina a linha impressa. Agora deve ser agnóstico para ambos. Desculpe novamente pela confusão.

Joey
fonte
Você diz que as caixas devem ajustar seu tamanho ao conteúdo. No entanto, no último exemplo, a primeira caixa interna ajusta seu tamanho à caixa externa. Então, como as caixas aninhadas obtêm seu tamanho?
Juan
@ Juan: Obrigado por capturar isso. Incrível que escorregue como esses ainda acontecem. Editado :-)
Joey
11
@ Joey Um velho, mas um bonzinho. Espero que possa inspirar alguns de nossos usuários mais novos a escrever boas e bem especificadas perguntas. :-)
Gareth
@ Gareth, eu definitivamente deveria tentar encontrar tempo para escrever mais desses novamente. Mas uma pergunta bem especificada, casos de teste, implementação de referência e outras coisas (coisas que considero essenciais para uma competição, mas essa visão não é compartilhada por muitos;) levam tempo. Foi muito mais fácil em uni: D
Joey

Respostas:

2

GolfScript, 125 caracteres

n/):B;[(~{[B"."+"""-"]B"| "+:B;@@{(.10,`-{[B\" "]\}{~A}if}*B[2>:B"'"+"""-"]\}:A~;].{~;1$++,}%$-1=:§;{~§3$.+3$+,-*+1$-1%++}%n*

Usando uma abordagem semelhante à solução de Keith .

Howard
fonte
26

Python, 204 caracteres

def P(n):x=raw_input();return eval('[(n+".","","-")]'+'+P(n+"| ")'*int(x))+[(n+"'",'','-')]if'0'<x<':'else[(n,x,' ')]
r=P('')
for q,t,f in r:print q+t+f*(max(len(2*x+y)for x,y,a in r)-len(2*q+t))+q[::-1]

Pretorna uma lista de triplos, cada um dos quais é um prefixo / sufixo de linha (o sufixo é o reverso do prefixo), algum texto de linha e um caractere de preenchimento de linha. Depois de calcular todos os triplos, eles são impressos usando o número certo de caracteres de preenchimento para tornar todas as linhas do mesmo comprimento.

Versão não destruída:

def get_lines(prefix):
  line=raw_input()
  result=[]
  if line.isdigit():
    result.append((prefix+'.', '', '-'))
    for i in xrange(int(line)):
      result += get_lines(prefix + '| ')
    result.append((prefix+"'", '', '-'))
  else:
    result.append((prefix, line, ' '))
  return result
lines=get_lines('')
width=max(2*len(prefix)+len(text) for prefix,text,fill in lines)
for prefix,text,fill in lines:
  print prefix+text+fill*(width-2*len(prefix)-len(text))+prefix[::-1]
Keith Randall
fonte
Uau, isso foi rápido. E ideia interessante com Plá.
JoeyAbr
Uau, de fato. Isso é interessante, você pode postar a versão não destruída? Eu gostaria de entender como o bit eval funciona. Heh, a minha solução python ungolfed é 1500 caracteres :( Apesar de eu ter uma abordagem totalmente diferente (e ineficiente).
Casey
@ Casey: eval é apenas um atalho de golfe para um loop, não é fundamental. Vou postar uma versão ungolfed em um segundo ...
Keith Randall
13

Ruby 1.9, 174 caracteres

r=->l{$*<<(l*2+i=gets.chop).size;/\d/?eval('[l+?.,p=?-,p,'+'*r["| "+l],'*i.to_i+"l+?',p,p]"):[l,i,?\s]}
r[""].each_slice(3){|a,b,c|puts a+b+c*($*.max-(a*2+b).size)+a.reverse}

Um pouco semelhante à solução de Keith .

Ventero
fonte
6

APL (78)

{∧/⎕D∊⍨I←⍞:{∆,('-'⍪⍵⍪'-'),∆←'.|'''/⍨1(⊃⍴⍵)1}⍕⍪/{⍵↑[2]⍨⌈/⊃∘⌽∘⍴¨∆}¨∆←∇¨⍳⍎I⋄⍉⍪I}⍬
marinus
fonte
5
o que é isso eu nem sequer
Nowayz
Não consigo executar isso no tio.run para testar a solução. Caso contrário, eu trocaria a resposta aceita também.
Joey #
5

Python - 355 314 259 caracteres

w=0
def p(n,l):
 global w;f=[(l-1,0)]
 for k in' '*n:
  i=raw_input()
  try:f+=p(int(i),l+1)
  except:f+=[(l,i)];w=max(w,4*l+len(i))
 return f+[(l-1,1)]
for l,s in p(input(),1):p=w-4*l-2;print'| '*l+(".'"[s]+'-'*p+".'"[s]if s<2 else s+' '*(p+2-len(s)))+' |'*l
Juan
fonte
quase uma redução de 100 caracteres, bom trabalho.
Casey
5

Ruby 1.9, 229 228 226 223 222

g=->n{(1..n).map{g[Integer l=gets.chop]rescue l}}
w=->b{b.bytesize rescue b.map{|e|w[e]}.max+4}
p=->b,c{r=c-2
[?.+?-*r+?.,*b.map{|i|p[i,c-4]}.flatten.map{|k|"| #{k} |"},?'+?-*r+?']rescue[b.ljust(c)]}
puts p[b=g[1][0],w[b]]
Lowjacker
fonte
5

C, 390 366 363 caracteres

#define F(n)for(int i=n;i--;)
#define H(n,s,a...)F(n)printf(s);printf(a);
#define I(s)H(v,"| ",s)H(l-2,"-",s)J
#define J H(v," |","\n")
S[1<<17][26],N[1<<17],P,a;E(p){int l=strlen(gets(S[p]));if(sscanf(S[p],"%d",N+p))F(N[p])l<(a=E(++P))?l=a:l;return l+4;}R(p,v,l){if(N[p]){I(".")F(N[p])R(++P,v+1,l-4);I("'")}else{H(v,"| ","%-*s",l,S[p])J}}main(){R(P=0,0,E(0)-4);}

Ajuntar com gcc -std=gnu99 -w file.c

Nem mesmo perto da versão de Keith, mas ei, é bom ol 'C

esneider
fonte
Passa apenas 159 dos 160 testes aqui.
Joey #
Ai. Eu acho que agora está tudo bem. Eu estava esquecendo de alocar espaço para o \ 0 no caso extremo.
esneider
Ainda parece o mesmo, o teste nº 142 falha. A propósito, o caso extremo real nem sequer está presente, pois possui 10 entradas MiB e 78 saídas MiB. Eu não queria que o script de teste a ser tão grande ;-)
Joey
estranho, eu estou começando 160/160 passed(eu quis dizer uma seqüência de 100 caracteres, que não está presente de qualquer maneira)
esneider
Estranho. FreeBSD 8.2-RELEASE #5: Sun Feb 27 10:40:25 CET 2011com gcc version 4.2.1 20070719 [FreeBSD]x64 aqui. Aceito sua palavra pelos 160, então :-). E deve haver um caso de teste com 100 caracteres, na verdade (Testes 143-147).
Joey #
4

python muito funcional, 460 caracteres

r=range
s=lambda x:isinstance(x,str)
w=lambda x:reduce(max,[len(i)if s(i)else w(i)+4 for i in x])
z=lambda b,x:''.join(b for i in r(x))
def g(n=1):
 t=[]
 for i in r(n):
  x=raw_input('')
  try:t+=[g(int(x))]
  except:t+=[x]
 return t
o=list.append
def y(c,m):
 f='| ';h=' |';e=z('-',m+2);a='.'+e+'.';b="'"+e+"'";t=[a]
 for i in c:
  if s(i):o(t,f+i+z(' ',m-len(i))+h)
  else:[o(t,f+j+h)for j in y(i,m-4)]
 return t+[b]
x=g()[0];m=w(x);print '\n'.join(y(x,m))
eordano
fonte
Hum, isso não parece funcionar para mim, os |caracteres não estão espaçados corretamente. É muito semelhante à minha solução python
Casey
2
Na verdade, não passa em nenhum dos casos de teste. eordano: Incluímos essas para que ninguém mais enviasse respostas que estão completamente erradas.
JoeyAbr
11
Acho que colei uma versão antiga do código. Deve funcionar agora. Desculpe por não ser profissional.
eordano
Funciona para mim! Solução agradável, eu gosto da abordagem funcional.
Casey
De fato, funciona agora.
Joey
4

Haskell, 297 caracteres

f§(a,b)=(f a,b)
h c=(c,'-',c)
b l=h".":map(\(p,f,q)->("| "++p,f,q++" |"))l++[h"'"]
y[]s z=([(s,' ',"")],z)
y[(n,_)]_ z=b§foldr(\_(l,w)->(l++)§x w)([],z)[1..n]
x(a:z)=y(reads a)a z
m(p,_,q)=length$p++q
n®a@(p,c,q)=p++replicate(n-m a)c++q++"\n"
o(l,_)=l>>=(maximum(map m l)®)
main=interact$o.x.lines

Enquanto golfe, o método é bastante simples. Somente limites estão disponíveis na memória.

MtnViewMark
fonte
4

C # - 1005 859 852 782 caracteres

using c=System.Console;using System.Linq;class N{static void Main(){new N();}N(){var i=R();c.WriteLine(i.O(0,i.G().W));}I R(){var s=c.ReadLine();int l=0,i=0;if(int.TryParse(s,out l)){var b=new I(l);for(;i<l;){b.m[i++]=R();}return b;}else{return new I(0,s);}}class P{public int W;public int H;}class I{public I[]m;bool z;string t;public I(int l,string r=""){z=l!=0;m=new I[l];t=r;}public P G(){var s=new P();if(z){var d=m.Select(i=>i.G());s.W=d.Max(y=>y.W)+4;s.H=d.Sum(y=>y.H)+2;}else{s.W=t.Length;s.H=1;}return s;}public string O(int l,int w){if(z){string s=A(l,"."+"-".PadRight(w-2,'-')+"."),e=s.Replace(".","'");foreach(var i in m){s+="\n"+i.O(l+1,w-4);}s+="\n"+e;return s;}else{return A(l,t.PadRight(w));}}}static string A(int l,string o){while(l-->0){o= "| "+o+" |";}return o;}}

Preciso dar uma nova olhada nisso, pois tenho certeza de que ela pode ser melhorada, mas esta é minha terceira passagem inicial .

Ungolf'd:

using c=System.Console;
using System.Linq;

class NestedBoxes
{
    static void Main()
    {
        new NestedBoxes();
    }
    NestedBoxes()
    {
        var item = ReadItem();
        c.WriteLine(item.Print(0, item.GetSize().Width));
    }
    Item ReadItem()
    {
        var line = c.ReadLine();
        int count = 0, i = 0;
        if (int.TryParse(line, out count))
        {
            var box = new Item(count);
            for (; i < count;)
            {
                box.items[i++] = ReadItem();
            }
            return box;
        }
        else
        {

            return new Item(0,line);
        }
    }
    class Size
    {
        public int Width;
        public int Height;
    }
    class Item
    {
        public Item[] items;
        bool isBox;
        string text;
        public Item(int size,string word="")
        {
            isBox = size != 0; items = new Item[size]; text = word;
        }
        public Size GetSize()
        {
            var s = new Size();
            if (isBox)
            {
                var sizes = items.Select(i => i.GetSize());
                s.Width = sizes.Max(y => y.Width) + 4; s.Height = sizes.Sum(y => y.Height) + 2;
            }
            else
            {
                s.Width = text.Length;
                s.Height = 1;
            }
            return s;
        }
        public string Print(int level, int width)
        {
            if (isBox)
            {
                string output = AddLevels(level, "." + "-".PadRight(width - 2, '-') + "."),
                        bottomLine = output.Replace(".", "'");
                foreach (var item in items)
                {
                    output += "\n" + item.Print(level + 1, width - 4);
                }
                output += "\n" + bottomLine;
                return output;
            } else {return AddLevels(level, text.PadRight(width)); }
        }
    }
    static string AddLevels(int level, string output)
    {
        while(level-->0)
        {
            output = "| " + output + " |";
        }
        return output;
    }
}
Rebecca Chernoff
fonte
@ Joey, sim, eu definitivamente preciso passar por tudo de novo. Precisa jogar com a lógica para tentar reduzi-la também.
Rebecca Chernoff
Eu não estou familiarizado com C, mas em JS, você pode combinar várias instruções var a um, como este: var a = 1, b = 2, c = 3;. Você não pode fazer a mesma coisa em C?
precisa saber é o seguinte
2
@ Nyuszika7H, este é C #, não C. Você não pode combinar varinstruções implícitas como essa. Você só pode combinar se eles tiverem um tipo explícito como o Joey mencionado usando string b="",e="".
Rebecca Chernoff
@RebeccaChernoff: Eu trabalhei na resposta dos outros caras, 689 agora.
Nick Larsen
@NickLarsen, legal - mas não estou olhando. q: Eu ainda preciso de algum tempo para passar pelo meu. Esta foi a minha primeira vez na lógica, tenho certeza de que há lugares em que posso ser mais inteligente sobre a lógica, só preciso de tempo para dar atenção.
Rebecca Chernoff
4

PHP, 403 388 306 caracteres

<?b((int)fgets(STDIN),'');foreach($t as $r)echo$r[0].str_pad($r[2],$w-2*strlen($r[0]),$r[1]).strrev($r[0])."\n";function b($c,$p){global$t,$w;$t[]=array($p.".","-");while($c--){if(($d=trim(fgets(STDIN)))>0)b($d,"| ".$p);else$t[]=array("| ".$p," ",$d);$w=max($w,strlen($d.$p.$p)+4);}$t[]=array($p."'","-");}

Ungolfed:

box((int)fgets(STDIN), '');

foreach($table as $row) {
    $prefix = $row[0];
    $pad = $row[1];
    $data = $row[2];
    echo $prefix . str_pad($data, ($width - 2*strlen($prefix)), $pad) . strrev($prefix)."\n";
}

function box($count,$prefix) {
    global $table, $width;
    $table[] = array($prefix.".","-");
    while($count--) {
        if(($data = trim(fgets(STDIN))) > 0) {
            box($data, "| ".$prefix);
        } else {
            $table[] = array("| ".$prefix, " ", $data);
        }
        $width = max($width,strlen($data.$prefix.$prefix)+4);
    }
    $table[] = array($prefix."'","-");
}
?>

Peguei emprestada a ideia do prefixo de Keith (isso é permitido?), Caso contrário, isso é muito parecido com o original. Ainda não conseguia ficar abaixo de 300. Preso com isso. Em diante.

Samuli K
fonte
2
Bem, o código é público aqui em todos os casos, portanto, emprestar idéias é permitido e talvez até encorajado. Eu acho que isso também é algo que diferencia este site de outros similares. Como um mordomo observou , competimos e colaboramos ao mesmo tempo .
Joey
3

PHP, 806 769 721 653 619 caracteres

<?php function A($a,$b,$c,&$d){for($e=$b;$e>0;$e--){$f=fgets($a);if(false===$f){return;}$g=intval($f);if(0<$g){$h[]=A($a,$g,$c+1,$d);}else{$f=trim($f);$h[]=$f;$j=strlen($f)+4*$c;if($d<$j){$d=$j;}}}return $h;}$d=0;$h=A(STDIN,intval(fgets(STDIN)),1,&$d);function B($k,$c,$d){$f=str_pad('',$d-4*$c-2,'-',2);return C($k.$f.$k,$c,$d);}function C($f,$c,$d){$f=str_pad($f,$d-4*$c,' ');$f=str_pad($f,$d-2*$c,'| ',0);$f=str_pad($f,$d,' |');return $f;}function D($l,$c,$d){if(!is_array($l)){echo C($l,$c,$d)."\n";return;}echo B('.',$c,$d)."\n";foreach($l as $m){echo D($m,$c+1,$d);}echo B('\'',$c,$d)."\n";}D($h,0,$d);exit(0);?>

Versão não destruída:

<?php
function read_itemgroup($handle, $item_count, $depth, &$width) {

    //$items = array();

    for($i = $item_count; $i > 0; $i--) {
        $line = fgets( $handle );
        if(false === $line) {
            return;
        }

        $line_int = intval($line);
        if(0 < $line_int) {
            // nested group
            $items[] = read_itemgroup($handle, $line_int, $depth + 1, $width);
        }
        else {
            // standalone item
            $line = trim($line);
            $items[] = $line;

            // determine width of item at current depth
            $width_at_depth = strlen($line) + 4 * $depth;
            if($width < $width_at_depth) {
                $width = $width_at_depth;
            }
        }
    }

    return $items;
}
$width = 0;
$items = read_itemgroup(STDIN, intval(fgets( STDIN )), 1, &$width);

//var_dump($items, $width);

function render_line($corner, $depth, $width) {
    $line = str_pad('', $width - 4 * $depth - 2, '-', 2); // 2 = STR_PAD_BOTH
    return render_item($corner . $line . $corner, $depth, $width);
}

function render_item($line, $depth, $width) {
    $line = str_pad($line, $width - 4 * $depth, ' ');
    $line = str_pad($line, $width - 2 * $depth, '| ', 0); // 0 = STR_PAD_LEFT
    $line = str_pad($line, $width, ' |');
    return $line;
}

function render($item, $depth, $width) {
    if(!is_array($item)) {
        echo render_item($item, $depth, $width) . "\n";
        return;
    }
    echo render_line('.', $depth, $width) . "\n";
    foreach($item as $nested_item) {
        echo render($nested_item, $depth + 1, $width);
    }
    echo render_line('\'', $depth, $width) . "\n";
}

render($items, 0, $width);

exit(0);
?>
Ratos
fonte
Por que você está usando nomes de função de duas letras em vez de nomes de uma letra?
Lowjacker
@ Lowkacler: boa captura, isso é uma coisa que ainda preciso otimizar. Eu não tinha nenhum minifier em mãos, então fiz isso manualmente. Eu também tenho várias idéias sobre o que aprimorar (código, não minificação), então postarei uma versão revisada mais tarde.
MicE
11
Primeiro de tudo, isso está faltando um <?no início para ser executado. Aparentemente, você está usando o comprimento máximo de todos os itens de texto em um caso de teste como a largura da caixa mais interna. Esse código passa apenas em 118 dos casos de teste (testados no Linux e FreeBSD). Eu não tenho idéia o que você fez para o script PowerShell que não iria funcionar, embora :-( Invocando-lo como. powershell -noprofile -file test.ps1 php boxes.phpDeve funcionar, na verdade Mas eu não tenho PHP na minha máquina Windows para teste..
Joey
Testei isso na minha caixa usando o script bash mais recente, tenho 118/156. I colocar a saída em uma essência
Juan
11
É bom ouvir :). Isso é o que eu recebo para escrever um script de teste que foi inicialmente destinado para a saída de linha única ;-)
Joey
3

Java - 681 668 caracteres

import java.util.*;public class b{static int m,h,i;public static void main(String[]a)throws Throwable{for(Object o:z("")){a=(String[])o;String s=a[0]+a[1];i=a[0].length();for(h=0;h<m-i*2-a[1].length();h++){s+=a[2];}for(h=i;h>0;h--){s+=a[0].charAt(h-1);}System.out.println(s);}}static List z(String p)throws Throwable{String b="",d="";List l=new ArrayList();while((i=System.in.read())>-1){if(10==i){if(d!=""){String[]v={p+".",b,"-"},t={p+"'",b,"-"};l.add(v);for(int u=0;u<Integer.parseInt(d);u++){l.addAll(z(p+"| "));}l.add(t);}else{h=b.length()+p.length()*2;if(m<h)m=h;String[]v={p,b," "};l.add(v);}break;}else if(i>47&&i<58){d+=(char)i;}else {b+=(char)i;}}return l;}}

essencialmente o mesmo método que o código Python de Keith Randall

Versão não destruída:

import java.util.*;

public class b {
    static int m, h, i;

    public static void main(String[] a) throws Throwable {
        for (Object o : z("")) {
            a = (String[]) o;
            String s = a[0] + a[1];
            i = a[0].length();
            for (h = 0; h < m - i * 2 - a[1].length(); h++) {
                s += a[2];
            }
            for (h = i; h > 0; h--) {
                s += a[0].charAt(h - 1);
            }
            System.out.println(s);
        }
    }

    static List z(String p) throws Throwable {
        String b = "", d = "";
        List l = new ArrayList();
        while ((i = System.in.read()) > -1) {
            if (10 == i) {
                if (d != "") {
                    String[] v = { p + ".", b, "-" }, t = { p + "'", b, "-" };
                    l.add(v);
                    for (int u = 0; u < Integer.parseInt(d); u++) {
                        l.addAll(z(p + "| "));
                    }
                    l.add(t);
                } else {
                    h = b.length() + p.length() * 2;
                    if (m < h)
                        m = h;
                    String[] v = { p, b, " " };
                    l.add(v);
                }
                break;
            } else if (i > 47 && i < 58) {
                d += (char) i;
            } else {
                b += (char) i;
            }
        }
        return l;
    }
}
Greg Schueler
fonte
Eu acho que você pode se livrar de um espaço cada vez que houver um throws.
Joey #
sim! também elminou mais alguns caracteres. (pode supor que cada linha é terminada com caractere de nova linha, redundante break;)
Greg Schueler
provavelmente poderia finesse as charcomparações, olhando para códigos ASCII para mais ... mas eu tenho que ir prepare-se para férias
Greg Schueler
3

Perl - 200 199 caracteres

Mesmo algoritmo que o Python de Keith Randall (design agradável, Keith), mas um pouco mais compacto neste Perl.

sub P{$_=<>;chop;$m>($l=length"$_@_@_")or$m=$l;/^\d/?(["@_.","","-"],(map{P("| @_")}1..$_),["@_'","","-"]):["@_",$_," "]}map{($q,$t,$f)=@$_;print"$q$t",($f x($m-length"$q$t$q")).reverse($q),"\n"}(P);
DCharness
fonte
11
$_@_@_parece alguém perseguindo o sinal de cifrão
ajax333221 27/03
3

F # - 341 caracteres

let rec f(x,y)=[
 let l=stdin.ReadLine()
 let q,d=Core.int.TryParse l
 if q then
  yield x+".","",'-',"."+y
  for i=1 to d do yield!f(x+"| ",y+" |")
  yield x+"'","",'-',"'"+y
 else yield x,l,' ',y]
let l=f("","")
for w,x,y,z in l do printfn"%s"(w+x.PadRight(List.max(l|>List.map(fun(w,x,y,z)->2*w.Length+x.Length))-2*w.Length,y)+z)

Uma versão em F # da solução de Keith. Como as listas são imutáveis ​​por padrão, essa versão reúne toda a função recursiva em uma lista e retorna a lista, da qual os itens são extraídos usando o for..doloop e a yield!. Não consegui encontrar uma maneira de reverter o prefixo de forma concisa, então apenas coloquei o sufixo nos triplos.

Para sua informação, o método TryParse retorna um duplo (bool,int).

nharren
fonte
2

Clojure - 480 caracteres

(use '[clojure.contrib.string :only (repeat)])(let [r ((fn p[%](repeatedly % #(let [x (read-line)](try(doall(p(Integer/parseInt x)))(catch Exception e x))))) 1)]((fn z[m,n,o] (let[b #( let[p(dec o)](println(str(repeat p "| ")%(repeat(- m(* 4 p)2)"-")%(repeat p " |"))))](b \.)(doseq[i n](if(seq? i)(z m i(inc o))(println(str(repeat o "| ")i(repeat(- m(count i)(* o 4))" ")(repeat o " |")))))(b \')))((fn w[x](reduce max(map(fn[%](if(seq? %)(+ (w %)4)(count %)))x)))r)(first r) 1))

Este é o meu primeiro programa Clojure e a minha primeira tentativa de golfe Clojure; portanto, nem é preciso dizer que isso não deve ser considerado um representante das soluções Clojure em geral. Tenho certeza de que poderia ser reduzido significativamente, especialmente se o método de Keith Randall de analisar e construir as caixas de uma só vez fosse implementado.

Casey
fonte
Cara, metade dessa fonte deve estar em branco. E obrigatoriamente :-). Interessante, embora e eu me pergunto se alguém vai ver uma variante Lisp ganhar um golf código ;-)
Joey
Tenho certeza de que é possível ... embora, como eu disse, provavelmente não vou ser o único a fazê-lo.
Casey
2

C # - 472 470 426 422 398 caracteres

using System.Linq;using y=System.Console;class W{static void Main(){var c=new int[5];var s=new string[0].ToList();int n=0,i;var l="";do{try{c[n]=int.Parse(l=y.ReadLine());l=".{1}.";n++;i=1;}catch{l+="{0}";i=0;}G:while(i++<n)l="| "+l+" |";s.Add(l);if(n>0&&--c[n-1]<0){n--;l="'{1}'";i=0;goto G;}}while(n>0);s.ForEach(z=>y.WriteLine(z,l="".PadLeft(s.Max(v=>v.Length)-z.Length),l.Replace(' ','-')));}}
nharren
fonte
Agradável. A goto! By the way, você pode omitir os parênteses em torno dos argumentos lambda ze v, trazendo este para baixo a 421.
Joey
2

Scala - 475 caracteres

object N2 extends App{type S=String;def b(x:List[S],t:Int,s:S,e:S):List[S]={var l=x;o=o:+(s+".-±-."+e+"-");for(i<-1 to t)if(l.head.matches("\\d+"))l=b(l.tail,l.head.toInt,s+"| ",e+" |")else{o=o:+(s+"| "+l.head+"±"+e+" | ");l=l.drop(1)};o=o:+(s+"'-±-'"+e+"-");return l};var o:List[S]=List();val l=io.Source.stdin.getLines.toList;b(l.tail,l.head.toInt,"","");(o map(x=>x.replaceAll("±",x.last.toString*((o sortBy((_:S).length)).last.length-x.length)).dropRight(1)))map println}
Gareth
fonte
1

C # 1198 1156 1142 689 671 634 caracteres

using z=System.Console;using System.Collections.Generic;using System.Linq;
class T{bool U;List<T> a=new List<T>();string m;IEnumerable<string>R(int s){if(U){yield return ".".PadRight(s-1,'-')+".";foreach(var e in a.SelectMany(b=>b.R(s-4)))yield return ("| "+e).PadRight(s-e.Length)+" |";yield return "'".PadRight(s-1,'-')+"'";}else yield return m;}int L(){return U?a.Max(x=>x.L())+4:m.Length;}
static void Main(){var p=O(int.Parse(z.ReadLine()));z.WriteLine(string.Join("\r\n",p.R(p.L())));}
static T O(int n){var k=new T(){U=true};while(n-->0){var l=z.ReadLine();int c;k.a.Add(int.TryParse(l,out c)?O(c):new T{m=l});}return k;}}
Fatal
fonte
11
A versão ungolfed está disponível no github - github.com/paulduran/CodeGolf
Fatal
Entrar com \nparece ser suficiente no final.
Joey
Livrar-se da interface liberou muitos caracteres, o resto era principalmente golfe padrão. Há muito mais que pode ser feito aqui, eu esperaria que isso poderia ficar abaixo de 600.
Nick Larsen
Bom trabalho, Nick. Suspeitei que a interface fosse um pouco exagerada, para ser sincero. uma bandeira simples seria suficiente nessa situação, como você mostrou.
Fatal
0

Pip , 89 bytes (não concorrente)

(A linguagem é mais nova que o desafio. Além disso, eu não conseguia superar o APL.)

O código é 87 bytes, +2 para -rnsinalizadores.

(z:{I+YPOi{Y{Vz}M,ym:MX#*Y$ALyY'|.s._.sX++m-#_.'|MyY".."J'-X++mALyAL"''"J'-Xm}yALl}i:g)

Experimente online!

A função zprocessa o primeiro item da lista de entrada ( gcopiado para a variável global ipara estar disponível nas chamadas de função). Se esse for um número n , ele se chama recursivamente n vezes, coloca a lista de linhas resultante em um retângulo completo, agrupa cada linha "| " " |"e adiciona .---.e '---'linhas antes de retornar a nova lista. Se for uma string, simplesmente a converte em uma lista de um item e a retorna. O resultado final é impresso com nova linha separada ( -nsinalizador). Mais detalhes disponíveis mediante solicitação.

DLosc
fonte
Normalmente, eu não tenho um problema com linguagens mais recentes do que o desafio, especialmente considerando que o problema não é tão trivial que uma língua recém-criado teria operações especificamente para resolvê-lo :-)
Joey
Isso falha na quarta amostra.
21417 Joey
0

Java (1369 caracteres, incluindo EOLs)

Não foi possível deixar isso sem uma implementação Java. Supõe-se que Java seja mais detalhado que os truques de Python e Ruby, por isso optei por uma solução elegante e recursiva.

A idéia é uma árvore (gráfico) de objetos (strings e caixas), contendo um ao outro a partir de uma caixa "head". Ao analisar linearmente o arquivo de entrada, você adiciona seqüências de caracteres e caixas à caixa "atual" e, enquanto adiciona, o comprimento máximo do contêiner é ajustado. Quando um contêiner atinge a quantidade de itens predefinidos que pode reter o retorno ao contêiner anterior. No final do arquivo de entrada, você tem um contêiner "head" que já possui um "maxLength" calculado; portanto, basta chamar o método print ().

import java.io.*;import java.util.*;
public class N{private static String rPad(String s,int l){return s+str(l-s.length(),' ');}
private static String str(int l, char c){StringBuffer sb=new StringBuffer();while(l-->0){sb.append(c);}return sb.toString();}
private static class Box {Box prnt=null;String txt=null;int items;List<Box> c=new ArrayList<Box>();int maxLength=0;
public Box(Box p,int n){prnt=p;items=n;if(p!=null){p.c.add(this);}}
public Box(Box p,String s){prnt=p;txt=s;if(p!=null){p.c.add(this);p.notify(s.length());}}
public void print(String prefix,int l,String suffix){if (txt == null){System.out.println(prefix+"."+str(l-2,'-')+"."+suffix);for(Box b:c){b.print(prefix+"| ",l-4," |"+suffix);}System.out.println(prefix+"'"+str(l-2,'-')+"'"+suffix);}else{System.out.println(prefix+rPad(txt,l)+suffix);}}
protected void notify(int l){if (l+4>this.maxLength){this.maxLength=l + 4;if (this.prnt != null){this.prnt.notify(this.maxLength);}}}}
public static void main(String[] args)throws IOException{Box head=null;Box b=null;BufferedReader in=new BufferedReader(new InputStreamReader(System.in));String s;while ((s=in.readLine()) != null){try{int n=Integer.parseInt(s);b=new Box(b, n);}catch (NumberFormatException nfe){b=new Box(b, s);}if(head == null)head=b;while ((b != null) && (b.items == b.c.size())){b=b.prnt;}}head.print("",head.maxLength,"");}}

É realmente uma solução agradável para escrever. Gostei muito da pergunta. Como mencionei anteriormente, optei pela elegância da solução e não pela abordagem minimalista, infelizmente o Java não possui a impressão "-" * 4 do Python para produzir "----" :-)

Aqui está a versão não destruída:

import java.io.*;
import java.util.*;

public class NestedBoxes
{

    private static String rPad ( String s, int l )
    {
        return s + str(l - s.length(), ' ');
    }

    private static String str ( int l, char c )
    {
        StringBuffer sb = new StringBuffer();
        while (l-- > 0)
        {
            sb.append(c);
        }
        return sb.toString();
    }

    private static class Box
    {

        Box parent = null;
        String text = null;
        int items;
        List<Box> contents = new ArrayList<Box>();

        int maxLength = 0;

        public Box ( Box p, int n )
        {
            parent = p;
            items = n;
            if (p != null)
            {
                p.contents.add(this);
            }
        }

        public Box ( Box p, String s )
        {
            parent = p;
            text = s;
            if (p != null)
            {
                p.contents.add(this);
                p.notify(s.length());
            }
        }

        public void print ( String prefix, int l, String suffix )
        {
            if (text == null)
            {
                System.out.println(prefix + "." + str(l - 2, '-') + "." + suffix);
                for (Box b : contents)
                {
                    b.print(prefix + "| ", l - 4, " |" + suffix);
                }
                System.out.println(prefix + "'" + str(l - 2, '-') + "'" + suffix);
            }
            else
            {
                System.out.println(prefix + rPad(text, l) + suffix);
            }
        }

        protected void notify ( int l )
        {
            if (l + 4 > this.maxLength)
            {
                this.maxLength = l + 4;
                if (this.parent != null)
                {
                    this.parent.notify(this.maxLength);
                }
            }
        }
    }

    public static void main ( String[] args ) throws IOException
    {
        Box head = null;
        Box b = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String s;
        while ((s = in.readLine()) != null)
        {
            try
            {
                int n = Integer.parseInt(s);
                b = new Box(b, n);
            }
            catch (NumberFormatException nfe)
            {
                b = new Box(b, s);
            }

            if (head == null)
            {
                head = b;
            }

            while ((b != null) && (b.items == b.contents.size()))
            {
                b = b.parent;
            }
        }
        head.print("", head.maxLength, "");
    }
}
ksymeon
fonte
4
Você sabe, isso é um código de golfe . Você deve pelo menos tentar apontar para uma pequena solução. A elegância é ótima e agradável, mas não é realmente necessária nem desejada aqui.
Joey