1P5: boîtes imbriquées

53

Cette tâche fait partie de la première poussée périodique de programmation Premier .

Vous obtenez une hiérarchie d'éléments dans le format suivant:

2
Hat
1
Gloves

qui doivent être mis dans des boîtes, comme suit:

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

Dans le format d'entrée, les nombres commencent par une zone contenant autant d'éléments que le nombre spécifié. La première boîte contient deux éléments (le chapeau et la boîte contenant les gants), la seconde ne contient qu'un seul élément, les gants.

Comme on peut le constater, les boîtes peuvent aussi vivre à l’intérieur des boîtes. Et ils sont toujours arrondis ... en quelque sorte (les coins pointus représentent un risque de blessure et nous ne le voudrions pas).

Ci-dessous, vous trouverez les détails désagréables pour ceux qui veulent utiliser chaque petite marge de manœuvre offerte par la spécification. Attention, ne pas lire les spécifications n'est pas une excuse pour soumettre de mauvaises solutions. Il y a un script de test et quelques cas de test à la fin.


spécification

  • Les boîtes sont construites à partir des caractères suivants:

    • | (U + 007C) est utilisé pour construire les arêtes verticales.
    • - (U + 002D) est utilisé pour construire les arêtes horizontales.
    • ' (U + 0027) sont les coins arrondis inférieurs.
    • . (U + 002E) sont les coins supérieurs arrondis.

    Une boîte ressemble donc à ceci:

    .--.
    |  |
    '--'
    

    Notez que, même si Unicode a aussi des coins arrondis et des caractères de dessin de boîte appropriés, cette tâche est en ASCII uniquement. Bien que j'aime Unicode, je me rends compte qu'il existe des langages et des environnements qui ne sont pas encore arrivés avant la dernière décennie.

  • Les boîtes peuvent contenir une séquence d'éléments qui sont du texte ou d'autres éléments. Les éléments individuels dans une boîte sont rendus de haut en bas. La séquence A, B, C se traduit ainsi:

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

    Ceci s'applique bien sûr aussi aux boîtes imbriquées, qui sont un élément au même titre que du texte. Ainsi, la séquence A, B, Boîte (C, Boîte (D, E)), F rendrait comme suit:

    .-----------.
    | A         |
    | B         |
    | .-------. |
    | | C     | |
    | | .---. | |
    | | | D | | |
    | | | E | | |
    | | '---' | |
    | '-------' |
    | F         |
    '-----------'
    
  • Les cases ajustent leur taille au contenu et les cases imbriquées s'étendent toujours à la taille de leur parent. Il y a toujours un espace avant et après le contenu, de sorte que ni le texte ni les zones imbriquées ne soient trop proches du bord de la zone extérieure. En bref, ce qui suit est faux:

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

    Et ce qui suit est correct:

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

    C'est beaucoup plus joli aussi :-)

  • Les éléments de texte (voir Entrée ci-dessous) doivent être reproduits exactement.

  • Il y a toujours une seule boîte de premier niveau (cf. XML). Cependant, une boîte peut contenir plusieurs autres boîtes.

Contribution

  • L'entrée est donnée sur l'entrée standard; pour un test plus facile probablement redirigé à partir d'un fichier.

  • L'entrée est donnée ligne par ligne, chaque ligne représentant un élément de texte à insérer dans la zone actuelle ou en ouvrant une nouvelle.

  • Chaque ligne est terminée par un saut de ligne.

  • Les éléments de texte sont marqués par une ligne qui ne consiste pas en un nombre (voir ci-dessous). Le texte utilise des caractères alphabétiques, l’espace et la ponctuation ( .,-'"?!()). Le texte ne commencera ni ne finira par un espace et aura toujours au moins un caractère.

  • Une boîte commence par une seule ligne avec un numéro. Le nombre indique la taille de la boîte, c'est-à-dire le nombre d'éléments suivants qui y sont placés:

    2
    A
    B
    

    donne une boîte avec deux éléments de texte:

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

    Une boîte contiendra toujours au moins un élément.

  • La fin des cases n'est pas explicitement marquée par une ligne; au lieu de cela, les boîtes sont implicitement fermées une fois que le nombre d'éléments spécifié y est placé.

  • Une boîte est toujours constituée d'un seul élément, quel que soit le nombre d'éléments qu'il contient. Par exemple

    3
    A
    4
    a
    b
    c
    d
    B
    

    donnera une boîte avec trois articles, le second est une autre boîte avec quatre articles.

    L'imbrication n'affecte pas non plus le fait qu'une boîte n'est qu'un seul élément.

Limites

  • Le niveau de nidification maximal est de cinq . C'est-à-dire qu'il y a au plus cinq boîtes l'une dans l'autre. Cela inclut le plus externe.

  • Il y a un maximum de dix articles par boîte.

  • Les éléments de texte ont une longueur maximale de 100 caractères.

Sortie

  • La sortie est la boîte rendue incluant tous les éléments contenant et imbriqués conformément aux règles décrites ci-dessus.
  • La sortie doit être donnée sur la sortie standard et doit correspondre exactement. Aucun espace de début ou de fin n'est autorisé.
  • Chaque ligne doit être terminée par un saut de ligne, y compris le dernier.

Condition gagnante

  • Le code le plus court gagne (c'est-à-dire qu'il obtient la réponse acceptée).

Exemple d'entrée 1

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

Exemple de sortie 1

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

Exemple d'entrée 2

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

Exemple de sortie 2

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

Exemple d'entrée 3

1
1
1
1
1
Extreme nesting Part Two

Exemple de sortie 3

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

Exemple d'entrée 4

3
Foo
2
Bar
Baz
2
Gak
1
Another foo?

Exemple de sortie 4

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

Script de test

Étant donné qu'il peut être difficile d'obtenir des détails corrects, nous ( Ventero et moi) avons déjà préparé un script de test avec lequel vous pouvez exécuter votre solution pour vérifier si elle est correcte. Il est disponible en tant que script PowerShell et script bash . L' invocation est: <test-script> <program invocation>.

UPDATE: Les scripts de test ont été mis à jour. il y a eu un certain nombre de cas tests qui n'ont pas respecté les limites que j'ai définies. Le script de test PowerShell n'a pas utilisé de comparaison sensible à la casse pour vérifier le résultat. J'espère que tout va bien maintenant. Le nombre de cas tests a été réduit à 156, bien que le dernier soit maintenant ... assez grand.

MISE À JOUR 2: J'ai téléchargé mon générateur de cas de test . Écrit en C # , ciblant le runtime .NET 2. Il fonctionne sur Mono. Cela peut aider les gens à tester leur mise en œuvre. En tant que pire cas définitif étant donné les limites de la tâche, vous pouvez essayer:

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

qui générera uniquement des boîtes jusqu'au niveau le plus profond et utilisera à la fois le nombre maximal d'éléments par boîte et la longueur maximale d'éléments de texte. Je n'ai toutefois pas inclus ce scénario dans le script de test, car il est assez volumineux et la sortie encore plus volumineuse.

MISE À JOUR 3: J'ai mis à jour le script de test PowerShell qui risquait de générer des erreurs en fonction de la fin des lignes dans le script et de la fin de ligne imprimée par la solution. Maintenant, il devrait être agnostique pour les deux. Désolé encore pour la confusion.

Joey
la source
Vous dites que les boîtes doivent ajuster leur taille à leur contenu. Pourtant, dans le dernier exemple, la première boîte intérieure ajuste sa taille à la boîte extérieure. Alors, comment les boîtes imbriquées obtiennent-elles leur taille?
Juan
@Juan: Merci d'avoir attrapé ça. Incroyable que glisse comme ceux qui se produisent encore. Edited :-)
Joey Le
1
@ Joey Un vieux mais un goody. Espérons que cela puisse inspirer certains de nos nouveaux utilisateurs à écrire de bonnes questions bien spécifiées. :-)
Gareth
@Gareth, je devrais absolument essayer de trouver le temps d'écrire plus de ceux-là. Mais une question bien spécifiée, des scénarios de test, une implémentation de référence et d'autres éléments (des éléments que j'estime essentiels pour un concours, mais que beaucoup ne partagent pas cet avis;)) prennent du temps. C'était beaucoup plus facile en université: D
Joey

Réponses:

2

GolfScript, 125 caractères

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

En utilisant une approche similaire à celle de la solution de Keith .

Howard
la source
26

Python, 204 caractères

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]

Prenvoie une liste de triplets, chacun étant un préfixe de ligne / suffixe (le suffixe étant l'inverse du préfixe), du texte de ligne et un caractère de remplissage de ligne. Après avoir calculé tous les triplets, ils sont imprimés avec le bon nombre de caractères de remplissage pour que toutes les lignes aient la même longueur.

Version non-golfée:

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
la source
Whoa, c'était rapide. Et idée intéressante avec Plà.
Joey
Wow, en effet. C'est intéressant, pouvez-vous poster la version non-golfée? J'aimerais comprendre comment fonctionne le bit eval. Heh, ma solution de python non-golfée est de plus de 1500 caractères :( Bien que je prenne une approche totalement différente (et inefficace).
Casey
@ Casey: eval n'est qu'un raccourci golfique pour une boucle, ce n'est pas fondamental. Je posterai une version non-golfée dans une seconde ...
Keith Randall
13

Ruby 1.9, 174 caractères

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}

Un peu similaire à la solution de Keith .

Ventero
la source
6

APL (78)

{∧/⎕D∊⍨I←⍞:{∆,('-'⍪⍵⍪'-'),∆←'.|'''/⍨1(⊃⍴⍵)1}⍕⍪/{⍵↑[2]⍨⌈/⊃∘⌽∘⍴¨∆}¨∆←∇¨⍳⍎I⋄⍉⍪I}⍬
marinus
la source
5
Qu'est-ce que je ne
fais
Je ne parviens pas à exécuter ceci sur tio.run pour tester la solution. Sinon, je changerais aussi la réponse acceptée.
Joey
5

Python - 355 314 259 caractères

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
la source
presque une réduction de 100 caractères, bon travail.
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
la source
5

C, 390 366 363 caractères

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

Compiler avec gcc -std=gnu99 -w file.c

Pas même proche de la version de Keith, mais bon, c'est bon vieux

esneider
la source
Ne passe que 159 des 160 tests ici.
Joey le
Aie. Je pense que maintenant ça va. J'oubliais d'allouer de l'espace pour le \ 0 dans le cas extrême.
esneider
On dirait toujours la même chose, le test n ° 142 échoue. En passant, le cas extrême actuel n’est même pas présent, car il possède 10 entrées et 78 sorties. Je ne voulais pas que le script de test soit aussi volumineux ;-)
Joey Le
bizarre, 160/160 passed
j'obtiens
Hm, bizarre. FreeBSD 8.2-RELEASE #5: Sun Feb 27 10:40:25 CET 2011avec gcc version 4.2.1 20070719 [FreeBSD]sur x64 ici. Je te crois sur parole pour le 160, alors :-). Et il devrait y avoir un scénario de test avec 100 caractères, en fait (tests 143 à 147).
Joey le
4

python très fonctionnel, 460 caractères

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
la source
Hm, cela ne semble pas fonctionner pour moi, les |caractères ne sont pas correctement espacés. C'est très similaire à ma solution python
Casey Le
2
En effet, ne passe aucun des cas de test. eordano: Nous avons inclus ceux-ci afin que personne ne soumette plus de réponses tout simplement fausses.
Joey
1
Je suppose que j'ai collé une ancienne version du code. Devrait travailler maintenant. Désolé d'être non professionnel.
eordano
Travaille pour moi! Belle solution, j'aime l'approche fonctionnelle.
Casey
En effet, fonctionne maintenant.
Joey
4

Haskell, 297 caractères

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

Alors que golf'd, la méthode est assez simple. Seules les limites sont la mémoire disponible.

MtnViewMark
la source
4

C # - 1005 859 852 782 caractères

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

Je dois examiner cela de nouveau car je suis sûr que cela peut être amélioré, mais c'est mon troisième essai initial .

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
la source
@ Joey, oui, j'ai vraiment besoin de tout refaire. Besoin de jouer avec la logique pour essayer de le réduire également.
Rebecca Chernoff le
Je ne suis pas familier avec le C, mais JS, vous pouvez combiner plusieurs déclarations var à un, comme ceci: var a = 1, b = 2, c = 3;. Tu ne peux pas faire la même chose en C?
nyuszika7h
2
@ Nyuszika7H, il s'agit de C #, pas de C. Vous ne pouvez pas combiner des vardéclarations implicites de ce genre. Vous ne pouvez combiner que s'ils ont un type explicite comme Joey, mentionné en utilisant string b="",e="".
Rebecca Chernoff le
@ RebeccaChernoff: J'ai travaillé sur la réponse des autres gars, 689 maintenant.
Nick Larsen le
@ NickLarsen, bien - mais je ne cherche pas. q: J'ai encore besoin de temps pour parcourir le mien. C’était ma première approche de la logique, je suis sûr que je peux être plus intelligent dans certains domaines, il me faut juste un peu de temps pour l’attirer.
Rebecca Chernoff le
4

PHP, 403 388 306 caractères

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

J'ai emprunté le préfixe-idée à Keith (est-ce permis?), Sinon c'est assez semblable à l'original. Je ne pouvais toujours pas descendre en dessous de 300. Coincé avec ça. En avant.

Samuli K
la source
2
Le code est ici public dans tous les cas, donc emprunter des idées est autorisé et peut-être même encouragé. Je pense que c'est aussi quelque chose qui différencie ce site d'autres sites similaires. Comme le dit le gnibbler, nous sommes en concurrence et collaborons en même temps .
Joey
3

PHP, 806 769 721 653 619 caractères

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

Version non-golfée:

<?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);
?>
MicE
la source
Pourquoi utilisez-vous des noms de fonction à deux lettres au lieu de noms à une lettre?
Lowjacker
@ Lowkacler: bonne capture, c'est une chose que je dois encore optimiser. Je n'avais pas de minifier sous la main, alors je l'ai fait manuellement. J'ai aussi plusieurs idées sur ce qu'il faut améliorer (codément, pas la minification), alors je posterai une version révisée plus tard.
MicE
1
Tout d’abord, il manque <?au début une course. Ensuite, vous utilisez apparemment la longueur maximale de tous les éléments de texte dans un scénario de test comme largeur pour la zone la plus à l'intérieur. Ce code ne transmet que 118 des cas de test (testés sous Linux et FreeBSD). Je n'ai aucune idée de ce que vous avez fait au script PowerShell selon lequel il ne fonctionnerait pas :-(. L'appeler comme tel powershell -noprofile -file test.ps1 php boxes.phpdevrait fonctionner, en fait. Mais je n'ai pas de code PHP sur ma machine Windows à tester.
Joey le
Testé cela sur ma boîte en utilisant le dernier script bash, obtenu 118/156. Je mets la sortie sur un élément essentiel
Juan
1
Bon de l'entendre :). C'est ce que je reçois pour l'écriture d'un script de test destiné initialement à une sortie sur une seule ligne ;-)
Joey le
3

Java - 681 668 caractères

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

essentiellement la même méthode que le code Python de Keith Randall

Version non-golfée:

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
la source
Je pense que vous pouvez vous débarrasser d'un espace à chaque fois qu'il y en a un throws.
Joey
Oui! a également éliminé quelques personnages de plus. (peut supposer que chaque ligne est terminée par un caractère nouvelle ligne, redondant break;)
Greg Schueler
On pourrait probablement affiner les charcomparaisons en regardant les codes ASCII plus longtemps ... mais je dois me préparer pour les vacances
Greg Schueler
3

Perl - 200 199 caractères

Même algorithme que Python de Keith Randall (joli design, Keith), mais un peu plus compact dans cette version 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);
Décharger
la source
1
$_@_@_on dirait que quelqu'un
court après le
3

F # - 341 caractères

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)

Une version F # de la solution de Keith. Les listes étant immuables par défaut, cette version intègre la totalité de la fonction récursive dans une liste et renvoie la liste à partir de laquelle les éléments sont extraits à l'aide de la for..doboucle et de la commande a yield!. Je ne pouvais pas trouver un moyen d'inverser le préfixe de manière concise, alors j'ai simplement attaché le suffixe aux triples.

Pour votre information, la méthode TryParse renvoie un double (bool,int).

Nharren
la source
2

Clojure - 480 caractères

(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))

Il s’agit de mon premier programme Clojure et de ma première tentative de golf Clojure. Inutile donc de dire que cela ne doit pas être considéré comme représentatif des solutions Clojure en général. Je suis sûr que cela pourrait être considérablement raccourci, surtout si la méthode d'analyse et de construction des boîtes à la fois de Keith Randall était appliquée.

Casey
la source
Homme, la moitié de cette source doit être un espace. Et obligatoirement alors :-). Intéressant, cependant, et je me demande si on verra une variante Lisp gagner un code golf ;-)
Joey
Je suis sûr que c'est possible ... bien que, comme je l'ai dit, je ne serai probablement pas le seul à le faire.
Casey
2

C # - 472 470 426 422 398 caractères

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
la source
Agréable. Un goto! En passant, vous pouvez omettre les parenthèses autour des arguments lambda zet vramener cela à 421.
Joey
2

Scala - 475 caractères

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
la source
1

C # 1198 1156 1142 689 671 634 Caractères

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
la source
1
La version non-golfée est disponible sur github - github.com/paulduran/CodeGolf
Fatal
Rejoindre avec \nsemble suffire à la fin.
Joey
Se débarrasser de l’interface libéra un grand nombre de personnages, le reste était essentiellement du golf standard. Il y a beaucoup d'autres choses qui peuvent être faites ici, je pense que cela pourrait être inférieur à 600.
Nick Larsen
Beau travail Nick. Je pensais que l'interface était un peu exagérée, pour être honnête. un simple drapeau aurait suffi dans cette situation, comme vous l'avez montré.
Fatal
0

Pip , 89 octets (non concurrents)

(La langue est plus récente que le défi. En outre, je ne pouvais pas tout à fait surgluter APL.)

Le code est 87 octets, +2 pour les -rndrapeaux.

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

Essayez-le en ligne!

La fonction ztraite le premier élément de la liste d'entrées ( g, copiée dans une variable globale iafin d'être disponible dans les appels de fonction). Si ce chiffre est n , il se dit récursive n fois, la liste des tampons résultant des lignes à un rectangle plein, enveloppe chaque ligne "| " " |"et ajoute .---.et les '---'lignes avant de retourner la nouvelle liste. S'il s'agit d'une chaîne, il la convertit simplement en une liste à un élément et la renvoie. Le résultat final est imprimé séparé par une ligne ( -ndrapeau). Plus de détails disponibles sur demande.

DLosc
la source
D'habitude, je n'ai pas de problème avec les langues plus récentes que le défi, d'autant plus que le problème n'est pas si trivial qu'une langue nouvellement créée aurait des opérations spécifiques pour le résoudre :-)
Joey, le
Cela échoue le quatrième échantillon.
Joey
0

Java (1369 caractères, y compris les EOL)

Impossible de laisser cela sans implémentation Java. Java est supposé être plus bavard que les nappes de Python et de Ruby, alors je suis allé vers une solution élégante et récursive.

L'idée est un arbre (graphe) d'objets (chaînes et boites), se contenant les uns les autres à partir d'une boite "tête". Lorsque vous analysez linéairement le fichier d'entrée, vous ajoutez des chaînes et des cases à la case "actuelle" et pendant que vous ajoutez, la longueur maximale du conteneur est ajustée. Lorsqu'un conteneur atteint la quantité d'éléments prédéfinis, il peut vous permettre de revenir au conteneur précédent. À la fin du fichier d'entrée, vous avez un conteneur "head" qui a déjà un "maxLength" calculé, vous appelez donc simplement sa méthode 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,"");}}

C'est vraiment une solution agréable à écrire. J'ai beaucoup aimé la question. Comme je l'ai mentionné plus tôt, j'ai opté pour une élégance des solutions plutôt qu'une approche minimaliste. Malheureusement, Java n'a pas l'empreinte de Python "-" * 4 pour produire "----" :-)

Voici la version non-golfée:

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
la source
4
Vous savez, ceci est un code de golf . Vous devriez au moins essayer de viser une petite solution. L’élégance est belle et bien, mais elle n’est ni requise ni voulue ici.
Joey