Analyseur de balises simple

9

Ceci est un modèle d'un analyseur HTML indulgent. Au lieu d'analyser le HTML et d'extraire les attributs, dans ce code golf, l'analyseur de balises sera simple.

Écrivez une fonction qui analyse une structure de balises et renvoie sa forme entre parenthèses. Une balise d'ouverture se compose d'une lettre minuscule et une balise de fermeture se compose d'une lettre majuscule. Par exemple, aAbaABparse dans (a)(b(a))ou en HTML, <a></a><b><a></a></b>. Bien sûr, les balises peuvent être juxtaposées et imbriquées.

Les balises fermées "prématurément" doivent être gérées. Par exemple, dans abcA, le Aferme le plus à l'extérieur a, de sorte qu'il analyse (a(b(c))).

Les balises de fermeture supplémentaires sont simplement ignorées: elles sont aABanalysées (a).

Les balises qui se chevauchent ne sont PAS gérées. Par exemple, abABanalyse (a(b)), non (a(b))(b), par la règle précédente des balises de fermeture supplémentaires ( abAB-> abA( (a(b))) + B(extra)).

En supposant qu'il n'y ait pas d'espaces blancs et d'autres caractères illégaux dans l'entrée.

Vous n'êtes pas autorisé à utiliser une bibliothèque.

Voici une implémentation de référence et une liste de cas de 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)

Le code le plus court gagne.

Ming-Tang
la source
comme tous les autres golfs de code, bibliothèque standard autorisée
Ming-Tang
aucune limite de longueur ni de niveau de nidification
Ming-Tang
4
Vous devez ajouter un cas de test pour l'entrée qui mène avec une balise de fermeture, comme AbcBCabA(devrait analyser comme (b(c))(a(b)). Mon code aurait pu être plus court sauf dans ce cas.
MtnViewMark

Réponses:

1

Golfscript, 54 caractères

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

Les 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))
VOUS
la source
6

Haskell, 111 caractères

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

Celui-ci est assez golfé pour Haskell. Fonction amusante: la pile et la sortie accumulée sont conservées dans la même chaîne!

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

  • Modifier: (113 → 111) a utilisé un @modèle comme suggéré par FUZxxl
MtnViewMark
la source
L'utilisation d'un @ -pattern pour d: z peut enregistrer deux caractères.
FUZxxl
4

Code machine Z80 pour TI-83 +, 41 octets

Il s'agit d'une implémentation en code machine hexadécimal pour un processeur z80 fonctionnant sur une TI-83 +.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

Le XXXX (3 - 6 inclus) est l'adresse 16 bits de la chaîne que vous analysez, moins 1 octet.

Encodé en Z80-ASCII:

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

(Approximatif, car les calculatrices TI ont leur propre jeu de caractères.)

NOTEZ QUE CE AsmPrgmN'EST PAS INCLUS DANS LE CI-DESSUS

Élektra
la source
2

Windows PowerShell, 142 146 147 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"}})}

Quelques points à noter: ce n'est qu'un bloc de script. Il peut être affecté à une variable ou donné un nom de fonction, si nécessaire. Vous pouvez également l'exécuter en plaçant .ou &en face de lui et les arguments à la fin. Utilise un espace final pour terminer les balises non fermées.

Réussit tous les tests. Script de test:

$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
la source
2

Python - 114 113 153 192 174 159 caractères

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

Utilise l'analyseur d'indentation de python pour utiliser un espace pour un onglet complet, cinq pour deux onglets.

Edit 1 - a enregistré un espace inutile dans la fonction range ()

Edit 2 - corrigé pour faire face à des grammaires d'analyse incorrectes, des balises non terminées.

Edit 3 - correction d'un bug qui pouvait générer des analyses "incorrectes" par ambiguïté dans l'arborescence des balises. Implémenter une stratégie basée sur la pile, plutôt qu'un compteur.

Edit 4 - renommé s.find en o pour éviter d'enregistrer les caractères utilisés pour l'appeler à plusieurs reprises. a fait de même pour f. inférieur.

Édition 5 - ajout du hack d'espace / tabulation, économisant trois caractères.

Edit 6 - abandonné la boucle en faveur de ")" * d.

arrdem
la source
1
au lieu de ord(f)...vous pouvez utiliser '@'<f<'\\'Si vous n'avez pas besoin de vérifier, '\\'vous pouvez utiliser à la ']'place
gnibbler
1
vous pouvez utiliser un seul onglet au lieu de 5 espaces. Cependant, le balisage de code SO ne peut pas le gérer :(. Dans votre cas, mettez simplement la nouvelle ligne et les espaces complètement à l' if ...:s+=")";c-=1else:s+="("+f;c+=1
écart
1
for i in range(d):s+=")"peut être réécrit en s+=")"*d. Et vous avez 174 caractères.
cemper93
@cemper - bon point. Je fais "_" * 80 toute la journée et j'oublie quand je joue au golf .... Merci aussi à @gnibbler pour les suggestions!
arrdem
En fait, je voulais dire que vous aviez eu 174 caractères auparavant . Vous en êtes donc maintenant à 159.
cemper93