Topografische Zeichenfolgen

23

Hier sind einige Beispieleingaben, damit ich erklären kann, wo das Problem liegt:

((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))

Stellen Sie sich diese Textzeile als topografische Karte einiger Berge vor. Jede Klammer gibt eine Höheneinheit an.

Wenn wir dies von der Seite "sehen", so dass wir die Berge vertikal sehen, werden wir sehen:

          4 5                cherries    woohoo  
  1 2  3       moo       lik          e
                      i

Bei einer dieser topografischen Karten geben Sie die Karte aus, jedoch in einem vertikalen Maßstab, wie in der obigen Ausgabe. Trennen Sie die verschiedenen Elemente in der Karte mit der Anzahl der Zeichen zum nächsten Element. Beispielsweise enthält die Ausgabe 4 Leerzeichen zwischen moound i. Ebenso enthält die Eingabe zwischen moound 4 Zeichen i.

Der Code, der dies mit der geringsten Anzahl von Zeichen tut, gewinnt.

beary605
quelle
Kann man davon ausgehen, dass die Höhen immer positiv sein werden? Beispielsweise sollte die Eingabe ((1 2))))))))))3ungültig sein, wenn negative Höhen verboten sind.
Cristian Lupascu
@ w0lf: yep, die Klammern stimmen immer überein.
beary605

Antworten:

10

J, 87 79 72 70 67 57 56 Zeichen

'( ) 'charsub|.|:(+/\@('('&=-')'&=)(],~' '$~[)"0])1!:1[1

Übernimmt Eingaben von der Tastatur. Beispiel:

   '( ) 'charsub|.|:(+/\@('('&=-')'&=)(],~' '$~[)"0])1!:1[1
((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))
          4 5                cherries    woohoo
  1 2  3       moo       lik          e
                      i

Erläuterung:

Diese Erklärung basiert auf der ersten Version meines Programms:

|.|:('( ) 'charsub x)((' '$~{.@]),[{~{:@])"1(('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1

x=.1!:1[1Eingaben von der Tastatur nehmen und xfür später speichern

(('('&([:+/=)-')'&([:+/=))\,.i.@#)Erstellt eine Liste aller Indices in der Zeichenfolge ( i.@#) und setzt ,.sie zusammen mit dem Ergebnis des (('('&([:+/=)-')'&([:+/=))\Verbs zusammen ( ) .

(('('&([:+/=)-')'&([:+/=))\Dieses Verb wird auf alle Präfixe der Zeichenfolge angewendet (so bei Eingabe hellowäre es gelten h, he, hel, hell, und hello. Es ist eine Gabel , die die Anzahl der offenen Klammern zählt ('('&([:+/=)und subtrahiert dann die Anzahl der Klammer zu ')'&([:+/=). Das gibt mir die Liste von Indices in die Zeichenfolge und die Ebene, auf der sich das Zeichen an diesem Index in der Ausgabe befinden soll. Bei einfacher Eingabe ergibt sich Folgendes:

   (('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1
(one(two(three)))
1  0
1  1
1  2
1  3
2  4
2  5
2  6
2  7
3  8
3  9
3 10
3 11
3 12
3 13
2 14
1 15
0 16

((' '$~{.@]),[{~{:@])"1Dies ist ein Verb, das die Liste, die ich gerade erstellt habe, und auch die Ausgabe von aufnimmt ('( ) 'charsub x)(wobei nur ein String ersetzt wird, um alle Klammern durch Leerzeichen in zu ersetzen x). Es nimmt das Ende jedes Elements der Liste {:@]und verwendet es als Index in der Zeichenfolge, um das Zeichen abzurufen [{~{:@]. Dann wird ihm ,die Anzahl der Leerzeichen vorangestellt, die durch den Kopf jedes Elements in der Liste angegeben sind (' '$~{.@]). Auf dem vorherigen Beispiel gibt mir das:

   ('( ) 'charsub x)((' '$~{.@]),[{~{:@])"1(('('&([:+/=)-')'&([:+/=))\,.i.@#)x=.1!:1[1
(one(two(three)))

 o
 n
 e

  t
  w
  o

   t
   h
   r
   e
   e

Ich transponiere dann das Array |:und kehre es |.um, um die gewünschte Ausgabe zu erhalten.

Gareth
quelle
6

GolfScript 69

0:§;{.'()'?))3%(.§+:§' ':s*\@s\if\n}%n/.{,}%$)\;:μ;{.,μ\-s*\+}%zip n*

Online Demo hier .

Erläuterung:

0:§;                # declare the variable §, representing the 
                    # current vertical level and initialize it at 0

{                   # iterate for each char in the string:

    .'()'?))3% (    # add on the stack the amount by which
                    # the current vertical level should be 
                    # adjusted:
                    #   * +1 if the character is '('
                    #   * -1 if the character is ')'
                    #   * 0 otherwise

    .§+:§           # adjust the value of §

    ' ':s*          # add as many spaces as § tells us
                    # and save the space in variable s

    \@s\if\         # return current char, if it's printable,
                    # or a space if it's '(' or ')'

    n               # add a newline char

}%

n/                  # split by newline char; now we have 
                    # an array of strings on the stack.
                    # Each string is a vertical line of the
                    # final output.

.{,}%$)\;:μ;        # Iterate through the strings and find the
                    # maximum length

{
    .,μ\-s*\+       # Add spaces at the end to make all the strings 
                    # the same length
}%

zip                 # Transpose the strings

n*                  # Join the transposed strings by newline characters
Cristian Lupascu
quelle
@ Gareth Ja, wir beide tun :)
Cristian Lupascu
Möchtest du eine Erklärung hinzufügen, wie es funktioniert?
Timwi
@ Timwi Ich habe meine Antwort bearbeitet, um eine Erklärung
hinzuzufügen
5

APL (59)

⊖↑{⊃,/T\¨⍨⍵×P=0}¨R∘=¨(⍴T)∘⍴¨⍳⌈/R←1++\P←+/¨1 ¯1∘ר'()'∘=¨T←⍞

Ich bin davon ausgegangen, dass die "Basis" auch verwendbar sein muss. (dh (a(b))c(d)ist gültig). Ist dies nicht erforderlich, können zwei Zeichen gespeichert werden.

Erläuterung:

  • T←⍞: speichere eine Eingabezeile in T
  • '()'∘=¨T: Prüfen Sie für jedes Zeichen in T, ob es sich um eine öffnende oder schließende Klammer handelt. Dies gibt eine Liste von Listen von Booleschen Werten.
  • 1 ¯1∘ר: Multiplizieren Sie das zweite Element in jeder dieser Listen mit -1 (eine öffnende Klammer ist also 1, eine schließende -1 und jedes andere Zeichen ist 0).
  • +/¨: Nimm die Summe jeder inneren Liste. Wir haben jetzt den ∆y-Wert für jedes Zeichen.
  • P←: Geschäft in P.
  • R←1++\P: Nimm eine laufende Summe von P und gib die Höhe für jedes Zeichen an. Fügen Sie jedem Zeichen ein Zeichen hinzu, sodass sich Zeichen außerhalb der Klammern in der ersten Zeile befinden.
  • (⍴T)∘⍴¨⍳⌈/R: Erstellen Sie für jeden möglichen y-Wert eine Liste mit der Länge T, die nur aus diesem Wert besteht. (dh 1111 ..., 2222 .... usw.)
  • R∘=¨: Prüfen Sie für jedes Element in dieser Liste, ob es gleich R ist. (Für jede Ebene haben wir jetzt eine Liste von Nullen und Einsen, die angeben, ob ein Zeichen auf dieser Ebene erscheinen soll oder nicht.)
  • ⍵×P=0: Setzen Sie für jede dieser Listen den Wert auf Null, wenn P an dieser Stelle nicht Null ist. Dadurch werden die Zeichen mit einem Delta-y ungleich Null entfernt, sodass die Klammern entfernt werden.
  • ⊃,/T\¨⍨: Wählen Sie für jede Tiefe aus T die Zeichen aus, die angezeigt werden sollen.
  • ⊖↑: Erstelle eine Matrix und lege sie mit der rechten Seite nach oben.
Marinus
quelle
Welche APL-Implementierung verwenden Sie? Ist es frei?
FUZxxl,
@FUZxxl Ich benutze Dyalog APL, die Windows-Version kann kostenlos heruntergeladen werden.
Marinus
5

Tcl, 50

puts \33\[9A[string map {( \33\[A ) \33\[B} $argv]

Art zu betrügen, aber gut ..

Ich verwende ASCII-Escape-Sequenzen, um die ^[[AZeilendifferenz zu ermitteln. Das bedeutet, dass der Cursor 1 nach oben und der ^[[BCursor 1 nach unten verschoben wird.

Johannes Kuhn
quelle
5

APL, 41 Zeichen / Byte *

{⊖⍉⊃(↑∘''¨-⌿+/¨p∘.=,\⍵),¨⍵/⍨1-2×⍵∊p←'()'}

Getestet auf Dyalog, mit ⎕IO←1und ⎕ML←3Umgebung. Es ist eine Funktion, die die erforderliche Eingabe übernimmt und die Ausgabe zurückgibt. Angesichts der Formulierung der Frage glaube ich, dass sie akzeptabel ist. Falls nicht, hier ist eine Version, die von stdin liest und in stdout schreibt, für 4 Zeichen mehr:

⍞←⊖⍉⊃(↑∘''¨-⌿+/¨'()'∘.=,\a),¨a/⍨1-2×'()'∊⍨a←⍞

Erklärung :

{                                 p←'()'}  p is the string made of two parentheses
                                ⍵∊ ______  check which characters from ⍵ are parens
                            1-2× ________  -1 for every par., 1 for every other char
                         ⍵/⍨ ____________  replace () with spaces in the orig. string
    (                 ),¨ _______________  append every char to the following items
                   ,\⍵ _____________________  for every prefix of the original string
               p∘.= ________________________  check which chars are '(' and which ')'
            +/¨ ____________________________  sum: compute the number of '(' and ')'
          -⌿ _______________________________  subtract the no. of ')' from that of '('
     ↑∘''¨ _________________________________  generate as many spaces as that number
 ⊖⍉⊃ ____________________________________  make it into a table, transpose and flip

Beispiele:

topo '((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))'
          4 5                cherries    woohoo   
  1 2  3       moo       lik          e           
                      i                           

 

topo 'a  (  b ( c(d)e ) f  )  g'
            d            
          c   e          
      b           f      
a                       g

*: APL kann in einer Vielzahl älterer Einzelbyte-Zeichensätze gespeichert werden, die APL-Symbole den oberen 128 Byte zuordnen. Aus diesem Grund kann ein Programm, das nur ASCII-Zeichen und APL-Symbole verwendet, zum Golfen als Zeichen = Byte gewertet werden.

Tobia
quelle
Ich suche den APL-Zeichensatz hier und kann das Symbol nicht finden . Es sieht aus wie eine Kombination aus den Zeichen ¨und ~?
Gareth
Hi @Gareth Nein, es war nicht in IBM APL2. Sie können es in finden Dyalog (kommerziell, aber es gibt eine nagware Version in ihrer Website begraben, und das ist gut genug für den Golfsport; IMHO der beste APL heute verfügbar ist ), Nars2000 (beste Open - Source - APL), GNU APL und ngn APL unter Andere.
Tobia
@Gareth Grafisch ist es die Kombination von ~und ¨, obwohl es ein anderes Zeichen als beide ist. Es ist ein Operator namens Commute . In seiner dyadischen Form dreht sie die Argumente der dyadischen Funktion es angewendet: (5-2)=(2-⍨5). Als monadischen Operator stellt sich eine dyadische Funktion in monadischen, das richtige Argument zu duplizieren: (2*2)=(*⍨2). Es wird meistens verwendet, um einen ununterbrochenen Strom von Funktionen von rechts nach links zu schreiben, ohne große Ausdrücke in Klammern zu setzen und mit den Augen darum herumzuspringen. Beim Golfen ist es nützlich, weil 3*⍨1-2ein Char weniger ist als (1-2)*3:-)
Tobia
2
Also ist es das Äquivalent von ~in J dann.
Gareth
3

J, 56 Zeichen

'( ) 'charsub|.|:((,~#&' ')"0[:+/\1 _1 0{~'()'&i.)1!:1]1

Eine weitere 56-Zeichen - J - Lösung ... I zählen Tiefe durch die Übersetzung (in ⁻1, )in 1 und alle anderen Zeichen in 0, und dann nimmt die laufende Summe dieses: [: +/\ 1 _1 0 {~ '()'&i.. Der Rest ähnelt weitgehend der @ Gareth-Lösung.

FireFly
quelle
2

Python, 161 Zeichen

S=raw_input()
R=range(len(S))
H=[S[:i].count('(')-S[:i].count(')')for i in R]+[0]
for h in range(max(H),0,-1):print''.join((' '+S[i])[H[i]==H[i+1]==h]for i in R)
Keith Randall
quelle
2

Python, 130

a=[""]*9
l=8
i=0
for c in raw_input():o=l;l+=c==')';l-=c=='(';a[l]=a[l].ljust(i)+c*(o==l);i+=1
print"\n".join(filter(str.strip,a))
grc
quelle
2

Ruby 1,9 (129)

Liest von stdin.

l=0
$><<gets.split('').map{|c|x=[?(]*99;x[l+=c==?(?-1:c==?)?1:0]=c;x}.transpose.map(&:join).*(?\n).tr('()',' ').gsub(/^\s+\n/,'')
Paul Prestidge
quelle
3
Nett! Sie haben einen Fehler im Ruby-
Textmarker
Ich habe getestet und SQL-Hervorhebung funktioniert besser für Ihr Programm.
Cristian Lupascu
@w0lf ha, du hast recht. Ich habe den Wert geändert //, bei ''dem die Anzahl der Charaktere gleich bleibt und der Fehler im Textmarker vermieden wird.
Paul Prestidge
2

C 132 Zeichen

char*p,b[999];n;
main(m){for(p=gets(memset(b,32,999));*p;++p)*p-41?*p-40?p[n*99]=*p:++n>m?m=n:0:--n;
for(;m;puts(b+m--*99))p[m*99]=0;}

In der Beschreibung wurde nicht angegeben, wie viele Eingaben die Übermittlung akzeptieren musste, um akzeptiert zu werden. Daher habe ich mich auf die Grenzen festgelegt, die meinen Golferfordernissen am ehesten entsprachen (während ich immer noch mit der angegebenen Beispieleingabe arbeitete). Lassen Sie mich diese Gelegenheit nutzen, um die Leute daran zu erinnern, dass es oft eine gute Idee ist, in Ihren Herausforderungsbeschreibungen Mindestmaxima anzugeben.

Der Code enthält zwei Hauptschleifen. In der ersten Schleife werden alle nicht in Klammern gesetzten Zeichen in die entsprechende Ausgabezeile ausgegeben, und in der zweiten Schleife wird jede Zeile gedruckt.

Brot-Box
quelle
1

C 149 Zeichen

#define S for(i=0;c=v[1][i++];)h+=a=c-'('?c-')'?0:-1:1,
c,i,h=0,m=0;main(int a,char**v){S m=h>m?h:m;for(;m;m--){S putchar(a||h-m?32:c);putchar(10);}}

mit angegebenem Argument ausführen, zB "((1 2) (3 (4 5) moo)) (i (lik (kirschen) e (woohoo)))"

Baby-Kaninchen
quelle
0

Oktave, 128

Sehr ähnlich zu meiner letzten Antwort ...

p=1;x=[0];y=input(0);for j=1:numel(y);p-=(y(j)==")");x(p,j)=y(j);p+=(y(j)=="(");end;x(x==40)=x(x==41)=x(x==0)=32;char(flipud(x))

Prüfung

Eingang: "((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))"

Ausgabe:

          4 5 Kirschen woohoo   
  1 2 3 mehr wie e           
                      ich                           
sudo rm -rf Schrägstrich
quelle
0

229 Bytes

Wenn es keine Einschränkung für den vertikalen Abstand zwischen den Zeilen gibt, können Sie diese verwenden (der Übersichtlichkeit halber eingerückt). Sie initialisiert den Cursor (vor dem Drucken für jede gefundene Zeile um eine Zeile nach unten und bewegt den Cursor beim Lesen von Klammern nach oben und unten.

using C=System.Console;
class P{
    static void Main(string[]a){
        int l=a[0].Length,i=l;
        while(i>0)
            if(a[0][--i]=='(')C.CursorTop++;
        while(++i<l){
            char c=a[0][i];
            if(c=='('){
                c=' ';
                C.CursorTop--;
            }
            if(c==')'){
                c=' ';
                C.CursorTop++;
            }
            C.Write(c);
        }
    }
}
Hand-E-Food
quelle
0

PowerShell , 120 bis 119 Byte

(($h=($c=$args|% t*y)|%{($l+=(1,-1)[$_-40])})|sort)[-1]..0|%{$x=0;$y=$_
-join($c|%{"$_ "[$h[$x++]-ne$y-or$_-in40,41]})}

Probieren Sie es online!

Nebenwirkungen: Zeichnet &und 'ändert die Höhe wie (und ), wird jedoch angezeigt. Ergebnisse vergleichen für:

&$f "((1 2)(3 (4 5) moo)) (i (lik(cherries)e (woohoo)))"
&$f "&&1 2'&3 &4 5' moo'' &i &lik&cherries'e &woohoo'''"

Weniger golfen:

$chars=$args|% toCharArray

$heights=$chars|%{
    $level+=(1,-1)[$_-40]       # 40 is ASCII for '(', 41 is ASCII for ')'
    $level
}

$maxHeight=($heights|sort)[-1]

$maxHeight..0|%{
    $x=0;$y=$_
    $line=$chars|%{
        "$_ "[$heights[$x++]-ne$y -or $_-in40,41]
    }
    -join($line)
}
mazzy
quelle
-1

VB.net (für S & G)

Nicht der schönste Code.

Module Q
 Sub Main(a As String())
  Dim t = a(0)
  Dim h = 0
  For Each m In (From G In (t.Select(Function(c)
                                     h += If(c = "(", 1, If(c = ")", -1, 0))
                                     Return h
                                   End Function).Select(Function(y, i) New With {.y = y, .i = i}))
             Group By G.y Into Group
             Order By   y Descending
            Select Group.ToDictionary(Function(x) x.i)
               ).Select(Function(d) New String(
                          t.Select(Function(c,i)If(d.ContainsKey(i),If(c="("c Or c=")"c," "c,c)," "c)).ToArray))
   Console.WriteLine(m)
  Next
 End Sub
End Module
Adam Speight
quelle