Analisador de tags simples

9

Este é um modelo de um analisador de HTML que perdoa. Em vez de analisar o HTML e extrair atributos, nesse código golf, o analisador de tags será simples.

Escreva uma função que analise uma estrutura de tags e retorne seu formulário entre parênteses. Uma tag de abertura consiste em uma letra minúscula e uma tag de fechamento consiste em uma letra maiúscula. Por exemplo, aAbaABanalisa em (a)(b(a)), ou em HTML <a></a><b><a></a></b>,. Obviamente, as tags podem estar em justaposição e aninhadas.

As tags fechadas "prematuramente" devem ser manipuladas. Por exemplo, em abcA, o Afecha o mais externo a, por isso é analisado (a(b(c))).

Tags de fechamento extras são simplesmente ignoradas: aABanalisa (a).

Tags sobrepostas NÃO são tratadas. Por exemplo, abABanalisa (a(b)), não (a(b))(b), pela regra anterior de tags de fechamento extras ( abAB-> abA( (a(b))) + B(extra)).

Supondo que não haja espaços em branco e outros caracteres ilegais na entrada.

Você não tem permissão para usar nenhuma biblioteca.

Aqui está uma implementação de referência e uma lista de casos de teste:

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

O menor código vence.

Ming-Tang
fonte
como quaisquer outros campos de golfe de código, biblioteca padrão permitido
Ming-Tang
sem limite de comprimento nem nível de aninhamento
Ming-Tang
4
Você deve adicionar um caso de teste para a entrada que conduz com uma marca de fechamento, tais como AbcBCabA(deve analisar como (b(c))(a(b))meu código poderia ter sido mais curto, exceto para este caso..
MtnViewMark

Respostas:

1

Golfscript, 54 caracteres

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

Testes

;["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))
VOCÊ
fonte
6

Haskell, 111 caracteres

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

Esse aqui é bonito para Haskell. Funcionalidade divertida: A pilha e a saída acumulada são mantidas na mesma sequência!

Casos de teste:

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

  • Edit: (113 → 111) usou um @padrão sugerido por FUZxxl
MtnViewMark
fonte
Usar um padrão @ para d: z pode salvar dois caracteres.
FUZxxl
4

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

Esta é uma implementação em código de máquina hexadecimal para uma CPU z80 em execução na TI-83 +.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

O XXXX (3-6 inclusive) é o endereço de 16 bits da string que você está analisando, menos 1 byte.

Codificado em Z80-ASCII:

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

(Aproximado, porque as calculadoras de TI têm seu próprio conjunto de caracteres.)

OBSERVAÇÃO DE AsmPrgmQUE NÃO ESTÁ INCLUÍDO ACIMA

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

Algumas coisas a serem observadas: este é apenas um bloco de script. Pode ser atribuído a uma variável ou receber um nome de função, se necessário. Você também pode executá-lo colocando .ou &na frente dele e dos argumentos no final. Usa um espaço final para finalizar tags não fechadas.

Passa em todos os testes. Script de teste:

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

Python - 114 113 153 192 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 do analisador de indentação do python para usar um espaço para uma guia completa, cinco para duas guias.

Editar 1 - salvou um espaço desnecessário na função range ()

Edição 2 - corrigida para lidar com gramáticas de análise impróprias, tags não terminadas.

Editar 3 - corrigido um bug no qual as análises "incorretas" podiam ser geradas por ambiguidade na árvore de tags. Implementou uma estratégia baseada em pilha, em vez de um contador.

Edite 4 - renomeado s.find para o para evitar salvar os caracteres usados ​​para chamá-lo repetidamente. fez o mesmo para f.lower.

Editar 5 - adicionado o hack espaço / guia, salvando três caracteres.

Edit 6 - abandonou o loop em favor de ")" * d.

arrdem
fonte
11
em vez de ord(f)...você pode usar '@'<f<'\\'Se você não precisa verificar para '\\'que você pode usar ']'em vez
gnibbler
11
você pode usar uma única guia em vez de 5 espaços. SO marcação código não pode lidar com isso embora :( No seu caso basta colocar deixar de fora a nova linha e os espaços completamente por exemplo.. if ...:s+=")";c-=1Eelse:s+="("+f;c+=1
gnibbler
11
for i in range(d):s+=")"pode ser reescrito como s+=")"*d. E você tem 174 caracteres.
Cemper93
@ cemper - bom ponto que. Faço "_" * 80 o dia todo e esqueço isso quando estou jogando golfe ... Além disso, obrigado ao @gnibbler pelas sugestões!
Arrdem
Na verdade, eu quis dizer que você já tinha 174 caracteres antes . Então você está em 159 agora.
Cemper93