1P5: Zagnieżdżone pola

53

To zadanie jest częścią First Periodic Premier Programming Puzzle Push .

Otrzymasz hierarchię pozycji w następującym formacie:

2
Hat
1
Gloves

które należy umieścić w pudełkach, np .:

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

W formacie wejściowym liczby zaczynają się od pola zawierającego tyle elementów, ile określa liczba. Pierwsze pudełko zawiera dwa przedmioty (Kapelusz i pudełko zawierające Rękawiczki), drugie zawiera tylko jeden przedmiot - rękawiczki.

Jak widać, pudła mogą również mieszkać wewnątrz pudełek. I zawsze są zaokrąglone ... w pewnym sensie (spiczaste rogi stanowią zagrożenie dla ran i nie chcielibyśmy tego).

Poniżej znajdują się paskudne szczegóły dla tych, którzy chcą wykorzystać każdą najmniejszą swobodę, jaką daje specyfikacja. Pamiętaj, że nie czytanie specyfikacji nie jest usprawiedliwieniem do przesyłania złych rozwiązań. Na samym końcu znajduje się skrypt testowy i kilka przypadków testowych.


Specyfikacja

  • Pudełka są zbudowane z następujących znaków:

    • | (U + 007C) służy do budowy pionowych krawędzi.
    • - (U + 002D) służy do konstruowania poziomych krawędzi.
    • ' (U + 0027) to okrągłe dolne rogi.
    • . (U + 002E) to okrągłe górne rogi.

    Dlatego pudełko wygląda następująco:

    .--.
    |  |
    '--'
    

    Zauważ, że chociaż Unicode ma również okrągłe rogi i odpowiednie znaki do rysowania ramek, to zadanie jest tylko w ASCII. Chociaż uwielbiam Unicode, zdaję sobie sprawę, że istnieją języki i środowiska, które nie dotarły do ​​końca w ciągu ostatniej dekady.

  • Pudełka mogą zawierać sekwencję elementów, które są tekstem lub innymi elementami. Poszczególne elementy w pudełku są renderowane od góry do dołu. Sekwencja A, B, C jest zatem następująca:

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

    Dotyczy to oczywiście również zagnieżdżonych pól, które są tak samo jak tekst. Tak więc sekwencja A, B, Box (C, Box (D, E)), F wyglądałaby następująco:

    .-----------.
    | A         |
    | B         |
    | .-------. |
    | | C     | |
    | | .---. | |
    | | | D | | |
    | | | E | | |
    | | '---' | |
    | '-------' |
    | F         |
    '-----------'
    
  • Pola dostosowują swój rozmiar do zawartości, a pola zagnieżdżone zawsze rozciągają się na rozmiar elementu nadrzędnego. Zawsze jest spacja przed i po zawartości, więc ani tekst, ani zagnieżdżone pola nie są zbyt blisko krawędzi zewnętrznego pola. Krótko mówiąc, następujące informacje są błędne:

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

    I poprawne jest:

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

    Wygląda też o wiele ładniej :-)

  • Elementy tekstowe (patrz Wejście poniżej) muszą być dokładnie odtworzone.

  • Zawsze jest jedno pole najwyższego poziomu (por. XML). Jednak jedno pudełko może zawierać kilka innych pól.

Wejście

  • Dane wejściowe są podawane na standardowe dane wejściowe; dla łatwiejszego testowania prawdopodobnie przekierowane z pliku.

  • Dane wejściowe są podawane liniowo, przy czym każda linia reprezentuje albo element tekstowy, który ma zostać umieszczony w bieżącym polu, albo otwiera nowe pole.

  • Każda linia kończy się przerwaniem linii.

  • Elementy tekstowe są oznaczone linią, która nie składa się z liczby (patrz poniżej). Tekst używa znaków alfabetu, spacji i interpunkcji ( .,-'"?!()). Tekst nie będzie zaczynać się ani kończyć spacją i zawsze będzie miał co najmniej jeden znak.

  • Pole zaczyna się od pojedynczego wiersza z liczbą. Liczba określa rozmiar pudełka, tj. Liczbę następujących elementów, które są w nim umieszczone:

    2
    A
    B
    

    daje pole z dwoma elementami tekstowymi:

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

    Pudełko zawsze będzie zawierało co najmniej jeden przedmiot.

  • Koniec pól nie jest wyraźnie oznaczony linią; zamiast tego pola są domyślnie zamykane po umieszczeniu w nich określonej liczby elementów.

  • Pudełko jest zawsze tylko pojedynczym przedmiotem, niezależnie od tego, ile jest w nim przedmiotów. Na przykład

    3
    A
    4
    a
    b
    c
    d
    B
    

    da pudełko z trzema przedmiotami, z których drugie to kolejne pudełko z czterema przedmiotami.

    Zagnieżdżanie nie wpływa również na fakt, że pudełko jest tylko jednym przedmiotem.

Granice

  • Maksymalny poziom zagnieżdżenia to pięć . Tzn. W środku jest najwyżej pięć pudeł. Dotyczy to również najbardziej zewnętrznego.

  • Opakowanie zawiera maksymalnie dziesięć przedmiotów.

  • Elementy tekstowe mają maksymalną długość 100 znaków.

Wynik

  • Dane wyjściowe to renderowane pole zawierające wszystkie elementy zawierające i zagnieżdżone zgodnie z zasadami opisanymi powyżej.
  • Dane wyjściowe powinny być podane na wyjściu standardowym i muszą być dokładnie dopasowane. Niedozwolone są wiodące lub końcowe białe znaki.
  • Każda linia musi być zakończona podziałem linii, w tym ostatnią.

Warunki wygranej

  • Najkrótszy kod wygrywa (tzn. Otrzymuje akceptowaną odpowiedź).

Przykładowe dane wejściowe 1

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

Próbka wyjściowa 1

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

Przykładowe wejście 2

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

Przykładowe wyjście 2

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

Przykładowe dane wejściowe 3

1
1
1
1
1
Extreme nesting Part Two

Próbka wyjściowa 3

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

Przykładowe wejście 4

3
Foo
2
Bar
Baz
2
Gak
1
Another foo?

Próbka wyjściowa 4

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

Skrypt testowy

Ponieważ prawidłowe uzyskanie szczegółów może być czasami trudne (my i Ventero ) przygotowaliśmy skrypt testowy, w którym możesz uruchomić swoje rozwiązanie, aby sprawdzić, czy jest poprawne. Jest dostępny zarówno jako skrypt PowerShell, jak i skrypt bash . Inwokacja jest: <test-script> <program invocation>.

AKTUALIZACJA: Skrypty testowe zostały zaktualizowane; było wiele przypadków testowych, które nie respektowały określonych przeze mnie limitów. Skrypt testowy PowerShell nie używał porównania wielkości liter do sprawdzania wyniku. Mam nadzieję, że teraz wszystko jest w porządku. Liczba przypadków testowych została zmniejszona do 156, chociaż ostatni jest teraz dość ... duży.

AKTUALIZACJA 2: Przesłałem mój generator przypadków testowych . Napisane w języku C # , ukierunkowane na środowisko uruchomieniowe .NET 2. Działa na Mono. Może to pomóc ludziom przetestować ich wdrożenie. Jako najgorszy przypadek, biorąc pod uwagę ograniczenia zadania, możesz spróbować:

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

który wygeneruje tylko pola do najbardziej wewnętrznego poziomu i wykorzysta zarówno maksymalną liczbę elementów w polu, jak i maksymalną długość elementów tekstowych. Nie uwzględniłem tego przypadku testowego w skrypcie testowym, ponieważ jest on dość duży, a wynik jeszcze większy.

AKTUALIZACJA 3: Zaktualizowałem skrypt testowy PowerShell, który miał skłonność do zgłaszania błędów w zależności od tego, jak kończą się linie w skrypcie i jakie końce linii drukuje rozwiązanie. Teraz powinno być agnostyczne dla obu. Jeszcze raz przepraszam za zamieszanie.

Joey
źródło
Mówisz, że pola powinny dostosowywać ich rozmiar do zawartości. Jednak w ostatnim przykładzie pierwsze pudełko wewnętrzne dostosowuje swój rozmiar do pudełka zewnętrznego. W jaki sposób zagnieżdżone boksy mają swój rozmiar?
Juan
@Juan: Dzięki za złapanie tego. Niesamowite, że takie poślizgnięcia się zdarzają. Edytowano :-)
Joey,
1
@Joey An oldy ale goody. Mamy nadzieję, że zainspiruje niektórych naszych nowych użytkowników do pisania dobrych, dobrze określonych pytań. :-)
Gareth
@Gareth, zdecydowanie powinienem znaleźć czas na napisanie ich więcej. Ale dobrze sprecyzowane pytanie, przypadki testowe, implementacja referencji i inne rzeczy (rzeczy, które uważam za niezbędne dla konkurencji, ale wielu nie podziela tego poglądu;)) wymagają czasu. Było o wiele łatwiej, będąc w uni: D
Joey

Odpowiedzi:

2

GolfScript, 125 znaków

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

Stosując podobne podejście jak rozwiązanie Keitha .

Howard
źródło
26

Python, 204 znaki

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]

Pzwraca listę trójek, z których każda jest prefiksem / sufiksem linii (sufiksem jest odwrotność prefiksu), pewnym tekstem linii i znakiem wypełnienia linii. Po obliczeniu wszystkich trójek są one drukowane przy użyciu odpowiedniej liczby znaków wypełnienia, aby wszystkie linie miały tę samą długość.

Wersja bez golfa:

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
źródło
Zaraz, to było szybkie. I ciekawy pomysł P.
Joey,
Wow, w rzeczy samej. To interesujące, czy możesz opublikować wersję bez golfa? Chciałbym zrozumieć, jak działa bit eval. Heh, moje rozwiązanie dla nieposkromionego pytona to ponad 1500 znaków :( Chociaż mam zupełnie inne (i nieefektywne) podejście.
Casey
@Casey: eval jest tylko skrótem golfowym dla pętli, nie jest fundamentalny. Wkrótce opublikuję wersję bez golfa ...
Keith Randall
13

Ruby 1.9, 174 znaków

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}

Nieco podobne do rozwiązania Keitha .

Ventero
źródło
6

APL (78)

{∧/⎕D∊⍨I←⍞:{∆,('-'⍪⍵⍪'-'),∆←'.|'''/⍨1(⊃⍴⍵)1}⍕⍪/{⍵↑[2]⍨⌈/⊃∘⌽∘⍴¨∆}¨∆←∇¨⍳⍎I⋄⍉⍪I}⍬
marinus
źródło
5
co to nawet nie
wiem
Nie mogę uruchomić tego na tio.run, aby przetestować rozwiązanie. W przeciwnym razie zmieniłbym również zaakceptowaną odpowiedź.
Joey,
5

Python - 355 314 259 znaków

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
źródło
prawie 100 znaków redukcji, dobra robota.
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
źródło
5

C, 390 366 363 znaków

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

Połącz z gcc -std=gnu99 -w file.c

Nawet nie jest zbliżona do wersji Keitha, ale hej, to jest dobre, stare

Esneider
źródło
Przechodzi tutaj tylko 159 ze 160 testów.
Joey,
Ojej. Myślę, że teraz jest OK. W skrajnym przypadku zapomniałem przydzielić miejsce na \ 0.
esneider
Wygląda tak samo, test nr 142 nie powiedzie się. Nawiasem mówiąc, rzeczywisty ekstremalny przypadek nie jest nawet obecny, ponieważ ma wejście 10 MiB i wyjście 78 MiB. Nie chciałem, żeby skrypt testowy był tak duży ;-)
Joey,
dziwne, dostaję 160/160 passed(miałem na myśli ciąg 100 znaków, który i tak nie jest obecny)
esneider
Hm, dziwne. FreeBSD 8.2-RELEASE #5: Sun Feb 27 10:40:25 CET 2011z gcc version 4.2.1 20070719 [FreeBSD]na x64 tutaj. Uwierzę ci na 160, a potem :-). I powinien istnieć przypadek testowy ze 100 znakami (Testy 143–147).
Joey,
4

bardzo funkcjonalny python, 460 znaków

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
źródło
Hm, to nie wydaje mi się, że |postacie nie są poprawnie rozmieszczone. Jest bardzo podobny do mojego rozwiązania w Pythonie
Casey
2
Rzeczywiście, nie przechodzi żadnego z przypadków testowych. eordano: Uwzględniliśmy te, aby nikt nie składał już odpowiedzi, które są całkowicie błędne.
Joey
1
Chyba wkleiłem starą wersję kodu. Powinien działać teraz. Przepraszam, że jestem nieprofesjonalny.
eordano
Pracuje dla mnie! Ładne rozwiązanie, podoba mi się funkcjonalne podejście.
Casey
Rzeczywiście, działa teraz.
Joey
4

Haskell, 297 znaków

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

Podczas gry w golfa metoda jest dość prosta. Dostępne są tylko limity pamięci.

MtnViewMark
źródło
4

C # - 1005 859 852 782 znaków

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

Muszę rzucić na to okiem, ponieważ jestem pewien, że można to poprawić, ale jest to moje pierwsze przejście na trzecie przejście.

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
źródło
@Joey, tak, zdecydowanie muszę to wszystko powtórzyć. Musisz zagrać z logiką, aby ją również ograniczyć.
Rebecca Chernoff
Nie jestem zaznajomieni z C, ale w JS, można połączyć wiele instrukcji var do jednego, tak: var a = 1, b = 2, c = 3;. Nie możesz zrobić tego samego w C?
nyuszika7h
2
@ Nyuszika7H, to jest C #, nie C. Nie można łączyć takich niejawnych varstwierdzeń. Możesz łączyć tylko wtedy, gdy mają wyraźny typ, o którym wspominał Joey string b="",e="".
Rebecca Chernoff
@RececcaChernoff: Pracowałem nad odpowiedzią innych facetów, teraz 689.
Nick Larsen
@NickLarsen, miło - ale nie patrzę. P: Nadal potrzebuję trochę czasu, aby przejść przez mój. To był mój pierwszy krok w logice, jestem pewien, że są miejsca, w których mogę być mądrzejszy w logice, po prostu potrzebuję czasu, aby zwrócić na to uwagę.
Rebecca Chernoff
4

PHP, 403 388 306 znaków

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

Nie golfowany:

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

Pożyczyłem pomysł Keixa na prefiks (czy to w ogóle dozwolone?), W przeciwnym razie jest to mniej więcej oryginał. Nadal nie mógł spaść poniżej 300. Utknąłem z tym. Dalej.

Samuli K
źródło
2
Kod jest tutaj publiczny w każdym przypadku, więc pożyczanie pomysłów jest dozwolone, a może nawet zachęcane. Myślę, że jest to również coś, co odróżnia tę stronę od innych, podobnych. Jak zauważył gnibbler , jednocześnie konkurujemy ze sobą i współpracujemy .
Joey,
3

PHP, 806 769 721 653 619 znaków

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

Wersja bez golfa:

<?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
źródło
Dlaczego używasz dwuliterowych nazw funkcji zamiast jednoliterowych?
Lowjacker
@Lowkacler: dobry połów, to jedna rzecz, którą wciąż muszę zoptymalizować. Nie miałem pod ręką żadnego wzmacniacza, więc zrobiłem to ręcznie. Mam też kilka pomysłów na ulepszenia (kodowanie, a nie minimalizacja), więc później opublikuję poprawioną wersję.
MicE
1
Przede wszystkim brakuje <?na początku nawet uruchomienia. Wtedy najwyraźniej używasz maksymalnej długości wszystkich elementów tekstowych w przypadku testowym jako szerokości najbardziej wewnętrznego pola. Ten kod przekazuje tylko 118 przypadków testowych (testowanych w systemie Linux i FreeBSD). Nie mam pojęcia, co zrobiłeś ze skryptem PowerShell, który by nie działał :-(. Wywołanie go tak, jak powershell -noprofile -file test.ps1 php boxes.phppowinno działać, w rzeczywistości. Ale nie mam PHP na moim komputerze z systemem Windows do przetestowania.
Joey
Przetestowałem to na moim urządzeniu przy użyciu najnowszego skryptu bash, otrzymałem 118/156. Włożyłem wyjście na GIST
Juan
1
Miło słyszeć :). To właśnie dostaję za napisanie skryptu testowego, który początkowo był przeznaczony do wyjścia jednowierszowego ;-)
Joey,
3

Java - 681 668 znaków

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

zasadniczo taka sama metoda jak kod Pythona Keitha Randalla

Wersja bez golfa:

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
źródło
Myślę, że możesz pozbyć się jednego miejsca za każdym razem, gdy jest throws.
Joey
tak! wydalił także kilka innych znaków. (można założyć, każdy wiersz jest zakończony z nowej linii char, zbędny break;)
Greg Schueler
Prawdopodobnie mógł finezji tych charporównań patrząc na kody ASCII na dłużej ... ale muszę iść przygotować się do urlopu
Greg SCHUELER
3

Perl - 200 199 znaków

Ten sam algorytm jak Python Keitha Randalla (ładny design, Keith), ale akceptuje go nieco bardziej kompaktowy w tym Perlu.

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
źródło
1
$_@_@_wygląda na to, że ktoś ściga znak dolara
ajax333221
3

F # - 341 znaków

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)

Wersja F # rozwiązania Keitha. Listy są domyślnie niezmienne, więc ta wersja umieszcza całą funkcję rekurencyjną w liście, zwraca listę, z której elementy są wyodrębniane za pomocą for..dopętli i a yield!. Nie mogłem znaleźć sposobu na zwięzłe odwrócenie prefiksu, więc po prostu przyłączyłem sufiks do potrójnych.

Do Twojej wiadomości, metoda TryParse zwraca wartość podwójną (bool,int).

Nharren
źródło
2

Clojure - 480 znaków

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

To mój pierwszy program Clojure, a także moja pierwsza próba golfowa Clojure, więc nie trzeba dodawać, że nie należy tego traktować jako reprezentatywnego dla rozwiązań Clojure. Jestem pewien, że można by go znacznie skrócić, szczególnie jeśli metoda parsowania i budowania skrzynek jednocześnie zostanie zaimplementowana przez Keitha Randalla .

Casey
źródło
Człowieku, połowa tego źródła musi być spacją. I tak obowiązkowo :-). Ciekawe i zastanawiam się, czy ktoś zobaczy, że wariant Lisp wygrywa golfa kodowego ;-)
Joey,
Jestem pewien, że to możliwe ... chociaż, jak powiedziałem, prawdopodobnie nie będę tym, który to zrobi.
Casey
2

C # - 472 470 426 422 398 znaków

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
źródło
Miły. A goto! Nawiasem mówiąc, możesz pominąć nawiasy wokół argumentów lambda zi vsprowadzając to do 421.
Joey
2

Scala - 475 znaków

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
źródło
1

C # 1198 1156 1142 689 671634 znaków

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;}}
Fatalny
źródło
1
Wersja niegolfowana jest dostępna na github - github.com/paulduran/CodeGolf
Fatal
Połączenie z \nwydaje się w końcu wystarczające.
Joey
Pozbawienie interfejsu uwolniło wiele postaci, reszta to w większości standardowe gry w golfa. Jest wiele innych rzeczy, które można zrobić tutaj, spodziewam się, że może to być poniżej 600.
Nick Larsen
Dobra robota, Nick. Szczerze mówiąc, podejrzewałem, że interfejs był trochę przesadzony. zwykła flaga wystarczyłaby w tej sytuacji, jak pokazałeś.
Fatal
0

Pip , 89 bajtów (niekonkurujący)

(Język jest nowszy niż wyzwanie. Poza tym nie mogłem całkowicie prześcignąć APL-a).

Kod to 87 bajtów, +2 dla -rnflag.

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

Wypróbuj online!

Funkcja zprzetwarza pierwszy element listy danych wejściowych ( gskopiowany do zmiennej globalnej i, aby był dostępny w wywołaniach funkcji). Jeśli jest to liczba n , wywołuje się rekurencyjnie n razy, "| " " |"wstawia wynikową listę linii do pełnego prostokąta, zawija każdą linię i dodaje .---.i '---'linie przed zwróceniem nowej listy. Jeśli jest to ciąg znaków, po prostu konwertuje go na listę jednopunktową i zwraca. Ostateczny wynik jest drukowany jako separator nowej linii ( -nflaga). Więcej szczegółów dostępnych na życzenie.

DLosc
źródło
Zwykle nie mam problemu z językami nowszymi niż wyzwanie, szczególnie biorąc pod uwagę, że problem nie jest tak trywialny, że nowo utworzony język będzie miał operacje specjalnie do jego rozwiązania :-)
Joey
To nie udaje się czwartej próby.
Joey
0

Java (1369 znaków łącznie z EOL)

Nie można tego zostawić bez implementacji Java. Java ma być bardziej gadatliwa niż sztuczki Pythona i Ruby, więc wybrałem eleganckie, rekurencyjne rozwiązanie.

Chodzi o drzewo (wykres) obiektów (ciągi i pola), zawierające się nawzajem, zaczynając od pola „głowy”. Podczas liniowego przetwarzania pliku wejściowego dodajesz ciągi i pola do pola „bieżącego”, a podczas dodawania dostosowywana jest maksymalna długość kontenera. Kiedy kontener osiągnie liczbę predefiniowanych przedmiotów, które może Cię zatrzymać, powróć do poprzedniego kontenera. Na końcu pliku wejściowego znajduje się kontener „head”, który ma już obliczoną wartość „maxLength”, więc wystarczy wywołać jego metodę 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,"");}}

To naprawdę przyjemne rozwiązanie do pisania. Bardzo podobało mi się to pytanie. Jak wspomniałem wcześniej, zdecydowałem się na elegancję rozwiązania, a nie minimalistyczne podejście, niestety Java nie ma wydruku Pythona „-” * 4 do wyprodukowania ”----„ :-)

Oto wersja bez golfa:

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
źródło
4
Wiesz, to jest golf golfowy . Powinieneś przynajmniej spróbować dążyć do małego rozwiązania. Elegancja jest ładna i ma się dobrze, ale nie jest tutaj wymagana ani pożądana.
Joey