1P5: cajas anidadas


53

Esta tarea forma parte del primer empuje de programación periódica Premier Puzzle .

Obtiene una jerarquía de elementos en el siguiente formato:

2
Hat
1
Gloves

que deben colocarse en cajas, así:

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

En el formato de entrada, los números comienzan un cuadro con tantos elementos como el número especifica. La primera caja tiene dos elementos (el Sombrero y la caja que contiene los Guantes), la segunda solo contiene un elemento: los guantes.

Como se puede ver, las cajas también pueden vivir dentro de las cajas. Y siempre son redondeados ... más o menos (las esquinas puntiagudas son un riesgo de herida y no quisiéramos eso).

A continuación, se encuentran los detalles desagradables para aquellos que desean utilizar cada pequeño margen de maniobra que brinda la especificación. Eso sí, no leer las especificaciones no es excusa para enviar soluciones incorrectas. Hay un script de prueba y algunos casos de prueba al final.


Especificación

  • Las cajas se construyen a partir de los siguientes caracteres:

    • | (U + 007C) se utiliza para construir los bordes verticales.
    • - (U + 002D) se utiliza para construir los bordes horizontales.
    • ' (U + 0027) son las esquinas inferiores redondas.
    • . (U + 002E) son las esquinas superiores redondas.

    Por lo tanto, una caja se ve así:

    .--.
    |  |
    '--'
    

    Tenga en cuenta que, si bien Unicode también tiene esquinas redondeadas y caracteres de dibujo de recuadro adecuados, esta tarea es solo en ASCII. Por mucho que amo a Unicode, me doy cuenta de que hay idiomas y entornos que no llegaron en la segunda a la última década.

  • Los cuadros pueden contener una secuencia de elementos que son texto u otros elementos. Los elementos individuales en un cuadro se representan de arriba a abajo. La secuencia A, B, C se presenta así:

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

    Por supuesto, esto también se aplica a los cuadros anidados, que son un elemento similar al texto. Entonces la secuencia A, B, Box (C, Box (D, E)), F se representaría de la siguiente manera:

    .-----------.
    | A         |
    | B         |
    | .-------. |
    | | C     | |
    | | .---. | |
    | | | D | | |
    | | | E | | |
    | | '---' | |
    | '-------' |
    | F         |
    '-----------'
    
  • Los cuadros ajustan su tamaño al contenido y los cuadros anidados siempre se extienden al tamaño de sus padres. Siempre hay un espacio antes y después del contenido, de modo que ni el texto ni los cuadros anidados estén demasiado cerca del borde del cuadro exterior. En resumen, lo siguiente está mal:

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

    Y lo siguiente es correcto:

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

    También se ve mucho mejor :-)

  • Los elementos de texto (ver Entrada a continuación) deben reproducirse exactamente.

  • Siempre hay un único cuadro de nivel superior (cf. XML). Sin embargo, un cuadro puede contener varios otros cuadros.

Entrada

  • La entrada se da en la entrada estándar; para una prueba más fácil, probablemente redirigido desde un archivo.

  • La entrada se da en línea, y cada línea representa un elemento de texto para colocar en el cuadro actual o abrir un nuevo cuadro.

  • Cada línea termina con un salto de línea.

  • Los elementos de texto están marcados por una línea que no consta de un número (ver más abajo). El texto usa caracteres alfabéticos, el espacio y la puntuación ( .,-'"?!()). El texto no comenzará ni terminará con un espacio y siempre tendrá al menos un carácter.

  • Un cuadro comienza con una sola línea con un número. El número indica el tamaño del cuadro, es decir, el número de elementos siguientes que se colocan en él:

    2
    A
    B
    

    produce un cuadro con dos elementos de texto:

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

    Una caja siempre contendrá al menos un elemento.

  • El final de los cuadros no está marcado explícitamente con una línea; en su lugar, los cuadros se cierran implícitamente después de que se les coloca el número especificado de elementos.

  • Un cuadro siempre es un solo elemento, independientemente de cuántos elementos contenga. P.ej

    3
    A
    4
    a
    b
    c
    d
    B
    

    producirá una caja con tres elementos, el segundo de los cuales es otra caja con cuatro elementos.

    La anidación tampoco afecta el hecho de que una caja es solo un elemento.

Límites

  • El nivel máximo de anidación es cinco . Es decir, hay como máximo cinco cajas una dentro de la otra. Esto incluye el más externo.

  • Hay un máximo de diez artículos por caja.

  • Los elementos de texto tienen una longitud máxima de 100 caracteres.

Salida

  • La salida es el cuadro representado que incluye todos los elementos que contienen y anidados según las reglas descritas anteriormente.
  • La salida debe darse en la salida estándar y debe coincidir exactamente. No se permiten espacios en blanco iniciales o finales.
  • Cada línea debe terminar con un salto de línea, incluida la última.

Condición ganadora

  • El código más corto gana (es decir, obtiene la respuesta aceptada).

Entrada de muestra 1

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

Salida de muestra 1

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

Entrada de muestra 2

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

Salida de muestra 2

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

Entrada de muestra 3

1
1
1
1
1
Extreme nesting Part Two

Salida de muestra 3

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

Entrada de muestra 4

3
Foo
2
Bar
Baz
2
Gak
1
Another foo?

Salida de muestra 4

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

Script de prueba

Dado que obtener los detalles correctos puede ser difícil en ocasiones, nosotros ( Ventero y yo) hemos preparado un script de prueba con el que puede ejecutar su solución para verificar si es correcta. Está disponible como un script de PowerShell y un script de bash . Invocación es: <test-script> <program invocation>.

ACTUALIZACIÓN: los scripts de prueba se han actualizado; hubo varios casos de prueba que no cumplieron con los límites que definí. El script de prueba de PowerShell no utilizó la comparación entre mayúsculas y minúsculas para verificar el resultado. Espero que todo esté bien ahora. El número de casos de prueba se redujo a 156, aunque el último ahora es bastante ... grande.

ACTUALIZACIÓN 2: cargué mi generador de casos de prueba . Escrito en C # , dirigido al tiempo de ejecución de .NET 2. Se ejecuta en mono. Puede ayudar a las personas a probar su implementación. Como peor caso definitivo dados los límites en la tarea, puede intentar:

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

que generará solo cuadros hasta el nivel más interno y utilizará tanto el número máximo de elementos por cuadro como la longitud máxima de elementos de texto. Sin embargo, no incluí este caso de prueba en el script de prueba, ya que es bastante grande y la salida aún más grande.

ACTUALIZACIÓN 3: Actualicé el script de prueba de PowerShell que era propenso a generar errores dependiendo de cómo estaban las terminaciones de línea en el script y qué terminaciones de línea imprimía la solución. Ahora debería ser agnóstico para ambos. Perdón de nuevo por la confusión.


Dices que las cajas deben ajustar su tamaño a su contenido. Sin embargo, en el último ejemplo, la primera caja interna ajusta su tamaño a la caja externa. Entonces, ¿cómo obtienen su tamaño los cuadros anidados?
Juan

@Juan: Gracias por atrapar eso. Asombroso que resbala como si todavía sucediera. Editado :-)
Joey

1
@Joey Un viejo pero bueno. Con suerte, puede inspirar a algunos de nuestros nuevos usuarios a escribir buenas preguntas bien especificadas. :-)
Gareth

@Gareth, definitivamente debería tratar de encontrar el tiempo para escribir más de esos nuevamente. Pero una pregunta bien especificada, casos de prueba, implementación de referencia y otras cosas (cosas que considero esenciales para una competencia, pero esa opinión no es compartida por muchos;)) lleva tiempo. Fue mucho más fácil mientras estaba en la universidad: D
Joey

Respuestas:


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 un enfoque similar a la solución de Keith .


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]

Pdevuelve una lista de triples, cada uno de los cuales es un prefijo / sufijo de línea (el sufijo es el reverso del prefijo), un texto de línea y un carácter de relleno de línea. Después de calcular todos los triples, se imprimen utilizando el número correcto de caracteres de relleno para que todas las líneas tengan la misma longitud.

Versión sin golf:

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]

Whoa, eso fue rápido. Y una idea interesante con Peso.
Joey

Wow, de hecho. Esto es interesante, ¿puedes publicar la versión sin golf? Me gustaría entender cómo funciona el bit eval. Heh, mi solución de Python sin golf es 1500+ caracteres :( Aunque tomo un enfoque totalmente diferente (e ineficiente).
Casey

@Casey: eval es solo un atajo de golf para un bucle, no es fundamental. Publicaré una versión sin golf en un 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}

Algo similar a la solución de Keith .


6

APL (78)

{∧/⎕D∊⍨I←⍞:{∆,('-'⍪⍵⍪'-'),∆←'.|'''/⍨1(⊃⍴⍵)1}⍕⍪/{⍵↑[2]⍨⌈/⊃∘⌽∘⍴¨∆}¨∆←∇¨⍳⍎I⋄⍉⍪I}⍬

55
¿
Qué

No puedo hacer que esto se ejecute en tio.run para probar la solución. De lo contrario, cambiaría la respuesta aceptada también.
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

casi una reducción de 100 char, buen trabajo.
Casey

5

Rubí 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]]

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

Compilar con gcc -std=gnu99 -w file.c

Ni siquiera cerca de la versión de Keith, pero bueno, está bien.


Pasa solo 159 de las 160 pruebas aquí.
Joey

Ay. Creo que ahora está bien. Estaba falsificando asignar espacio para \ 0 en el caso extremo.
esneider

Parece igual, la Prueba # 142 falla. Por cierto, el caso extremo real ni siquiera está presente, ya que tiene 10 entradas MiB y 78 salidas MiB. No quería que el script de prueba fuera tan grande ;-)
Joey

extraño, me estoy poniendo 160/160 passed(me refería a una cadena de 100 caracteres, que de todos modos no está presente)
esneider

Hm, raro. FreeBSD 8.2-RELEASE #5: Sun Feb 27 10:40:25 CET 2011con gcc version 4.2.1 20070719 [FreeBSD]el x64 aquí. Tomaré tu palabra para el 160, entonces :-). Y debería haber un caso de prueba con 100 caracteres, en realidad (Pruebas 143–147).
Joey

4

pitón muy 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))

Hm, esto no parece funcionar para mí, los |personajes no están espaciados correctamente. Es muy similar a mi solución de Python
Casey

2
De hecho, no pasa ninguno de los casos de prueba. eordano: Los incluimos para que nadie envíe respuestas que ya no sean correctas.
Joey

1
Supongo que pegué una versión anterior del código. Debería funcionar ahora. Perdón por no ser profesional.
eordano

¡Funciona para mi! Buena solución, me gusta el enfoque funcional.
Casey

De hecho, funciona ahora.
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

Mientras golf'd, el método es bastante sencillo. Solo los límites son memoria disponible.


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

Necesito echarle otro vistazo a esto, ya que estoy seguro de que se puede mejorar, pero este es mi tercer paso 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;
    }
}

@Joey, sí, definitivamente necesito revisarlo todo de nuevo. Necesito jugar con la lógica para intentar reducirlo también.
Rebecca Chernoff

No estoy familiarizado con C, pero en JS, se pueden combinar varias instrucciones var a uno, como esto: var a = 1, b = 2, c = 3;. ¿No puedes hacer lo mismo en C?
nyuszika7h

2
@ Nyuszika7H, esto es C #, no C. No se pueden combinar vardeclaraciones implícitas como esa. Solo puedes combinar si tienen un tipo explícito como el que Joey mencionó usar string b="",e="".
Rebecca Chernoff

@RebeccaChernoff: trabajé en la respuesta de otros chicos, 689 ahora.
Nick Larsen

@NickLarsen, bien, pero no estoy mirando. q: Todavía necesito algo de tiempo para pasar por el mío. Este fue mi primer paso en la lógica, estoy seguro de que hay lugares en los que puedo ser más inteligente acerca de la lógica, solo necesito tiempo para prestarle atención.
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."'","-");}

Sin golf:

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."'","-");
}
?>

Tomé prestada la idea del prefijo de Keith (¿está permitido?), De lo contrario, esto es más o menos como el original. Todavía no podía estar por debajo de 300. Atrapado con esto. Adelante.


2
Bueno, el código es público aquí en todos los casos, por lo que se permite pedir prestado ideas y tal vez incluso alentarlo. Creo que también es algo que diferencia a este sitio de otros similares. Como gnibbler uno notó , competimos y colaboramos al mismo tiempo .
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);?>

Versión sin golf:

<?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);
?>

¿Por qué estás usando nombres de funciones de dos letras en lugar de los de una letra?
Lowjacker

@Lowkacler: buena captura, esa es una cosa que todavía necesito optimizar. No tenía ningún minificador a mano, así que lo hice manualmente. También tengo varias ideas sobre qué mejorar (codewise, no minificación), así que publicaré una versión revisada más adelante.
MicE

1
En primer lugar, a esto le falta un <?principio para incluso ejecutarse. Entonces, aparentemente, está utilizando la longitud máxima de todos los elementos de texto en un caso de prueba como el ancho del cuadro más interno. Este código solo pasa 118 de los casos de prueba (probados en Linux y FreeBSD). No tengo idea de lo que hizo para la secuencia de comandos PowerShell que no iba a funcionar, aunque :-( Invocando como. powershell -noprofile -file test.ps1 php boxes.phpDebería funcionar, en realidad, pero no tengo PHP en mi máquina de Windows a prueba..
Joey

Probé esto en mi caja usando el último script de bash, obtuve 118/156. Puse la salida en una esencia
Juan

1
Que bueno escuchar eso :). Eso es lo que obtengo por escribir un script de prueba que inicialmente estaba destinado a la salida de una sola línea ;-)
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;}}

esencialmente el mismo método que el código Python de Keith Randall

Versión sin golf:

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

Creo que puedes deshacerte de un espacio cada vez que hay un throws.
Joey

¡si! También eliminó algunos caracteres más. (puede suponer que cada línea está terminada con nueva línea char, redundante break;)
Greg Schueler

probablemente podría precisar las charcomparaciones mirando códigos ascii por más tiempo ... pero tengo que ir a prepararme para las vacaciones
Greg Schueler

3

Perl - 200 199 caracteres

El mismo algoritmo que el Python de Keith Randall (diseño agradable, Keith), pero un poco más compacto en esta versión de 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);

1
$_@_@_parece alguien persiguiendo el signo del dólar
ajax333221

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)

Una versión F # de la solución de Keith. Las listas son inmutables por defecto, por lo que esta versión inserta toda la función recursiva en una lista, devuelve la lista, de la que se extraen los elementos usando el for..dobucle y a yield!. No pude encontrar una manera de revertir el prefijo de forma concisa, así que simplemente adjunté el sufijo a los triples.

Para su información, el método TryParse devuelve un doble (bool,int).


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 es mi primer programa de Clojure, así como mi primer intento de golf de Clojure, por lo que, no hace falta decir que esto no debe tomarse como representante de las soluciones de Clojure en general. Estoy seguro de que podría acortarse significativamente, especialmente si el método de Keith Randall de analizar y construir las cajas de inmediato se implementó.


Hombre, la mitad de esta fuente debe ser un espacio en blanco. Y obligatoriamente así :-). Interesante, sin embargo, y me pregunto si uno verá una variante de Lisp ganar un código de golf ;-)
Joey

Estoy seguro de que es posible ... aunque, como dije, probablemente no voy a ser yo quien lo haga.
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(' ','-')));}}

Agradable. A goto! Por cierto, puede omitir los paréntesis en torno a los argumentos lambda zy v, reduciéndolo 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}

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

1
La versión sin golf está en github - github.com/paulduran/CodeGolf
Fatal

Unirse con \nparece ser suficiente al final.
Joey

Deshacerse de la interfaz liberó a muchos personajes, el resto era en su mayoría golf estándar. Hay mucho más que se puede hacer aquí, esperaría que esto pudiera ser inferior a 600.
Nick Larsen

Buen trabajo Nick. Sospeché que la interfaz era un poco exagerada, para ser honesto. una simple bandera habría bastado en esta situación como has demostrado.
Fatal

0

Pip , 89 bytes (no competitivos)

(El lenguaje es más nuevo que el desafío. Además, no pude superar a APL).

El código es de 87 bytes, +2 para las -rnbanderas.

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

Pruébalo en línea!

La función zprocesa el primer elemento de la lista de entrada ( gcopiado en una variable global ipara que esté disponible dentro de las llamadas a funciones). Si este es un número n , se llama a sí mismo recursivamente n veces, rellena la lista de líneas resultante en un rectángulo completo, ajusta cada línea "| " " |"y agrega .---.y '---'líneas antes de devolver la nueva lista. Si es una cadena, simplemente la convierte en una lista de un elemento y la devuelve. El resultado final se imprime separado por una nueva línea ( -nbandera). Más detalles disponibles bajo petición.


Por lo general, no tengo un problema con los idiomas más nuevos que el desafío, especialmente teniendo en cuenta que el problema no es tan trivial que un idioma recién creado tendría operaciones específicas para resolverlo :-)
Joey

Esto falla la cuarta muestra.
Joey

0

Java (1369 caracteres, incluidos EOL)

No podría dejar esto sin una implementación de Java. Se supone que Java es más detallado que los slicks de Python y Ruby, así que busqué una solución elegante y recursiva.

La idea es un árbol (gráfico) de objetos (cadenas y cuadros), que se contienen entre sí a partir de un cuadro de "cabeza". A medida que analiza linealmente el archivo de entrada, agrega cadenas y cuadros al cuadro "actual" y mientras agrega la longitud máxima del contenedor se ajusta. Cuando un contenedor alcanza la cantidad de elementos predefinidos que puede retenerlo, retroceda al contenedor anterior. Al final del archivo de entrada, tiene un contenedor "head" que ya tiene un "maxLength" calculado, por lo que simplemente llama a su 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,"");}}

Es realmente una solución agradable para escribir. Me gustó mucho la pregunta. Como mencioné anteriormente, busqué la elegancia de la solución, no el enfoque minimalista, lamentablemente Java no tiene la impresión de Python "-" * 4 para producir "----" :-)

Aquí está la versión sin golf:

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, "");
    }
}

44
Sabes, este es un código de golf . Al menos deberías intentar apuntar a una pequeña solución. La elegancia es agradable y buena, pero no se requiere ni se desea aquí.
Joey
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.