Простой парсер тегов

9

Это модель прощающего анализатора HTML. Вместо синтаксического анализа HTML и извлечения атрибутов в этом кодовом гольфе анализатор тегов будет простым.

Напишите функцию, которая анализирует структуру тегов и возвращает ее заключенную в скобки форму. Открывающий тег состоит из одной строчной буквы, а закрывающий тег состоит из одной заглавной буквы. Например, aAbaABанализирует (a)(b(a))или в HTML <a></a><b><a></a></b>. Конечно, теги могут быть в сопоставлении и гнезде.

«Преждевременно» закрытые теги должны быть обработаны. Например, в abcA, то Aзакрывает удаленный от центра a, поэтому он разбирает в (a(b(c))).

Дополнительные закрывающие теги просто игнорируются: aABанализируются в (a).

Перекрывающиеся теги НЕ обрабатываются. Например, abABразбирает в (a(b)), не (a(b))(b), предыдущим правилом дополнительных тегов закрытия ( abAB-> abA( (a(b))) + B( за дополнительную плату)).

Предполагая отсутствие пробелов и других недопустимых символов на входе.

Вы не можете использовать любую библиотеку.

Вот эталонная реализация и список тестовых случаев:

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

Самый короткий код выигрывает.

Мин-Tang
источник
как и любой другой код гольф, стандартная библиотека разрешена
Ming-Tang
нет ограничений по длине и уровню вложенности
Ming-Tang
4
Вы должны добавить тестовый пример для ввода, который ведет с закрывающим тегом, например AbcBCabA(должен анализироваться как (b(c))(a(b)). Мой код мог бы быть короче, за исключением этого случая.
MtnViewMark

Ответы:

1

Golfscript, 54 символа

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

тесты

;["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 символов

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

Этот красивый гольф для Хаскелла. Забавная особенность: стек и накопленный вывод хранятся в одной строке!

Тестовые случаи:

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

  • Редактировать: (113 → 111) использовал @шаблон, как предложено FUZxxl
MtnViewMark
источник
Использование @ -pattern для d: z может сохранить два символа.
FUZxxl
4

Машинный код Z80 для TI-83 +, 41 байт

Это реализация в шестнадцатеричном машинном коде для процессора z80, работающего на TI-83 +.

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

XXXX (3–6 включительно) - это 16-битный адрес анализируемой строки минус 1 байт.

Закодировано в Z80-ASCII:

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

(Приблизительно, потому что калькуляторы TI имеют свой собственный набор символов.)

ПРИМЕЧАНИЕ, ЧТО AsmPrgmНЕ ВКЛЮЧЕНО В ВЫШЕ

Электра
источник
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"}})}

Некоторые вещи, на которые стоит обратить внимание: это просто блок скрипта. При необходимости его можно присвоить переменной или дать имя функции. Вы также можете запустить его, поставив .или &перед ним и аргументы в конце. Использует последний пробел для завершения незакрытых тегов.

Проходит все тесты. Тестовый скрипт:

$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 символов

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

Злоупотребляет синтаксическим анализатором отступов в python, чтобы использовать один пробел для полной вкладки, пять для двух вкладок.

Редактировать 1 - сохранить ненужный пробел в функции range ()

Edit 2 - исправлено, чтобы иметь дело с неправильными грамматиками разбора, неопределенными тегами.

Редактировать 3 - исправлена ​​ошибка, из-за которой "неправильные" парсинги могли генерироваться неоднозначностью в дереве тегов. Реализована основанная на стеке стратегия, а не счетчик.

Редактировать 4 - переименовать s.find в o, чтобы не сохранять символы, используемые для его повторного вызова. сделал то же самое для f.lower.

Редактировать 5 - добавлен хак пробел / вкладка, сохранив три символа.

Редактировать 6 - исключить цикл в пользу ")" * d.

arrdem
источник
1
вместо ord(f)...вы можете использовать '@'<f<'\\'Если вам не нужно проверять, '\\'вы можете использовать ']'вместо
gnibbler
1
Вы можете использовать одну вкладку вместо 5 пробелов. Так что разметка кода не может справиться с этим :(. В вашем случае просто не if ...:s+=")";c-=1else:s+="("+f;c+=1
указывайте символ
1
for i in range(d):s+=")"можно переписать как s+=")"*d. И у вас есть 174 символа.
cemper93
@cemper - это хорошо. Я делаю "_" * 80 целый день и забываю об этом при игре в гольф .... Также, спасибо @gnibbler за предложения!
августа
На самом деле, я имел в виду, что у вас было 174 символа раньше . Итак, вы сейчас на 159.
cemper93