Teleskopklammern

79

Betrachten Sie eine nicht leere Zeichenfolge mit korrekt ausgeglichenen Klammern:

(()(()())()((())))(())

Wir können uns vorstellen, dass jedes Klammernpaar einen Ring in einer zusammengeklappten Teleskopkonstruktion darstellt . Verlängern wir also das Teleskop:

(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()

Eine andere Betrachtungsweise ist, dass die Klammern in der Tiefe n auf die Linie n verschoben werden , während ihre horizontale Position beibehalten wird.

Ihre Aufgabe ist es, eine solche Folge ausgewogener Klammern zu verwenden und die erweiterte Version zu erstellen.

Sie können ein Programm oder eine Funktion schreiben, indem Sie Eingaben über STDIN (oder das nächste Äquivalent), ein Befehlszeilenargument oder einen Funktionsparameter vornehmen und Ausgaben über STDOUT (oder das nächste Äquivalent), einen Rückgabewert oder einen Funktionsparameter (out) erzeugen.

Sie können davon ausgehen, dass die Eingabezeichenfolge gültig ist, dh nur aus Klammern besteht, die korrekt ausgeglichen sind.

Sie dürfen in jeder Zeile nachgestellte Leerzeichen drucken, jedoch nicht mehr führende Leerzeichen als erforderlich. Insgesamt dürfen die Zeilen nicht länger als die doppelte Länge der Eingabezeichenfolge sein. Sie können optional eine einzelne nachgestellte Zeile drucken.

Beispiele

Neben dem obigen Beispiel gibt es hier noch einige Testfälle (Ein- und Ausgabe sind durch eine Leerzeile getrennt).

()

()
(((())))

(      )
 (    )
  (  )
   ()
()(())((()))(())()

()(  )(    )(  )()
   ()  (  )  ()
        ()
((()())()(()(())()))

(                  )
 (    )()(        )
  ()()    ()(  )()
             ()

Verwandte Herausforderungen:

  • Topographic Strings , bei dem Sie gefragt werden, was im Wesentlichen die Ergänzung der Ausgabe in dieser Herausforderung ist.
  • Code Explanation Formatter , eine breite Verallgemeinerung der Ideen in dieser Herausforderung, wurde kürzlich von PhiNotPi veröffentlicht. (Tatsächlich hat PhiNotPis ursprüngliche Beschreibung seiner Idee diese Herausforderung inspiriert.)

Bestenlisten

Huh, das hat eine Menge Beteiligung gebracht, also hier ein Stack-Snippet, um sowohl eine reguläre Rangliste als auch eine Übersicht der Gewinner nach Sprache zu generieren.

Um sicherzustellen, dass Ihre Antwort angezeigt wird, beginnen Sie Ihre Antwort mit einer Überschrift. Verwenden Sie dazu die folgende Markdown-Vorlage:

# Language Name, N bytes

Wo Nist die Größe Ihres Beitrags? Wenn Sie Ihren Score zu verbessern, Sie können alte Rechnungen in der Überschrift halten, indem man sich durch das Anschlagen. Zum Beispiel:

# Ruby, <s>104</s> <s>101</s> 96 bytes

Martin Ender
quelle
17
Alternativer Titel: De-Lisp-ify eine Zeichenfolge. : P
Alex A.
1
Gibt es Einschränkungen hinsichtlich der Farbe der Ausgabe?
Matteo Italia
1
@ Martinbüttner: vergiss, ich habe einen saubereren weg gefunden; Lassen Sie uns einfach sagen , dass meine früheren Idee , ein Byte zu verlassen alle geschlossenen Klammern rasiert hätte blinkt blau über cyan ... :-)
Matteo Italia
8
@ MatteoItalia oh Gott, ich bin froh, dass das nicht passiert ist. ;)
Martin Ender
12
@ MatteoItalia: Veröffentlichen Sie diese Version! Es ist sehenswert.
user2357112

Antworten:

8

CJam, 17 16 15 Bytes

0000000: 72 3a 69 22 28 0b 20 9b 41 29 22 53 2f 66 3d     r:i"(. .A)"S/f=

Das obige ist ein reversibler xxd-Speicherauszug, da der Quellcode die nicht druckbaren Zeichen VT (0x0b) und CSI (0x9b) enthält.

Wie in dieser Antwort werden ANSI-Escape-Sequenzen verwendet , es werden jedoch auch vertikale Tabulatoren verwendet und die Steuerzeichen werden direkt gedruckt, um die Verwendung von printf zu vermeiden .

Dies erfordert ein unterstützendes Videotext-Terminal, das die meisten Nicht-Windows-Terminalemulatoren enthält.

Testlauf

Wir müssen die Shell-Variable LANG und die Codierung des Terminal-Emulators auf ISO 8859-1 setzen. Ersteres wird durch Ausführung erreicht

$ LANGsave="$LANG"
$ LANG=en_US

Bevor wir den eigentlichen Code ausführen, deaktivieren wir die Eingabeaufforderung und löschen den Bildschirm.

$ PS1save="$PS1"
$ unset PS1
$ clear

Dadurch wird sichergestellt, dass die Ausgabe korrekt angezeigt wird.

echo -n '()(())((()))(())()' | cjam <(base64 -d <<< cjppIigLIJtBKSJTL2Y9)
()(  )(    )(  )()
   ()  (  )  ()
        ()

Führen Sie Folgendes aus, um LANG und die Eingabeaufforderung wiederherzustellen :

$ LANG="$LANGsave"
$ PS1="$PS1save"

Wie es funktioniert

Wir fügen nach jedem einen vertikalen Tabulator ein ( um den Cursor nach unten zu bewegen, und die Bytesequenz 9b 41 ( "\x9bA") vor jedem ) , um den Cursor nach oben zu bewegen.

r         e# Read a whitespace-separated token from STDIN.
:i        e# Replace each character by its code point.
          e#   '(' -> 40, ')' -> 41
"(. .A)"  e# Push the string "(\v \x9bA)".
S/        e# Split at spaces into ["(\v" "\x9bA)"].
f=        e# Select the corresponding chunks.
          e# Since arrays wrap around in CJam, ["(\v" "\x9bA)"]40= and 
          e# ["(\v" "\x9bA)"]41= select the first and second chunk, respectively.
Dennis
quelle
49

x86-Maschinencode, 39 34 33 30 29 Bytes

00000000  68 c3 b8 07 31 ff be 82  00 b3 a0 ad 4e 3c 28 7c  |h...1.......N<(||
00000010  f0 77 05 ab 01 df eb f3  29 df ab eb ee           |.w......)....|
0000001d

x86-Assembly für DOS mit einigen Tricks:

    org 100h

section .text

start:
    ; point the segment ES to video memory
    ; (c3 is chosen so that it doubles as a "ret")
    push 0b8c3h
    pop es
    ; di: output pointer to video memory
    xor di,di
    ; si: input pointer from the command line
    mov si,82h
    ; one row=160 bytes (assume bh=0, as should be)
    mov bl,160
lop:
    ; read & increment si (assume direction flag clean)
    ; we read a whole word, so that later we have something nonzero to
    ; put into character attributes
    lodsw
    ; we read 2 bytes, go back 1
    dec si
    ; check what we read
    cmp al,'('
    ; less than `(`: we got the final `\n` - quit
    ; (we jump mid-instruction to get a c3 i.e. a ret)
    jl start+1
    ; more than `(`: assume we got a `)`
    ja closed
    ; write a whole word (char+attrs), so we end
    ; one position on the right
    stosw
    ; move down
    add di,bx
    ; rinse & repeat
    jmp lop
closed:
    ; move up
    sub di,bx
    ; as above
    stosw
    jmp lop

Einschränkungen :

  • Es wird immer beginnend am unteren Bildschirmrand gedruckt, ohne es vorher zu löschen. ein clsvorheriges Laufen ist fast obligatorisch;
  • die Farben sind hässlich; Dies ist die Folge des Recyclings des nächsten Zeichens als Farbattribut, um hier und da zwei Bytes zu sparen.
  • der Code wird angenommen bh=0und das Richtungsflag wird beim Start gelöscht, beide undokumentiert; OTOH bxwird in allen DOS-Varianten, die ich gesehen habe (DosBox, MS-DOS 2, FreeDOS), explizit auf Null gesetzt, und überall, wo ich die Flags getestet habe, waren sie bereits in Ordnung.

Bildbeschreibung hier eingeben

Matteo Italia
quelle
Ich habe das gerade verifiziert. Ja es funktioniert. Müssen Sie das wirklich tun cld?
FUZxxl
@FUZxxl: Auf DosBox funktioniert es auch ohne, aber wenn man sich die Quellen ansieht, sagt es, dass die Flags von allem, was zuvor in DOS und in TRS passiert ist, erhalten bleiben, also wäre es wahrscheinlich erforderlich, auf Nummer sicher zu gehen. Wie auch immer, das wäre nur ein Byte, die eigentliche Auszahlung wäre, mindestens eines dieser großen (= 4 Byte pro Byte) add/ zu töten sub.
Matteo Italia
Hm ... eigentlich keine Ahnung.
FUZxxl
Können Sie ändern lopzu loop?
mbomb007
@ mbomb007: vielleicht? Ich bin mir nicht sicher, ob nasmzwischen der loopBezeichnung und loopder Montageanleitung eine lopeindeutige Trennung besteht. Deshalb schreibe ich wie alle anderen auch.
Matteo Italia
28

J 32 28 Bytes

Dies war ein Spaß.

0|:')(('&(i.-<:@+/\@i:){."0]

Erläuterung

So funktioniert diese Lösung, einschließlich einer Erläuterung, wie Golf gespielt wurde.

   NB. Let a be a test case
   a =. '((()())()(()(())()))'

   NB. level alterations
   _1 + ').(' i. a
1 1 1 _1 1 _1 _1 1 _1 1 1 _1 1 1 _1 _1 1 _1 _1 _1

   NB. absolute levels
   +/\ _1 + ').(' i. a
1 2 3 2 3 2 1 2 1 2 3 2 3 4 3 2 3 2 1 0

   NB. adjusted levels
   (+/\ _1 + ').(' i. a) - ')(' i. a
0 1 2 2 2 2 1 1 1 1 2 2 2 3 3 2 2 2 1 0

   NB. take level from end of each item of a and transpose
   |: a {."0~ _1 - (+/\ _1 + ').(' i. a) - ')(' i. a
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

   NB. code as a tacit verb
   [: |: ] {."0~ _1 - ([: +/\ _1 + ').(' i. ]) - ')(' i. ]

   NB. subtractions pulled into the prefix insert
   [: |: ] {."0~ (')(' i. ]) - [: <:@+/\ ').(' i. ]

   NB. i: instead of i. so we can use the same string constant
   [: |: ] {."0~ (')((' i. ]) - [: <:@+/\ ')((' i: ]

   NB. get rid of the caps
   0 |: ] {."0~ (')((' i. ]) - ')((' <:@+/\@i: ]

   NB. join the two usages of ')((' into a single dyadic phrase
   0 |: ] {."0~ ')((' (i. - <:@+/\@i:) ]

   NB. bond ')((' and flip arguments to {."0
   0 |: ')(('&(i. - <:@+/\@i:) {."0 ]
FUZxxl
quelle
1
Sehr schön! Die Lösung steckt voller großartiger Teile!
Randomra
1
(Normalerweise füge ich einen Beispielaufruf der Funktion hinzu, damit auch nicht erfahrene Benutzer sie ausprobieren können.)
randomra
Diese Lösung macht meinen Kopf weh:')
Nic Hartley
@ QPaysTaxes Ich nehme das als Kompliment.
FUZxxl
@FUZxxl Es ist. Es ist auch ein Wortspiel, das auf einer Folge von Zeichen basiert, die in Ihrer Antwort erscheinen.
Nic Hartley
15

C 150 Bytes

t;f(char*c){char l=strlen(c)+1,o[l*l],*A=o,m=0;for(t=1;t<l*l;t++)o[t-1]=t%l?32:10;for(t=-1;*c;c++)A++[l*(*c-41?++t>m?m=t:t:t--)]=*c;A[m*l]=0;puts(o);}

Das war ein verrückter Spaß beim Golfspielen. Ich bin immer noch nicht davon überzeugt, dass ich damit fertig bin.

Wir definieren eine einzelne Funktion, fdie den String als Ein- und Ausgang für stdout verwendet.

Lassen Sie uns den Code Zeile für Zeile durchgehen:

/* t will represent the current depth of a parentheses. It must be an int. */
t;
f(char*c){
    //Our variables:
    char l=strlen(c)+1,    //The length of each row of output, including newlines
         o[l*l],           //The output string. It's way larger than it needs to be.
         *A=o,             //We need another pointer to keep track of things.
         m=0;              //The maximum depth recorded thus far.

    for(t=1;t<l*l;t++)     //For each character in our output...
        o[t-1]=t%l?32:10;  //If it's at the end of a line, make it '\n'. Else, ' '.
    for(t=-1;*c;c++)       //While we have an input string...
        //Perhaps a personal record for ugliest warning-less line...
        A++[l*(*c-41?++t>m?m=t:t:t--)]=*c;
    /* 
        A breakdown:
        A++        --> Go to the next *column* of output, after writing. 
                   --> There will only ever be one parentheses per output column.
        [l*(...)]  --> A[l*X] is the character in the current column at depth X.
        (*c-41?    --> If the character is a '('...    
        ++t>m?     --> Increment t *before* we write it. If this is a new highest depth
        m=t:       --> Set m to t, and set the whole expression to t.
        t:         --> If it's not a new highest depth, don't set m.
        t--)       --> If the character was a ')', decrement t *after* we write it.
        =*c        --> Write our output character to whatever the input read.
    */    

    A[m*l]=0; //The last character of the maximum-depth line should be null terminated.
    puts(o);  //Output!
}

Ich werde alle Ihre Fragen beantworten!

Probieren Sie ein Testprogramm online aus !

BrainSteel
quelle
Ich möchte daran erinnern, dass "char l = strlen (c) +1, o [l * l]" nicht gültig ist, weil Sie ein Array mit variabler Größe nicht so definieren können, aber es ist 15 Jahre her, seit ich irgendetwas ausprobiert habe diese Art in C.
Sparr
@Sparr Mein Compiler gibt nicht einmal eine Warnung aus. Ich glaube, dies war "offiziell" Standard in C99. Ich werde versuchen, eine Referenz dafür zu finden.
BrainSteel 20.04.15
1
@Sparr Hier ist eine Referenz.
BrainSteel 20.04.15
Vielen Dank. Es sieht so aus, als ob sich die Dinge in dieser Hinsicht vor 15 (ein paar oder zwei) Jahren geändert haben :)
Sparr
1
@CoolGuy Es würde, aber bei nachfolgenden Aufrufen von f, mnicht auf 0 zurückgesetzt. Dies gilt als "Brechen Ihrer Umgebung", hier verboten .
BrainSteel,
15

Retina + Bash, 27 Bytes (14 + 10 + 3 = 27)

Dies nutzt ANSI-Escapes:

\(
(\e[B
\)
\e[A)

Entspricht sed -e "s/(/(\\\e[B/g;s/)/\\\e[A)/g". Der \e[BEscape-Code bedeutet, dass der Cursor eine Zeile nach unten und der \e[ACursor eine Zeile nach oben bewegt wird. Bei dieser Lösung werden diese Codes einfach nach und vor dem Anfang und dem Ende jedes geschachtelten Klammerpaars eingefügt. Die Eingabe erfolgt über STDIN.

Sie müssen es als aufrufen printf $(Retina ...), um die Ausgabe korrekt zu sehen.

Ausgabe

(((())))
(\e[B(\e[B(\e[B(\e[B\e[A)\e[A)\e[A)\e[A)
^C
amans:~ a$ printf "(\e[B(\e[B(\e[B(\e[B\e[A)\e[A)\e[A)\e[A)"
(      )amans:~ a$ 
 (    )
  (  )
   ()

((()())()(()(())()))
(\e[B(\e[B(\e[B\e[A)(\e[B\e[A)\e[A)(\e[B\e[A)(\e[B(\e[B\e[A)(\e[B(\e[B\e[A)\e[A)(\e[B\e[A)\e[A)\e[A)
^C
amans:~ a$ printf "(\e[B(\e[B(\e[B\e[A)(\e[B\e[A)\e[A)(\e[B\e[A)(\e[B(\e[B\e[A)(\e[B(\e[B\e[A)\e[A)(\e[B\e[A)\e[A)\e[A)"
(                  )amans:~ a$ 
 (    )()(        )
  ()()    ()(  )()
             ()
user22723
quelle
1
Na ja, nicht schlecht! Wenn Sie auf ein bestimmtes Terminal zeigen könnten, das nicht benötigt wird printf, wäre das großartig. Ansonsten halte ich es nur für fair, die Byteanzahl | printfzu erhöhen.
Martin Ender
@ Martinbüttner Es soll printf $()oder sein printf $(Retina ).
Jimmy23013
1
Was ist das für ein Retina-Ding?
FUZxxl
2
@FUZxxl Es ist meine eigene, auf Regex basierende Programmiersprache. Siehe GitHub .
Martin Ender
2
Warum \eplus printf? Sie können die Steuerzeichen einfach in das Ersetzungsmuster einfügen.
Dennis
15

TI-BASIC, 69 60 56 55 Bytes

Dies ist für die TI-83 + / 84 + -Rechnerfamilie, obwohl sie auf einer 84+ C Silver Edition geschrieben wurde.

Das Programm wird bei Berechnung als größer angezeigt, da Mehrwertsteuer und Größenangaben enthalten sind. Außerdem gibt es hier mehr als 56 Zeichen. Der Grund dafür ist, dass alle Befehle, die mehr als ein Zeichen enthalten, auf Tokens mit einer Größe von ein oder zwei Bytes komprimiert werden.

Input Str1
1→B
For(A,1,length(Str1
sub(Str1,A,1→Str2
Ans="(
Output(B+Ans,A,Str2
B-1+2Ans→B
End

Dank thomas-kwa ein weiteres byte abgeschnitten ! (Auch von ihm war der Sprung von 60 auf 56.)

MI Wright
quelle
4
Ahhh, meine erste Programmiersprache. Danke für die Nostalgie, haha.
Alex Pritchard
1
Das Programmieren von TI für den Mathematikunterricht an der Highschool ist weiterhin hilfreich, da Formeln eingebaut sind, die bei Tests und Aufgaben für Sie berechnet werden.
Elias Benevedes
1
Wenn Sie Dinge verschieben, können Sie den cos(piAnsTrick verwenden, um ein weiteres Byte zu speichern.
Lirtosiast
9

Python 2, 115 Bytes

def f(L,n=0,O=()):
 for c in L:n-=c>"(";O+=" "*n+c,;n+=c<")"
 for r in map(None,*O):print"".join(c or" "for c in r)

Call like f("((()())()(()(())()))"), und die Ausgabe erfolgt nach STDOUT.

Erläuterung

Wir beginnen mit n = 0. Für jedes Zeichen in der Eingabezeile:

  • Wenn das Zeichen ist (, werden nLeerzeichen vorangestellt und dann inkrementiertn
  • Wenn das Zeichen ist ), dekrementieren wir Leerzeichen nund stellen sie vorann

Das Ergebnis wird dann gezippt und gedruckt. Beachten Sie, dass Pythons zipReißverschlüsse der Länge des kürzesten Elements entsprechen, z

>>> zip([1, 2], [3, 4], [5, 6, 7])
[(1, 3, 5), (2, 4, 6)]

Normalerweise würde man itertools.zip_longest( izip_longest) verwenden, wenn man zipauf die Länge des längsten Elements auffüllen möchte .

>>> import itertools
>>> list(itertools.izip_longest([1, 2], [3, 4], [5, 6, 7]))
[(1, 3, 5), (2, 4, 6), (None, None, 7)]

In Python 2 kann dieses Verhalten jedoch durch Zuordnen simuliert werden None:

>>> map(None, [1, 2], [3, 4], [5, 6, 7])
[(1, 3, 5), (2, 4, 6), (None, None, 7)]

Python 3, 115 Bytes

L,d,*O=input(),0
for i,c in enumerate(L):b=c>"(";O+="",;O[d-b]=O[d-b].ljust(i)+c;d-=b*2-1
for l in O:l and print(l)

Kein Reißverschluss, nur passendes Auffüllen ljust. Dieser scheint ein gewisses Golfpotential zu haben.

Sp3000
quelle
8

R, 151 127 Zeichen

S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}

Mit Einrückungen und Zeilenumbrüchen:

S=strsplit(scan(,""),"")[[1]]
C=cumsum
D=c(C(S=="("),0)-c(0,C(S==")"))
for(j in 1:max(D)){
    X=S
    X[D!=j]=' '
    cat(X,sep='',fill=T)
    }

Verwendungszweck:

> S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}
1: ()(())((()))(())()
2: 
Read 1 item
()(  )(    )(  )()
   ()  (  )  ()   
        ()        
> S=strsplit(scan(,""),"")[[1]];C=cumsum;D=c(C(S=="("),0)-c(0,C(S==")"));for(j in 1:max(D)){X=S;X[D!=j]=' ';cat(X,sep='',fill=T)}
1: ((()())()(()(())()))
2: 
Read 1 item
(                  )
 (    )()(        ) 
  ()()    ()(  )()  
             ()     

Es liest die Zeichenkette als stdin, teilt sie als Vektor aus einzelnen Zeichen auf, berechnet die kumulative Summe von (und )subtrahiert die erstere mit der letzteren (mit einer Verzögerung), wodurch das "Niveau" jeder Klammer berechnet wird. Anschließend werden für jede Ebene entweder die entsprechenden Klammern oder ein Leerzeichen auf stdout gedruckt.

Vielen Dank an @MickyT, der mir dabei geholfen hat, es erheblich zu verkürzen!

Plannapus
quelle
2
+1 Schöne und elegante Lösung. Sie können 6 durch Ersetzen sparen for(i in n)cat(ifelse(D[i]-j," ",S[i]));cat("\n")mit X=S;X[which(D!=j)]=' ';cat(X,sep='',fill=T). Dann nist das nicht wirklich erforderlich, aber Sie müssten den Cumsum-Teil ein bisschen ändern. D=c(C(S=="("),0)-c(0,C(S==")"));
Herabsetzung
@ MickyT wow danke! daran habe ich nicht gedacht. whichist hier allerdings nicht wirklich notwendig (da D!=jes sich bereits um einen Vektor von Booleschen Elementen handelt, die eine Indizierung ermöglichen). Ich wusste kein Argument filldafür cat, das ist ein toller Trick! Vielen Dank, dass ich es um erstaunliche 24 Zeichen verkürzen musste !!
Plannapus
8

C, 58 53 52 51 49 Bytes

Verwendet ANSI-Escape-Sequenzen, um die Cursorposition zu verschieben.

f(char*s){while(*s)printf(*s++&1?"\e[A)":"(\v");}

Wenn Sie gcc oder einen anderen unterstützten Compiler nicht verwenden \e, können Sie ihn durch \x1Binsgesamt 2 zusätzliche Bytes ersetzen . \e[ABewegt den Cursor eine Zeile nach oben und \e[Bden Cursor eine Zeile nach unten. Es ist nicht erforderlich, \e[Beine Zeile nach unten zu verschieben, da es zwei Bytes kürzer ist, um das vertikale ASCII-Tabulatorzeichen 0xBoder zu verwenden \v.

Von der Frage wird angenommen, dass die Eingabezeichenfolge nur aus (ausgeglichenen) Klammern besteht. Daher reicht es aus, die Parität des Zeichens mit zu überprüfen &1, um zwischen (und zu unterscheiden ).

CL-
quelle
7

Pip, 53 Bytes

Pip ist eine Code-Golf-Sprache meiner Erfindung. Die erste Version wurde am Samstag veröffentlicht, also kann ich es offiziell ausprobieren! Die folgende Lösung ist in Bezug auf Golfsprachen nicht besonders wettbewerbsfähig, aber das liegt zum Teil daran, dass ich Dinge wie zip und max noch nicht implementiert habe.

z:{aEQ'(?++v--v+1}MaW(o:{z@++v=i?as}Ma)RMs{Pov:-1++i}

Erwartet die Zeichenfolge in Klammern als Befehlszeilenargument.

"Ungolfed" Version:

z:{
   a EQ '( ?
    ++v
    --v+1
  } M a
W (o:{
      z @ ++v = i ?
       a
       s
     } M a
  ) RM s
{
 P o
 v:-1
 ++i
}

Erläuterung:

Im Gegensatz zu den meisten Golfsprachen ist Pip bei Infix-Operatoren unerlässlich, sodass die Syntax etwas näher an C und seinen Derivaten liegt. Außerdem werden Ideen aus der funktionalen und Array-basierten Programmierung übernommen. Weitere Dokumentation finden Sie im Repository.

Das Programm generiert zunächst eine Liste von Tiefen (in der es gespeichert ist z), indem eine Funktion der Eingabezeichenfolge zugeordnet wird a. Die globale Variable vverfolgt die aktuelle Ebene. (Variablen a-gin Pip sind funktionslokale Variablen, aber h-zglobal. vIst praktisch, weil sie auf -1 vorinitialisiert sind.)

Als nächstes verwenden wir eine WHile-Schleife, um jede Zeile zu erzeugen und zu drucken, bis die erzeugte Zeile aus allen Leerzeichen bestehen würde. vwird jetzt für Spalten und ifür Zeilen verwendet. Die {z@++v=i?as}Funktion, die wiederholt der ursprünglichen Eingabezeichenfolge zugeordnet wird, prüft, ob die aktuelle Zeile imit der Zeile übereinstimmt, in der sich die aktuelle Klammer befinden soll (wie in der zListe gespeichert ). Verwenden Sie in diesem Fall die Klammer ( a). Wenn nicht, verwenden Sie s(für Leerzeichen vorinitialisiert). Das Endergebnis ist, dass bei jeder Iteration oeine Liste von Zeichen zugewiesen wird, die der nächsten Zeile der Ausgabe entspricht.

Um zu testen, ob wir die Schleife fortsetzen sollen, prüfen wir, ob obei allen Leerzeichen RM'd' leer ist. Wenn nicht, drucken Sie es aus (das verkettet standardmäßig alles wie in CJam), setzen Sie die Spaltennummer auf -1 zurück und erhöhen Sie die Zeilennummer.

(Witzige Tatsache: Ich hatte zuerst eine 51-Byte-Lösung ... die nicht funktionierte, weil sie einen Fehler im Interpreter aufwies.)

DLosc
quelle
7

Pyth, 31 Bytes

VzJs.e?YqN-/<zk\(/<zhk\)dzI-JdJ

Probieren Sie es online aus.

-/<zk\(/<zhk\): Findet die passende Stufe für die aktuelle Zeichenposition.

?YqN-/<zk\(/<zhk\)d: Ein Leerzeichen, wenn die entsprechende Ebene nicht der aktuellen Ebene entspricht, andernfalls das aktuelle Zeichen.

Js.e?YqN-/<zk\(/<zhk\)dz: Generiere den String und speichere ihn in J.

I-JdJ: Wenn Jnicht alle Leerzeichen vorhanden sind, drucken Sie es aus.

Vz: Loop- zZeiten.

isaacg
quelle
6

GNU Bash + coreutils + indent, 135

eval paste "`tr '()' {}|indent -nut -i1 -nbap|sed 's/.*/<(fold -1<<<"&")/'|tr '
' \ `"|expand -t2|sed 'y/{}/()/;s/\(.\) /\1/g;s/ \+$//'

Ein- / Ausgabe über STDIN / STDOUT:

$ ./telescopic.sh <<< "(()(()())()((())))(())"
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
$ 

indenterledigt das meiste schwere Heben, muss aber mit Zahnspangen anstelle von Parens arbeiten. Der Rest ist die Änderung dieser Antwort , um die Ausgabe von zu transponieren indent.

Digitales Trauma
quelle
5

Python 2, 92

def f(s,i=0,z=''):
 for x in s:b=x>'(';z+=[' ',x][i==b];i-=2*b-1
 if'('in z:print z;f(s,i-1)

Druckt zeilenweise. Durchläuft für eine bestimmte Zeilennummer i(eigentlich deren Negation) die Eingabezeichenfolge sund erstellt eine neue Zeichenfolge z, die nur die Zeichen der sTiefe enthält i. Dies erfolgt durch Inkrementieren oder Dekrementieren i, um die aktuelle Tiefe zu verfolgen, und Hinzufügen der aktuellen Zeichen, wenn dies für den Parentyp angepasst iist 0, und andernfalls Hinzufügen eines Leerzeichens.

Anschließend wird gedruckt und mit der nächsten iZeile fortgefahren, es sei denn, in der aktuellen Zeile waren alle Leerzeichen. Da die Parens ausgeglichen sind, ist der iAfter-Loop derselbe wie zu Beginn.

Python 3 wäre bis auf ein Zeichen für dasselbe print(z).

xnor
quelle
5

Betrug :( Retina + TeX, N Bytes Betrug :(

Dies funktioniert nur, wenn Sie die Ausgabe mit MathJax oder einem anderen TeX rendern (?), Das derzeit für diese SE deaktiviert ist :(

\(
({
\)
})
\{\(
_{(

Jede Zeile sollte sich in einer anderen Datei befinden, aber Sie können sie mit Retina -e "\(" -e "({" -e "\)" -e "})" -e "\{\(" -e "_{("(oder dem entsprechenden sed-Befehl sed -e "s/(/({/g;s/)/})/g;s/{(/_{(/g") testen . Die Eingabe erfolgt über STDIN.

Dies funktioniert, indem der Inhalt jedes Klammerpaares in geschweifte Klammern eingeschlossen und anschließend alle darin enthaltenen Elemente subskribiert werden.

Ausgabe

(((())))
(_{(_{(_{({})})})})

()(())((()))(())()
({})(_{({})})(_{(_{({})})})(_{({})})({})

((()())()(()(())()))
(_{(_{({})({})})({})(_{({})(_{({})})({})})})

TeX-Ausgabe

user22723
quelle
1
Ich fühle mich geschmeichelt, dass Sie Retina verwendet haben, und dies ist eine nette Art, über den Tellerrand zu schauen, aber so soll die Ausgabe nicht aussehen. ;) Dies verstößt insbesondere gegen die alternative Formulierung "Eine andere Sichtweise ist, dass die Klammern in der Tiefe n auf die Linie n verschoben werden, während ihre horizontale Position beibehalten wird." Ich wäre jedoch sehr beeindruckt von einer reinen, regelkonformen Retina-Lösung und würde möglicherweise ein Kopfgeld dafür ausgeben. ;)
Martin Ender
In total the lines must not be longer than twice the length of the input string. Wenn Sie Zeile 2 auf (\,{und Zeile 4 auf }\,)
ändern
Nun, ich habe es geschafft, eine regelkonforme Lösung zu finden
:)
1
Gute Arbeit. Das heißt, Sie können die betrügerische Antwort jetzt löschen. ;)
Martin Ender
5

Java, 232 226 224 222 Bytes

Golf Version:

int i,j,k,l,m,a[];void f(String s){a=new int[s.length()];j=a.length;for(k=0;k<j;){a[k]=s.charAt(k++)<41?i++:--i;m=m<i?i:m;}for(k=0;k<m;k++)for(l=0;l<j;)System.out.print(k==a[l++]?i++%2<1?'(':l==j?")\n":')':l==j?'\n':' ');}

Lange Version:

int i, j, k, l, m, a[];
void f(String s) {
    a = new int[s.length()];
    j = a.length;
    for (k = 0; k < j;) {
        a[k] = s.charAt(k++) < 41 ? i++ : --i;
        m = m < i ? i : m;
    }
    for (k = 0; k < m; k++)
        for (l = 0; l < j;)
            System.out.print(k == a[l++] ? (i++ % 2 < 1 ? '(' : (l == j ? ")\n" : ')')) : (l == j ? '\n':' '));
}

Die Eingabezeichenfolge wird zuerst analysiert und sucht nach "(" und ")", um einen Zähler zu addieren / subtrahieren und seinen Wert zu speichern, um zu bestimmen, wie weit die Klammern in einem Array reichen sollen, und um zu verfolgen, wie tief der tiefste Wert ist. Dann wird das Array analysiert; Die Klammern mit niedrigeren Werten werden zuerst gedruckt und werden zeilenweise weiter gedruckt, bis das Maximum erreicht ist.

Ich werde wahrscheinlich später weitere Möglichkeiten finden, um Golf zu spielen.

TNT
quelle
5

Javascript / ES6, 97 Zeichen

f=s=>{for(n in s){m=o=d='';for(c of s)o+=n==(c<')'?d++:--d)?c:' ',m=m<d?d:m;n<m&&console.log(o)}}

Verwendungszweck

f("(()(()())()((())))(())")

Erläuterung

fn=str=>{                          // accepts string of parenthesis
  for(line in str){                // repeat process n times where n = str.length
    max=output=depth='';           // max: max depth, output: what to print, depth: current depth
    for(char of str)               // iterate over chars of str
      output+=
        line==(char<')'?depth++:--depth)? // update depth, if line is equal to current depth
        char:' ',                  // append either '(', ')', or ' '
        max=max<depth?depth:max;   // update max depth
    line<max&&console.log(output)  // print if current line is less than max depth
  }
}
Dendrobium
quelle
Stattdessen n<m?console.log(o):0können Sie verwenden, n<m&&console.log(o)was 1 Byte spart.
Ismael Miguel
4

CJam, 43 41 36 Bytes

Ich denke, nicht zu golfen, aber hier ist mein erster Versuch:

l:L,{)L<)_')=@~zS*\+}%_$0=,f{Se]}zN*

Wie es funktioniert

Ich benutze die sehr praktische Tatsache, dass )und (in CJam Inkrementieren bzw. Dekrementieren bedeuten. Daher bewerte ich einfach die Klammern, um die Tiefe zu erhalten.

l:L,{)L<)_')=@~zS*\+}%_$0=,f{Se]}zN*
l:L,{                    }%                "Store input line in L and iterate over [0,L)";
     )L<                                   "substr(L, 0, iterator + 1)";
        )                                  "Slice off the last character to stack";
         _')=                              "Put 0 on stack if the sliced character is (,
                                            else 1 if sliced character is )";
             @~                            "bring forth the remaining
                                            brackets after slicing and evaluate them";
               zS*                         "Stack has negative depth number, take absolute
                                            value and get that many spaces";
                  \+                       "Prepend to the sliced character";
                      _$0=,                "Get the maximum depth of brackets";
                           f{Se]}          "Pad enough spaces after each string to match
                                            the length of each part";
                                 zN*       "Transpose and join with new lines";

Probieren Sie es hier online aus

Optimierer
quelle
4

Oktave, 85 Zeichen

function r=p(s)i=j=0;for b=s k=b==40;k&&++j;t(j,++i)=9-k;k||--j;r=char(t+32);end;end

Es ist eine Optimierung des naiven Ansatzes, was für Matlab und Octave eigentlich ganz selbstverständlich ist:

function r=p(s)
i=j=1;
for b=s
 if b=='(' t(++j,i++)='(' else t(j--,i++)=')' end; end; t(~t)=' '; r=char(t);
end;

Die Tabelle ist t möglicherweise noch nicht vorhanden, und wir können sie jedem Element sofort zuweisen. Sie wird in die kleinste Dimension umgeformt, die für die Existenz dieses Elements erforderlich ist, was sehr praktisch ist.

pawel.boczarski
quelle
4

Perl, 91 89 88 84 80 79 Bytes

$t=<>;{$_=$t;s/\((?{$l++})|.(?{--$l})/$^R==$c?$&:$"/ge;print,++$c,redo if/\S/}
  • $ t ist die Eingabezeichenfolge.
  • $ c ist die Tiefe, die in der aktuellen Zeile gedruckt werden soll.
  • $ l ist die Tiefe, in der wir uns befinden, nachdem wir einem Elternteil begegnet sind.
  • $ l wird in regulären eingebetteten Codeblöcken aktualisiert .
  • $ ^ R ist das Ergebnis des letzten Codeblocks.
Helios
quelle
4

Haskell, 154 Bytes

f h('(':s)=h:f(h+1)s;f h(')':s)=(h-1):f(h-1)s;f _ _=[]
main=interact$ \s->unlines[[if i==h then c else ' '|(c,i)<-zip s l]|let l=f 0 s,h<-[0..maximum l]]

gleiche Idee wie die andere Haskell-Lösung, jedoch etwas kürzer. - Verwendungszweck:

echo  '(((())())(()))' | runghc Golf.hs
d8d0d65b3f7cf42
quelle
3

J, 46

Nicht so gut wie die anderen "Golfsprachen", aber zu meiner Verteidigung: J ist schrecklich mit Streichern.

[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~

Nimmt den String als Eingabe für eine Funktion. Es gibt wahrscheinlich auch einen besseren Weg, dies in J zu tun.

Verwendungszweck:

   f=:[:|:(((,~(' '#~]))"0)(0,2%~[:+/\2+/\1-'(('i.]))~
   f '(()(()())()((())))(())'
(                )(  )
 ()(    )()(    )  () 
    ()()    (  )      
             ()       
ɐɔıɐɔuʇǝɥʇs
quelle
Eine andere Möglichkeit, dies zu tun, finden Sie in meiner Antwort in J.
FUZxxl,
3
Persönlich denke ich, dass J perfekt für Streicher geeignet ist. Sie müssen nur mit Arrays denken.
FUZxxl
3

Ruby, 119, 115, 114

->s{r=[""]*s.size
d=0
s.chars.map{|l|r.map!{|s|s+" "}
b=l>"("?1:0
d-=b
r[d][-1]=l
d+=1-b}.max.times{|i|puts r[i]}}

Erläuterung:

->s{r=[""]*s.size  # Take an array of strings big enough
d=0                # This will contain the current depth
s.chars.map{|l|r.map!{|s|s+" "}  # Add a new space to every array
b=l>"("?1:0       # Inc/Dec value of the depth
d-=b               # Decrement depth if we are at a closing paren
r[d][-1]=l         # Set the corresponding space to the actual open/close paren
d+=1-b             # Increment the depth if we are at a opening paren
}.max.times{|i|puts r[i]}}  # Print only the lines up to the max depth
rorlork
quelle
3

Java, 233 214 Bytes

void f(String s){int p,x,d,l=s.length();char c,m[]=new char[l*l];java.util.Arrays.fill(m,' ');p=x=0;while(x<l){d=(c=s.charAt(x))==40?p++:--p;m[d*l+x++]=c;}for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);}

Eingerückt:

void f(String s){
    int p, x, d, l = s.length();
    char c, m[] = new char[l * l];
    java.util.Arrays.fill(m, ' ');
    p = x = 0;
    while (x < l){
        d = (c = s.charAt(x)) == 40
                ? p++
                : --p;
        m[d * l + x++] = c;
    }
    for (x = 0; x < l * l; x++)
        System.out.print((x % l == 0 ? "\n" : "") + m[x]);
}

Ich denke, die letzte Schleife könnte verkürzt werden, aber ich überlasse sie dem Leser als Übung. ;-)


Alt, 233 Bytes Antwort:

void f(String s){int y=s.length(),x=0;char[][]m=new char[y][y];for(char[]q:m)java.util.Arrays.fill(q,' ');y=0;for(char c:s.toCharArray())if(c=='(')m[y++][x++]=c;else m[--y][x++]=c;for(char[]q:m)System.out.println(String.valueOf(q));}

Eingerückt:

static void f(String s) {
    int y = s.length(), x = 0;
    char[][] m = new char[y][y];
    for(char[] q : m)
        java.util.Arrays.fill(q, ' ');
    y = 0;
    for(char c : s.toCharArray())
        if(c == '(')
            m[y++][x++] = c;
        else
            m[--y][x++] = c;
    for(char[] q : m)
        System.out.println(String.valueOf(q));
}
ArturoTena
quelle
Ich weiß, dass es mehr als ein Jahr her ist, aber "Ich denke, die letzte Schleife könnte verkürzt werden, aber ich werde es dem Leser als Übung überlassen. ;-)"; Du hast in der Tat recht. Sie kann für -1 Byte von for(x=0;x<l*l;x++)System.out.print((x%l==0?"\n":"")+m[x]);auf geändert werden for(x=0;x<l*l;)System.out.print((x%l==0?"\n":"")+m[x++]);. Sie können auch 2 weitere Bytes einsparen, indem Sie diese entfernen p=x=0und int p=0,x=0,stattdessen bei der Initialisierung der Felder verwenden. Insgesamt werden es 211 Bytes .
Kevin Cruijssen
3

C # 195 Bytes

Versuchen Sie es zuerst mit Golf - schreien Sie, wenn ich etwas falsch gemacht habe.

Alternative C # -Version mit SetCursorPosition und Verwendung der Eingabe von links nach rechts als Befehlszeilenargument.

using System;class P{static void Main(string[] a){Action<int,int>p=Console.SetCursorPosition;int r=0,c=0;foreach(var x in a[0]){r+=x==')'?-1:0;p(c,r);Console.Write(x);r+=x=='('?1:0;p(c,r);c++;}}}

Ich dachte, es würde Spaß machen, die Schreibposition basierend auf dem Open / Close-Paren und nicht den vollständigen Zeilen anzupassen. Close Paren verschiebt die Position vor dem Schreiben nach oben. open paren verschiebt es nach dem Schreiben nach unten. Durch die Aktion SetCursorPosition werden fünf Bytes gespart. Das Bewegen des Cursors in die nächste Zeile nach der Ausgabe würde einiges mehr kosten.

using System;
class P
{
    static void Main(string[] a)
    {
        Action<int, int> p = Console.SetCursorPosition;
        int r = 0, c = 0;
        foreach (var x in a[0])
        {            
            r += x == ')' ? -1 : 0;
            p(c, r);
            Console.Write(x);
            r += x == '(' ? 1 : 0;
            p(c, r);
            c++;
        }
    }
}
Jeremy Murray
quelle
3

Batch, 356 335 Bytes

Ich weiß, dass es für diese Herausforderung bereits eine Batch-Lösung gibt, aber diese ist deutlich umfangreicher und scheint einen anderen Ansatz zu verfolgen. Am wichtigsten ist, dass die andere Batch-Lösung mindestens einen Powershell-Befehl enthält. Diese Lösung tut es nicht.

@echo off
setlocal enabledelayedexpansion
set p=%1
set p=%p:(="(",%
set p=%p:)=")",%
set c=0
for %%a in (%p%)do (if ")"==%%a set/ac-=1
set d=!d!,!c!%%~a
if "("==%%a set/ac+=1&if !c! GTR !m! set m=!c!)
set/am-=1
for /l %%a in (0,1,!m!)do (for %%b in (!d!)do (set t=%%b
if "%%a"=="!t:~0,-1!" (cd|set/p=!t:~-1!)else (cd|set/p=. ))
echo.)

In U+0008der vorletzten Zeile nach dem Punkt (Zeile 12, Spalte 57) befindet sich ein Backspace-Zeichen ( ). Dies ist im hier veröffentlichten Code nicht sichtbar, ist jedoch in der Byteanzahl enthalten.

Ankh-Morpork
quelle
Jemand anderes, der tatsächlich eine Antwort in Batch - Nice one +1 sendet.
Unclemeat
3

Batch, 424 Bytes

@echo off
setLocal enableDelayedExpansion
set s=%1
set a=1
:c
if defined s (set/ac+=1
set "z="
if "%s:~0,1%"=="(" (set "1=(")else (set/aa-=1
set "1=)")
for %%a in (!a!)do for /f usebackq %%b in (`powershell "'!l%%a!'".Length`)do (set/ay=!c!-%%b
for /l %%a in (1,1,!y!)do set z= !z!
set "l%%a=!l%%a!!z!!1!")
if "%s:~0,1%"=="(" set/aa+=1
if !a! GTR !l! set/al=!a!-1
set "s=%s:~1%"
goto c)
for /l %%a in (1,1,!l!)do echo !l%%a!

Nicht golfen:

@echo off
setLocal enableDelayedExpansion

set s=%1
set a=1
set c=0
set l=0

:c
if defined s (
    set /a c+=1
    set "z="
    if "%s:~0,1%"=="(" (
        set "1=("
    ) else (
        set /a a-=1
        set "1=)"
    )
    for %%a in (!a!) do for /f usebackq %%b in (`powershell "'!l%%a!'".Length`) do (
        set /a y=!c!-%%b
        for /l %%a in (1,1,!y!) do set z= !z!
        set "l%%a=!l%%a!!z!!1!"
    )
    if "%s:~0,1%"=="(" set /a a+=1
    if !a! GTR !l! set /a l=!a!-1
    set "s=%s:~1%"
    goto c
)

for /l %%a in (1,1,!l!) do echo !l%%a!

Beispiel:

h:\>par.bat (((())())(()))
 (            )
  (      )(  )
   (  )()  ()
    ()
unclemeat
quelle
3

C 118 117 Bytes

Eine andere Antwort in C, aber meine ist kürzer.

c;d;main(m,v)int**v;{while(d++<m){char*p=v[1];while(*p)c+=*p==40,putchar(c-d?*p:32),m=c>m?c:m,c-=*p++==41;puts("");}}

Ungolfed-Version:

c; /* current depth */
d; /* depth to print in current row */
main(m,v)int**v;{
    while(d++<m) {
        char*p=v[1];
        while(*p){
            c+=*p==40;           /* 40 = '(' */
            putchar(c-d?*p:32); /* 32 = ' ' (space) */
            m=c>m?c:m;           /* search maximum depth */
            c-=*p++==41;         /* 41 = ')' */
        }
        puts("");
    }
}

Und es funktioniert!

% ./telescope '()(())((()))(())()'
()(  )(    )(  )()
   ()  (  )  ()
        ()
% ./telescope '((()())()(()(())()))'
(                  )
 (    )()(        )
  ()()    ()(  )()
             ()
MarcDefiant
quelle
1
Eine recht elegante Lösung ist jedoch putchar(c-d?32:*p)ein Zeichen kürzer als putchar(c==d?*p:32).
pawel.boczarski
2

Haskell, 227 Bytes

n _ []=[]
n h ('(':r)=('(',h):n(h+1)r
n d (')':r)=let h=d-1 in(')',h):n h r
m n []=n
m n ((_,h):r)=m(max h n)r
p s=let v=n 0 s;h=m 0 v;in map(\d->map(\(b,l)->if l==d then b else ' ')v)[0..h]
main=fmap p getLine>>=mapM_ putStrLn
Jeremy List
quelle
1
Sie können mit Operatoren einige Leerzeichen speichern: zB n#[]statt m n [].
Franky
2

Perl, 76 Bytes

$a[/\(/?$l++:--$l][$i++]=$_ for split//,<>;print map{$_||' '}@$_,"\n"for@a

Nein use stricthier :)

Alexander-Brett
quelle
2

Lex, 94 Bytes

Hängt von den Linux-Konsolencodes ab. Mit gcc können Sie vier Bytes ausschneiden, indem Sie beide Instanzen von \33durch ein tatsächliches Escape-Zeichen ersetzen .

%%
 int p[2]={0};
\( printf("(\33D");++p[!*p];
\) printf("\33M)");--*p;
\n while(p[1]--)ECHO;

Kompilieren und ausführen:

$ flex -o telescopic.c telescopic.l
$ gcc -o telecopic telescopic.c -lfl
$ ./telescopic
(()(()())()((())))(())
(                )(  )
 ()(    )()(    )  ()
    ()()    (  )
             ()
--- type ctrl-D ---
rici
quelle