Анализатор XML для ленивых программистов

15

Фон

Вы работаете программистом в компании по продаже автомобилей. Ваша задача на этой неделе - запрограммировать парсер XML, который получает данные о доступных моделях от разных производителей автомобилей и печатает информацию о новейших моделях. К счастью для вас, отдел тестирования предоставил только один тестовый пример! Чем быстрее вы сможете написать код, который его передает, тем больше у вас будет времени на промедление в течение остальной части недели.

вход

Ваш вклад - это именно тот фрагмент XML-данных, который предоставляется отделом тестирования. Он содержит данные о некоторых производителях автомобилей, их серии автомобилей и моделях этих серий. Вы можете принять завершающий символ новой строки.

<?xml version="1.0" ?>
<products>
  <manufacturer name="Test Manufacturer 1">
    <series title="Supercar" code="S1">
      <model>
        <name>Road Czar</name>
        <code>C</code>
        <year>2011</year>
      </model>
      <model>
        <name>Ubervehicle</name>
        <code>U</code>
        <year>2013</year>
      </model>
      <model>
        <name>Incredibulus</name>
        <code>I</code>
        <year>2015</year>
      </model>
      <model>
        <name>Model 1</name>
        <code>01</code>
        <year>2010</year>
      </model>
    </series>
    <series title="Test series 22" code="Test">
      <model>
        <name>Test model asdafds</name>
        <code>TT</code>
        <year>2014</year>
      </model>
    </series>
  </manufacturer>
  <manufacturer name="Car Corporation">
    <series title="Corporation Car" code="CC">
      <model>
        <name>First and Only Model</name>
        <code>FOM</code>
        <year>2012</year>
      </model>
    </series>
  </manufacturer>
  <manufacturer name="Second Test Manufacturer">
    <series title="AAAAAAAAAAAAAA" code="D">
      <model>
        <name>Some older model</name>
        <code>O</code>
        <year>2011</year>
      </model>
      <model>
        <name>The newest model</name>
        <code>N</code>
        <year>2014</year>
      </model>
    </series>
    <series title="BBBBBBBBBBBBBBB" code="asdf">
      <model>
        <name>Another newest model here</name>
        <code>TT</code>
        <year>2015</year>
      </model>
    </series>
  </manufacturer>
</products>

Выход

Ваш вывод - эта строка В нем перечислены производители автомобилей в алфавитном порядке, за ними следуют двоеточие и количество серий, которые они производят. Для каждого производителя указывается название серии, название модели и код каждой из их моделей, начиная с самой новой и начиная с года назад. Конечный пробел и разрывы строк допустимы, если ваш вывод при печати выглядит примерно так.

Car Corporation: 1 series
  Corporation Car, First and Only Model (CC-FOM)
Second Test Manufacturer: 2 series
  BBBBBBBBBBBBBBB, Another newest model here (asdf-TT)
  AAAAAAAAAAAAAA, The newest model (D-N)
  AAAAAAAAAAAAAA, Some older model (D-O)
Test Manufacturer 1: 2 series
  Supercar, Incredibulus (S1-I)
  Test series 22, Test model asdafds (Test-TT)
  Supercar, Ubervehicle (S1-U)
  Supercar, Road Czar (S1-C)
  Supercar, Model 1 (S1-01)

Правила и оценки

Вы можете написать либо функцию, либо полную программу. Побеждает меньшее количество байтов, и стандартные лазейки запрещены.

Обратите внимание, что ввод является фиксированным: вам не нужно поддерживать какие-либо другие входы, кроме приведенного здесь. Ваша программа может возвращать бессмыслицу или даже сбой, если входные данные изменены каким-либо образом. При желании вы также можете игнорировать ввод и жестко закодировать вывод. Однако вы не можете использовать библиотеки или встроенные библиотеки синтаксического анализатора XML или HTML.

Zgarb
источник
Разрешается ли анализатор HTML или это будет нарушать правила?
Вниз
11
Я никогда не хочу покупать машину у этой компании.
kirbyfan64sos 9.09.15
1
@vihan Я (довольно произвольно) решу, что HTML-парсеры также не разрешены, так как эти два формата очень похожи.
Згарб
Что насчет XSLT? ;)
Бета-распад
@BetaDecay Я собираюсь разрешить XSLT в качестве исключения, поскольку, вероятно, было бы очень утомительно и раздражающе не использовать операции синтаксического анализа XML на этом языке. : P И это не будет конкурировать с ответом CJam в любом случае.
Згарб

Ответы:

8

CJam, 109 107 байт

"rzn ¸À¨ 4T\$D"S/q"<>"'"er'"/
f{\:i2/_E5bf.+.+\ff=)1<_s,9/+":  series
"2/.+\"  ,  ()
-"2/Z4e\f.\}

Обратите внимание, что четыре символа в строке в начале непечатаемы.

Попробуйте онлайн в интерпретаторе CJam .

идея

Это в основном жесткий код, который разделяет ввод при всех вхождениях < , > и " , выбирает определенные чанки и чередует их с остальными частями выходных данных.

После разделения входных данных порциями с индексами 110 , 114 и 122 являются автомобильная корпорация , автомобильная корпорация и первая и единственная модель . Коды для серии и имени можно найти в индексах 116 и 126, которые можно рассчитать, добавив 2 и 4 к индексам имен. Наконец, количество серий - это длина строки Car Corporation, деленная на 9 (очевидно).

Таким образом, мы кодируем ту часть вывода, которая соответствует данному производителю [114 122 110], в виде строки"rzn" .

Код

e# Split the string at spaces.

"rzn ¸À¨ 4T\$D"S/

e# After replacing characters with their code points, this will be the result:
e# [[114 122 110] [184 192 144 168 144 152 140] [12 52 84 92 12 36 12 20 12 68 8]]

e# Read from STDIN, replace < and > with " and split at double quotes.

q"<>"'"er'"/ 

f{       e# For each chunk of the split string, push the split input; then:
\:i2/    e# Replace characters with character codes and split into chunks of
         e# length 2.
_E5b     e# Copy the result and push [2 4].
f.+      e# Replace each pair [I J] in the copy with [I+2 J+4].
.+       e# Vectorized concatenation.
         e# For the first chunk, we've achieved
         e# [114 122 110] -> [[114 122] [110]]
         e#               -> [[114 122] [110]] [[116 126] [110 112 4]]
         e#               -> [[114 122 116 126] [110 112 4]]
\ff=     e# Replace each integer with the chunk of the split input at that index.
)1<      e# Pop the first chunk and reduce it to the first string.
_s,9/    e# Divide that strings length by 9 and append the integer to the array.
":  series
"2/      e# Push [": " " s" "er" "ie" "s\n"].
.+       e# Vectorized concatenation; pushes the manufacturer line.
\        e# Swap the remaining strings on top of the stack.
"  ,  ()
-"2/     e# Push ["  " ", " " (" ")\n" "-"].
Z4e\     e# Swap the chunks at indexes 3 and 4.
\f.\     e# Interleave both arrays of strings.
}
Деннис
источник
10

Жевательная резинка , 227 225 байт

0000000: 6d 50 45 b6 02 31 10 dc cf 29 6a 87 eb 92 1d ee 0e 07  mPE..1...)j.......
0000012: 08 93 1e 3c e1 45 be 9d fe 37 ae bd 2b 7d 95 54 85 41  ...<.E...7..+}.T.A
0000024: 55 9b 83 36 c2 ad b5 2a a1 00 4b 66 4d 36 c0 23 0f f6  U..6...*..KfM6.#..
0000036: a5 d1 58 1b eb 20 94 c4 50 ed 7e d1 d7 92 76 88 57 ab  ..X.. ..P.~...v.W.
0000048: 99 c6 b0 9f 08 a6 14 6a 96 66 c4 9e be 50 3e 12 a1 f3  .......j.f...P>...
000005a: 86 4c 09 c5 7b 67 e5 f9 d2 28 2b ed 56 64 a0 e8 9b 83  .L..{g...(+.Vd....
000006c: d8 9f 3a 99 20 c4 85 95 51 66 36 4b 70 ac fc 74 69 cc  ..:. ...Qf6Kp..ti.
000007e: 56 f4 9c 88 d7 32 83 4f c6 a9 de 13 f4 4e 92 b9 1b 87  V....2.O.....N....
0000090: 89 e0 6d 24 0a 4f 33 a7 fe 40 26 e4 37 a3 ad 42 43 72  ..m$.O3..@&.7..BCr
00000a2: bd f0 3b 6f 11 9f 16 32 ed 04 eb a7 fc d9 8d 62 91 f7  ..;o...2.......b..
00000b4: dc 97 f0 6a 11 49 f6 1e b9 cb fc 7b dd 7c 41 e6 8b 56  ...j.I.....{.|A..V
00000c6: eb 70 47 a7 b6 f9 b3 3c d1 42 a2 fa 27 cc 49 ac 3e 89  .pG....<.B..'.I.>.
00000d8: 97 ff 2e 9c a4 7c 21 f1 0f                             .....|!..

Это не очень конкурентоспособно, но я просто не мог удержаться, чтобы опубликовать свой первый Bubblegum ответ на реальный .

Hexdump можно поменять местами xxd -r -c 18 > xml.bg.

Код полностью игнорирует ввод. Сжатие выполнено с помощью zopfli , который использует формат DEFLATE, но получает лучшее соотношение, чем (g) zip.

Спасибо @ Sp3000 за -2 байта!

Деннис
источник
9

sed, 449 байт

Предполагается, что sed будет работать с -nrпараметрами.

/\?|<p/d;:M
/<ma/{s/.*"(.*)".*/Q\1: X series/;/C/ s/X/1/;s/X/2/;H;d}
/<se/{s/.*"([^"]*)".*"([^"]*)".*/@\1!\2/;H;d}
/<mo/{
G;s/.*@(.*)*$/\1/;x;s/@(.*)*$//;x;:A N
/<\/m/!bA
s/\n/!/g;s/  +//g;s|<[/a-z]*>||g;s/(.*)!(.*)!(.*)!(.*)!(.*)!/%\1, \3 (\2-\4)@\1!\2/;H}
/<\/se/{x;s/\n*@.*$//;x}
$!{n;bM}
x;s/\n//g;s/Q(.*)Q(.*)%(.*)Q(.*)/\2\n  \3\n\4\n\1/
s/%(.*)%(.*)%(.*)\n(.*)%(.*)%(.*)%(.*)%(.*)%(.*)/\n  \3\n  \2\n  \1\n\4\n  \7\n  \9\n  \6\n  \5\n  \8/;p

Безголовая версия:

# Remove first 2 lines
/\?|<p/ d

:M
#manufacturer
/<ma/ {
    s/.*"(.*)".*/Q\1: X series/
    #Car corp
    /C/ s/X/1/
    #other
    s/X/2/
    H
    d
}

#series: store in hold buffer. (treating the hold buffer as a list, with @ as a delimeter)
/<se/{
    s/.*"([^"]*)".*"([^"]*)".*/@\1!\2/
    H
    d
}
/<mo/ {
    # pull series from hold buffer
    G
    s/.*@(.*)*$/\1/

    # remove series from hold buffer
    x
    s/@(.*)*$//
    x

    # Concatenate model into one line
    :A N
    /<\/m/ !{
        bA
    }
    s/\n/!/g

    # Remove junk
    s/  +//g
    s|<[/a-z]*>||g

    # Append formatted line to hold buffer, replace series at the end
    s/(.*)!(.*)!(.*)!(.*)!(.*)!/%\1, \3 (\2-\4)@\1!\2/
    H
}
/<\/se/ {
    #pop series name
    x
    s/\n*@.*$//
    x
}

$ ! {
    n
    b M
}
# end of loop

x
s/\n//g

# "sort"
s/Q(.*)Q(.*)%(.*)Q(.*)/\2\n  \3\n\4\n\1/
s/%(.*)%(.*)%(.*)\n(.*)%(.*)%(.*)%(.*)%(.*)%(.*)/\n  \3\n  \2\n  \1\n\4\n  \7\n  \9\n  \6\n  \5\n  \8/
p
луч
источник
1
Добро пожаловать в Программирование Пазлов и Code Golf!
Деннис
2

Баш, 388 368 365

base64 -d<<<H4sICKVS9FUCA2hlcmUAbVFBasMwELwH8oc92mBD5GNuqUogB9dQOw9QpDUWKFJYWS3t6yvJtI3T7k07szOzKy4IuKObIzFrZ/fAwCNp9NsN3APABVVw1ORnEFZBZ80HtE6hgYLz+ti15XbTo3QRGzCSWmHDKOQcCGkPzZ3q07oqOFg3T0hg8T1NXrNqbCAUwquxHoYyzR1WVcEw4XqkeK5f/mX27orgjIoeP8wuMv8EBbaO2ocbkkybn6wkVPoSTPBQ9Kw+ZaessPChaarlvXjE6GJUkZx63zv8Cp4vSG84aWkw650f8FcnFPDP+D0J5Q/ocnmWsR0rvwC2OTuexgEAAA==|zcat

Небольшой тест потому что:

$ bash ./go_procrastination.sh cars.xml
Car Corporation: 1 series
  Corporation Car, First and Only Model (CC-FOM)
Second Test Manufacturer: 2 series
  BBBBBBBBBBBBBBB, Another newest model here (asdf-TT)
  AAAAAAAAAAAAAA, The newest model (D-N)
  AAAAAAAAAAAAAA, Some older model (D-O)
Test Manufacturer 1: 2 series
  Supercar, Incredibulus (S1-I)
  Test series 22, Test model asdafds (Test-TT)
  Supercar, Ubervehicle (S1-U)
  Supercar, Road Czar (S1-C)
  Supercar, Model 1 (S1-01)
LukStorms
источник
1
Даже если вы настаиваете на том, чтобы избегать непечатных символов и предупреждений, это можно сделать намного короче. 1. Ваш сжатый файл содержит имя исходного файла car_manufacturer.txt. 2. Здесь строка будет на 3 байта короче. 3. Использование zopfli вместо vanilla gzip экономит еще 12 байтов.
Деннис
Спасибо за совет. Действительно, это сэкономило несколько байтов. Но чтобы не терять настроение, ленивость не поощряла установку zopfli или одной из программ сжатия данных PAQ. :)
LukStorms
1
Здесь строка это легкий гольф, хотя. Просто замените <<Lна <<<(base encoded stuff).
Деннис
И 3 байта побрился. Ницца.
LukStorms