Analizador de etiquetas simple

9

Este es un modelo de un analizador de HTML indulgente. En lugar de analizar HTML y extraer atributos, en este campo de código, el analizador de etiquetas será simple.

Escriba una función que analice una estructura de etiqueta y devuelva su forma entre paréntesis. Una etiqueta de apertura consta de una letra minúscula y una etiqueta de cierre consta de una letra mayúscula. Por ejemplo, aAbaABanaliza en (a)(b(a)), o en HTML, <a></a><b><a></a></b>. Por supuesto, las etiquetas pueden estar en yuxtaposición y anidarse.

Las etiquetas cerradas "prematuramente" deben manejarse. Por ejemplo, en abcA, Acierra el más externo a, por lo que analiza en (a(b(c))).

Las etiquetas de cierre adicionales simplemente se ignoran: se aABanaliza en (a).

Las etiquetas superpuestas NO se manejan. Por ejemplo, abABanaliza (a(b)), no (a(b))(b), por la regla anterior de etiquetas de cierre adicionales ( abAB-> abA( (a(b))) + B(extra)).

Asumiendo que no hay espacios en blanco y otros caracteres ilegales en la entrada.

No tiene permitido usar ninguna biblioteca.

Aquí hay una implementación de referencia y una lista de casos de prueba:

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

El código más corto gana.

Ming-Tang
fuente
como cualquier otro código de golf, se permite la biblioteca estándar
Ming-Tang
sin límite de longitud ni nivel de anidación
Ming-Tang
44
Usted debe agregar un caso de prueba para la entrada que conduce con una etiqueta de cierre, tales como AbcBCabA(deben analizar como (b(c))(a(b))Mi código podría haber sido más corto a excepción de este caso..
MtnViewMark

Respuestas:

1

Golfscript, 54 caracteres

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

Pruebas

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

fuente
6

Haskell, 111 personajes

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

Este es un bonito campo de golf para Haskell. Característica divertida: ¡La pila y la salida acumulada se mantienen en la misma cadena!

Casos de prueba:

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

  • Editar: (113 → 111) usó un @patrón sugerido por FUZxxl
MtnViewMark
fuente
Usar un @ -pattern para d: z podría ahorrar dos caracteres.
FUZxxl
4

Código de máquina Z80 para TI-83 +, 41 bytes

Esta es una implementación en código máquina hexadecimal para una CPU z80 que se ejecuta en una TI-83 +.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

XXXX (3 - 6 inclusive) es la dirección de 16 bits de la cadena que está analizando, menos 1 byte.

Codificado en Z80-ASCII:

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

(Aproximado, porque las calculadoras TI tienen su propio conjunto de caracteres).

NOTA QUE EL AsmPrgmNO ESTÁ INCLUIDO EN LO ANTERIOR

Élektra
fuente
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"}})}

Algunas cosas a tener en cuenta: Esto es solo un bloque de script. Se puede asignar a una variable o dar un nombre de función, si es necesario. También puede ejecutarlo poniendo .o &delante de él y los argumentos al final. Utiliza un espacio final para terminar las etiquetas no cerradas.

Pasa todas las pruebas. Script de prueba:

$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
fuente
2

Python - 114 113 153 192 174 159 caracteres

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 analizador de sangría de Python para usar un espacio para una pestaña completa, cinco para dos pestañas.

Edición 1 : guardado un espacio innecesario en la función range ()

Edición 2 : corregido para tratar con gramáticas de análisis incorrectas, etiquetas no terminadas.

Edición 3 : se corrigió un error por el cual se podían generar análisis "incorrectos" por la ambigüedad en el árbol de etiquetas. Implementó una estrategia basada en la pila, en lugar de un contador.

Editar 4 - renombrado de s.find a o para evitar guardar los caracteres utilizados para llamarlo repetidamente. hizo lo mismo para f.lower.

Editar 5 : se agregó el hack de espacio / tabulación, ahorrando tres caracteres.

Editar 6 : abandonó el bucle a favor de ")" * d.

arrdem
fuente
1
en lugar de ord(f)...que pueda usar '@'<f<'\\'Si no necesita verificar '\\', puede usar ']'en su lugar
gnibbler
1
puedes usar una sola pestaña en lugar de 5 espacios. SO código de marcado no puede manejarlo, aunque :( En su caso sólo hay que poner la licencia de la nueva línea y los espacios por completo por ejemplo.. if ...:s+=")";c-=1Yelse:s+="("+f;c+=1
gnibbler
1
for i in range(d):s+=")"puede reescribirse como s+=")"*d. Y tienes 174 caracteres.
cemper93
@cemper: buen punto. Hago "_" * 80 todo el día y me olvido al jugar al golf ... Además, ¡gracias a @gnibbler por las sugerencias!
llega
En realidad, quise decir que habías tenido 174 caracteres antes . Entonces estás en 159 ahora.
cemper93