Prosty parser tagów

9

To jest model wybaczającego parsera HTML. Zamiast analizować HTML i wyodrębniać atrybuty, w tym kodzie golfowym parser znaczników będzie prosty.

Napisz funkcję, która przeanalizuje strukturę znaczników i zwróci jej nawiasową formę. Znacznik otwierający składa się z jednej małej litery, a znacznik zamykający składa się z jednej wielkiej litery. Na przykład, aAbaABanalizuje się (a)(b(a)), czy w HTML <a></a><b><a></a></b>. Oczywiście tagi mogą znajdować się w zestawieniu i zagnieżdżeniu.

Należy obsługiwać „przedwcześnie” zamknięte znaczniki. Na przykład w abcA, Azamyka skrajne a, więc analizuje w (a(b(c))).

Dodatkowe znaczniki zamykające są po prostu ignorowane: aABanalizuje w (a).

Nakładające się tagi NIE są obsługiwane. Na przykład abABanalizuje (a(b)), a nie (a(b))(b)poprzednią zasadę dodatkowych tagów zamykających ( abAB-> abA( (a(b))) + B(extra)).

Zakładając, że na wejściu nie ma białych znaków i innych niedozwolonych znaków.

Nie możesz używać żadnej biblioteki.

Oto implementacja referencyjna i lista przypadków testowych:

#!/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)

Najkrótszy kod wygrywa.

Ming-Tang
źródło
jak każdy inny golf golfowy, dozwolona jest standardowa biblioteka
Ming-Tang
brak ograniczenia długości i poziomu zagnieżdżenia
Ming-Tang,
4
Należy dodać przypadek testowy dla danych wejściowych, które prowadzą ze znacznikiem zamykającym, na przykład AbcBCabA(powinien parsować jako (b(c))(a(b)). Mój kod mógłby być krótszy, z wyjątkiem tego przypadku.
MtnViewMark

Odpowiedzi:

1

Golfscript, 54 znaki

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

Testy

;["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))
TY
źródło
6

Haskell, 111 znaków

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

Ten jest fajny dla Haskella. Zabawna funkcja: stos i kumulowane wyniki są przechowywane w tym samym łańcuchu!

Przypadki testowe:

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

  • Edycja: (113 → 111) użył @wzorca sugerowanego przez FUZxxl
MtnViewMark
źródło
Użycie @ -pattern dla d: z może zapisać dwa znaki.
FUZxxl
4

Kod maszynowy Z80 dla TI-83 +, 41 bajtów

Jest to implementacja szesnastkowego kodu maszynowego dla procesora Z80 działającego na TI-83 +.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

XXXX (3-6 włącznie) to 16-bitowy adres analizowanego ciągu, minus 1 bajt.

Zakodowane w Z80-ASCII:

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

(Przybliżone, ponieważ kalkulatory TI mają swój własny zestaw znaków.)

UWAGA, ŻE AsmPrgmNIE JEST WŁĄCZONE POWYŻEJ

Élektra
źródło
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"}})}

Kilka rzeczy do zapamiętania: To tylko blok skryptu. W razie potrzeby można go przypisać do zmiennej lub nadać nazwę funkcji. Możesz również uruchomić go, umieszczając .lub &przed nim i argumentami na końcu. Używa ostatniego miejsca do zakończenia niezamkniętych znaczników.

Przechodzi wszystkie testy. Skrypt testowy:

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

Python - 114 113 153 192 174 159 znaków

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

Nadużywa parsera wcięć Pythona, aby użyć jednej spacji dla pełnej tabulacji, pięciu dla dwóch tabulacji.

Edycja 1 - zapisano niepotrzebne miejsce w funkcji range ()

Edycja 2 - naprawiono, aby radzić sobie z niewłaściwymi gramatykami, niezakończonymi tagami.

Edycja 3 - naprawiono błąd, przez który „dwuznaczne” analizy mogły być generowane przez niejednoznaczność w drzewie znaczników. Zaimplementowano strategię opartą na stosie, a nie licznik.

Edytuj 4 - zmieniono nazwę s.find na o, aby zapobiec zapisywaniu znaków używanych do wielokrotnego wywoływania go. zrobił to samo dla F.lower.

Edycja 5 - dodano hakowanie spacji / tabulatorów, oszczędzając trzy znaki.

Edycja 6 - porzuciłem pętlę na korzyść „)” * d.

arrdem
źródło
1
zamiast tego ord(f)...możesz użyć '@'<f<'\\'Jeśli nie musisz tego sprawdzać '\\', możesz użyć ']'zamiast
gnibbler
1
możesz użyć jednej tabulacji zamiast 5 spacji. Znaczniki kodu SO nie mogą sobie z tym poradzić :(. W twoim przypadku po prostu if ...:s+=")";c-=1else:s+="("+f;c+=1
wypuść nową linię
1
for i in range(d):s+=")"można przepisać jako s+=")"*d. I masz 174 znaki.
cemper93
@cemper - dobrze, że. Robię „_” * 80 przez cały dzień i zapominam o tym podczas gry w golfa .... Dziękuję również @gnibbler za sugestie!
arrdem
Właściwie, to oznaczało, że miał 174 znaków przed . Masz teraz 159 lat.
cemper93