Einfacher Tag-Parser

9

Dies ist ein Modell eines verzeihenden HTML-Parsers. Anstatt HTML zu analysieren und Attribute zu extrahieren, ist der Tag-Parser in diesem Code Golf einfach.

Schreiben Sie eine Funktion, die eine Tag-Struktur analysiert und ihre übergeordnete Form zurückgibt. Ein öffnendes Tag besteht aus einem Kleinbuchstaben, und ein schließendes Tag besteht aus einem Großbuchstaben. Zum Beispiel aAbaABparst in (a)(b(a))oder in HTML, <a></a><b><a></a></b>. Natürlich können Tags nebeneinander stehen und verschachtelt sein.

"Vorzeitig" geschlossene Tags müssen behandelt werden. Zum Beispiel in abcAder Aschließt die äußerste a, so dass es in parst (a(b(c))).

Zusätzliche schließende Tags werden einfach ignoriert: aABanalysiert in (a).

Überlappende Tags werden NICHT behandelt. abABAnalysiert beispielsweise (a(b))nicht (a(b))(b)nach der vorherigen Regel für zusätzliche schließende Tags ( abAB-> abA( (a(b))) + B(extra)).

Angenommen, die Eingabe enthält keine Leerzeichen und keine anderen unzulässigen Zeichen.

Sie dürfen keine Bibliothek benutzen.

Hier ist eine Referenzimplementierung und eine Liste von Testfällen:

#!/usr/bin/python

def pars(inpu):
  outp = ""
  stac = []
  i = 0
  for x in inpu:
    lowr = x.lower()
    if x == lowr:
      stac.append(x)
      outp += "(" + x
      i = i + 1
    else:
      while len(stac) > 1 and stac[len(stac) - 1] != lowr:
        outp += ")"
        stac.pop()
        i = i - 1
      if len(stac) > 0:
        outp += ")"
        stac.pop()
        i = i - 1
  outp += ")" * i
  return outp

tests = [
  ("aAaAbB", "(a)(a)(b)"),
  ("abBcdDCA", "(a(b)(c(d)))"),
  ("bisSsIB", "(b(i(s)(s)))"),
  ("aAabc", "(a)(a(b(c)))"),
  ("abcdDA", "(a(b(c(d))))"),
  ("abcAaA", "(a(b(c)))(a)"),
  ("acAC", "(a(c))"),
  ("ABCDEFG", ""),
  ("AbcBCabA", "(b(c))(a(b))")
]

for case, expe in tests:
  actu = pars(case)
  print "%s: C: [%s] E: [%s] A: [%s]" % (["FAIL", "PASS"][expe == actu], case, expe, actu)

Der kürzeste Code gewinnt.

Ming-Tang
quelle
Wie bei jedem anderen Code-Golf ist die Standardbibliothek erlaubt
Ming-Tang
Keine Begrenzung der Länge oder des Verschachtelungsniveaus
Ming-Tang
4
Sie sollten einen Testfall für Eingaben hinzufügen, der mit einem schließenden Tag führt, z. B. AbcBCabA(sollte analysiert werden als (b(c))(a(b)). Mein Code hätte bis auf diesen Fall kürzer sein können.
MtnViewMark

Antworten:

1

Golfscript, 54 Zeichen

{[]:|\{.96>{.|+:|;40\}{32+|?).')'*\|>:|;}if}%|,')'*}:$

Tests

;["aAaAbB" "abBcdDCA" "bisSsIB" "aAabc" "abcdDA" "abcAaA" "acAC" "aAB" "abAB" "AbcBCabA"]{.' '\$n}%

aAaAbBaAaAbB (a)(a)(b)
abBcdDCA (a(b)(c(d)))
bisSsIB (b(i(s)(s)))
aAabc (a)(a(b(c)))
abcdDA (a(b(c(d))))
abcAaA (a(b(c)))(a)
acAC (a(c))
aAB (a)
abAB (a(b))
AbcBCabA (b(c))(a(b))
DU
quelle
6

Haskell, 111 Zeichen

s@(d:z)§c|c>'^'=toEnum(fromEnum c-32):s++'(':[c]|d<'='=s|d==c=z++")"|1<3=(z++")")§c
p=tail.foldl(§)"$".(++"$")

Das hier ist ziemlich gut für Haskell. Unterhaltsame Funktion: Der Stapel und die akkumulierte Ausgabe bleiben in derselben Zeichenfolge!

Testfälle:

> runTests 
Pass: aAbaAB parsed correctly as (a)(b(a))
Pass: abcA parsed correctly as (a(b(c)))
Pass: aAB parsed correctly as (a)
Pass: abAB parsed correctly as (a(b))
Pass: aAaAbB parsed correctly as (a)(a)(b)
Pass: abBcdDCA parsed correctly as (a(b)(c(d)))
Pass: bisSsIB parsed correctly as (b(i(s)(s)))
Pass: aAabc parsed correctly as (a)(a(b(c)))
Pass: abcdDA parsed correctly as (a(b(c(d))))
Pass: abcAaA parsed correctly as (a(b(c)))(a)
Pass: acAC parsed correctly as (a(c))
Pass: AbcBCabA parsed correctly as (b(c))(a(b))

  • Bearbeiten: (113 → 111) verwendete ein @von FUZxxl vorgeschlagenes Muster
MtnViewMark
quelle
Wenn Sie ein @ -Muster für d: z verwenden, werden möglicherweise zwei Zeichen gespeichert.
FUZxxl
4

Z80-Maschinencode für TI-83 +, 41 Byte

Dies ist eine Implementierung in hexadezimalem Maschinencode für eine z80-CPU, die auf einem TI-83 + ausgeführt wird.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

XXXX (3 - 6 einschließlich) ist die 16-Bit-Adresse der Zeichenfolge, die Sie analysieren, minus 1 Byte.

In Z80-ASCII codiert:

¹XX≤¯•⟙8𝑭o↥>(ˣïÑ}ˣïÑ≠á↑γ∊>)ˣïÑ≠Ì⬆︎E𝑤↥!₄L↑Φ

(Ungefähr, da TI-Rechner einen eigenen Zeichensatz haben.)

HINWEIS , DASS DIE AsmPrgmIN DER OBEN ist nicht inbegriffen

Élektra
quelle
2

Windows PowerShell, 142 146 147 152 156 169

{$s=''
-join([char[]]"$args "|%{if(90-ge$_){')'*(($x=$s.indexOf("$_".ToLower())+1)+$s.Length*!$x)
$s=$s.substring($x)}else{"($_"
$s="$_$s"}})}

Einige Dinge zu beachten: Dies ist nur ein Skriptblock. Sie kann bei Bedarf einer Variablen zugewiesen oder mit einem Funktionsnamen versehen werden. Sie können es auch ausführen, indem Sie .oder &davor und die Argumente am Ende setzen. Verwendet ein letztes Leerzeichen, um nicht geschlossene Tags zu beenden.

Besteht alle Tests. Testskript:

$tests = ("aAaAbB","(a)(a)(b)"),("abBcdDCA","(a(b)(c(d)))"),("bisSsIB","(b(i(s)(s)))"),("aAabc","(a)(a(b(c)))"),("abcdDA","(a(b(c(d))))"),("abcAaA", "(a(b(c)))(a)"),("acAC","(a(c))")
"function f " + ((gc ./tags.ps1)-join"`n") | iex
$tests | %{
    $result = f $_[0]
    ("FAIL: $($_[0]):$($_[1]) - $result", 'PASS')[$result -ceq $_[1]]
}
Joey
quelle
2

Python - 114 113 153 192 174 159 Zeichen

from sys import *
s="";c=a=argv[1]
for f in a:
 o=c.find;p=f.lower
 if '@'<f<'\\':
\td=o(f)-o(p())
\ts+=")"*d
\tc=(c[:o(p())]+c[o(f)+1:])
 else:s+=("("+f)
print s

Missbraucht den Einrückungsparser von Python, um ein Leerzeichen für eine vollständige Registerkarte und fünf für zwei Registerkarten zu verwenden.

Bearbeiten 1 - sparte einen nicht benötigten Platz in der Funktion range ()

Bearbeiten 2 - behoben, um mit falschen Analyse-Grammatiken und nicht abgeschlossenen Tags umzugehen.

Bearbeiten 3 - Es wurde ein Fehler behoben, durch den "falsche" Analysen durch Mehrdeutigkeit im Tag-Baum generiert werden konnten. Implementierte eine stapelbasierte Strategie anstelle eines Zählers.

Edit 4 - s.find in o umbenannt, um zu verhindern, dass die Zeichen gespeichert werden, mit denen es wiederholt aufgerufen wird. tat das gleiche für f.lower.

Bearbeiten 5 - Fügte den Space / Tab-Hack hinzu und sparte drei Zeichen.

Edit 6 - hat die Schleife zugunsten von ")" * d verworfen.

arrdem
quelle
1
anstatt ord(f)...Sie können verwenden '@'<f<'\\'Wenn Sie nicht '\\'']'
suchen
1
Sie können eine einzelne Registerkarte anstelle von 5 Leerzeichen verwenden. SO Code Markup kann aber nicht damit umgehen :(. In Ihrem Fall lassen Sie einfach die Newline und die Leerzeichen insgesamt weg. if ...:s+=")";c-=1else:s+="("+f;c+=1
ZB
1
for i in range(d):s+=")"kann umgeschrieben werden als s+=")"*d. Und du hast 174 Zeichen.
Cemper93
@cemper - guter Punkt, dass. Ich mache den ganzen Tag "_" * 80 und vergesse es beim Golfen .... Danke auch an @gnibbler für die Vorschläge!
Arrdem
Eigentlich meinte ich, dass Sie schon einmal 174 Zeichen hatten . Sie sind jetzt bei 159.
Cemper93