Parser tag semplice


9

Questo è un modello di un parser HTML perdonatore. Invece di analizzare HTML ed estrarre attributi, in questo codice golf, il tag parser sarà semplice.

Scrivi una funzione che analizza una struttura di tag e restituisce la sua forma tra parentesi. Un tag di apertura è costituito da una lettera minuscola e un tag di chiusura è costituito da una lettera maiuscola. Ad esempio, aAbaABanalizza in (a)(b(a)), o in HTML, <a></a><b><a></a></b>. Naturalmente, i tag possono essere in giustapposizione e nidificare.

I tag chiusi "prematuramente" devono essere gestiti. Ad esempio, in abcA, il Achiude il più esterno a, quindi analizza (a(b(c))).

I tag di chiusura extra vengono semplicemente ignorati: aABanalizza in (a).

I tag sovrapposti NON vengono gestiti. Ad esempio, abABanalizza (a(b)), non (a(b))(b), la regola precedente dei tag di chiusura extra ( abAB-> abA( (a(b))) + B(extra)).

Supponendo che non vi siano spazi bianchi e altri caratteri illegali nell'input.

Non è consentito utilizzare alcuna libreria.

Ecco un'implementazione di riferimento e un elenco di casi di test:

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

Il codice più corto vince.


come qualsiasi altro codice golf, biblioteca standard consentita
Ming-Tang

nessun limite di lunghezza o livello di nidificazione
Ming-Tang

4
Dovresti aggiungere un caso di test per l'input che porta con un tag di chiusura, come AbcBCabA(dovrebbe analizzare come (b(c))(a(b)). Il mio codice avrebbe potuto essere più breve, tranne per questo caso.
MtnViewMark

Risposte:


1

Golfscript, 54 caratteri

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

test

;["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))

6

Haskell, 111 caratteri

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

Questo è bello per Haskell. Fun feature: lo stack e l'output accumulato sono mantenuti nella stessa stringa!

Casi test:

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

  • Modifica: (113 → 111) ha usato un @modello come suggerito da FUZxxl

L'uso di un @ -pattern per d: z potrebbe salvare due caratteri.
FUZxxl

4

Codice macchina Z80 per TI-83 +, 41 byte

Questa è un'implementazione in codice macchina esadecimale per una CPU z80 in esecuzione su una TI-83 +.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

XXXX (compreso tra 3 e 6) è l'indirizzo a 16 bit della stringa che si sta analizzando, meno 1 byte.

Codificato in Z80-ASCII:

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

(Approssimativo, perché i calcolatori TI hanno il proprio set di caratteri.)

NOTA CHE AsmPrgmNON È INCLUSO QUANTO SOPRA


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

Alcune cose da notare: questo è solo un blocco di script. Può essere assegnato a una variabile o assegnato un nome di funzione, se necessario. Puoi anche eseguirlo mettendo .o &davanti ad esso e gli argomenti alla fine. Utilizza uno spazio finale per terminare i tag non chiusi.

Supera tutti i test. Script di prova:

$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]]
}

2

Python - 114 113 153 192 174 159 caratteri

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

Abusa del parser di rientro di Python per usare uno spazio per una scheda completa, cinque per due schede.

Modifica 1 - salvato uno spazio non necessario nella funzione range ()

Modifica 2 - risolto per gestire grammatiche di analisi improprie, tag non terminati.

Modifica 3 - risolto un bug per cui analisi "errate" potevano essere generate dall'ambiguità nella struttura dei tag. Implementata una strategia basata su stack, piuttosto che un contatore.

Modifica 4 - rinominato s.find in o per impedire il salvataggio dei caratteri utilizzati per chiamarlo ripetutamente. ha fatto lo stesso per f.lower.

Modifica 5 : aggiunto l'hack dello spazio / scheda, salvando tre caratteri.

Modifica 6 - abbandonato il ciclo a favore di ")" * d.


1
invece di ord(f)...te puoi usare '@'<f<'\\'Se non hai bisogno di controllare '\\'puoi usare ']'invece
gnibbler

1
puoi usare una singola scheda invece di 5 spazi. Il markup del codice SO non può gestirlo però :(. Nel tuo caso basta lasciare fuori la nuova riga e gli spazi del tutto. Es. if ...:s+=")";c-=1Eelse:s+="("+f;c+=1
gnibbler

1
for i in range(d):s+=")"può essere riscritto come s+=")"*d. E hai 174 caratteri.
cemper93,

@cemper - buon punto quello. Faccio "_" * 80 tutto il giorno e me ne dimentico durante il golf .... Grazie anche a @gnibbler per i suggerimenti!
arrdem,

In realtà, ho fatto sì che avessi avuto 174 caratteri prima . Quindi sei a 159 ora.
cemper93,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.