Analyseur XML du programmeur paresseux

15

Contexte

Vous travaillez en tant que programmeur pour une entreprise de vente de voitures. Votre tâche pour cette semaine est de programmer un analyseur XML qui prend les données sur les modèles disponibles de différents constructeurs automobiles et jette des informations sur les nouveaux modèles. Heureusement pour vous, le département de test n'a fourni qu'un seul cas de test! Plus vite vous pouvez écrire du code qui le transmet, plus vous avez de temps pour la procrastination pendant le reste de la semaine.

Contribution

Votre entrée est exactement ce morceau de données XML, fourni par le service de test. Il contient des données sur certains constructeurs automobiles, leurs séries de voitures et les modèles de ces séries. Vous pouvez supposer une nouvelle ligne de fin.

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

Production

Votre sortie est cette chaîne. Il répertorie les constructeurs automobiles par ordre alphabétique, suivi par deux points et le nombre de séries qu'ils font. Sous chaque fabricant, il répertorie le nom de la série, le nom du modèle et le code de chacun de leurs modèles, en commençant par le plus récent et en reculant par année. Les espaces de fin et les sauts de ligne sont acceptables, tant que votre sortie ressemble à ceci lors de l'impression.

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)

Règles et notation

Vous pouvez écrire soit une fonction soit un programme complet. Le nombre d'octets le plus bas gagne et les failles standard sont interdites.

Notez que l'entrée est fixe: vous n'avez pas besoin de prendre en charge d'autres entrées que celle indiquée ici. Votre programme est autorisé à retourner des bêtises ou même à planter si l'entrée est modifiée de quelque manière que ce soit. Vous pouvez également ignorer l'entrée et coder en dur la sortie, si vous le souhaitez. Cependant, vous ne pouvez pas utiliser de bibliothèques d'analyseurs XML ou HTML intégrées.

Zgarb
la source
Un analyseur HTML serait-il autorisé ou cela irait-il à l'encontre des règles?
Downgoat
11
Je ne veux jamais acheter une voiture de cette entreprise.
kirbyfan64sos
1
@vihan Je déciderai (plutôt arbitrairement) que les analyseurs HTML ne sont pas autorisés non plus, car les deux formats sont très similaires.
Zgarb
Et XSLT? ;)
Beta Decay
@BetaDecay Je vais autoriser XSLT à titre d'exception, car il serait probablement très fastidieux et ennuyeux de ne pas utiliser les opérations d'analyse XML dans ce langage. : P Et il ne sera pas en concurrence avec la réponse CJam de toute façon.
Zgarb

Réponses:

8

CJam, 109 107 octets

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

Notez que quatre des caractères de la chaîne au début ne sont pas imprimables.

Essayez-le en ligne dans l' interpréteur CJam .

Idée

Il s'agit essentiellement d'un code dur qui divise l'entrée à toutes les occurrences de < , > et " , sélectionne des morceaux spécifiques et les entrelace avec les parties restantes de la sortie.

Après avoir divisé l'entrée, les morceaux aux indices 110 , 114 et 122 sont Car Corporation , Corporation Car et First and Only Model . Les codes de série et de nom se trouvent aux index 116 et 126, qui peuvent être calculés en ajoutant 2 et 4 aux index des noms. Enfin, le nombre de séries est la longueur de la chaîne Car Corporation divisée par 9 (évidemment).

Ainsi, nous encodons la partie de la sortie qui correspond à ce fabricant comme [114 122 110]ou plutôt la chaîne "rzn".

Code

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.
}
Dennis
la source
10

Bubblegum , 227 225 octets

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                             .....|!..

Ce n'est pas très compétitif, mais je n'ai pas pu résister à poster ma première réponse Bubblegum à un véritable .

Le vidage hexadécimal peut être inversé avec xxd -r -c 18 > xml.bg.

Le code ignore complètement l'entrée. La compression a été effectuée avec zopfli , qui utilise le format DEFLATE mais obtient un meilleur rapport que (g) zip.

Merci à @ Sp3000 pour -2 octets!

Dennis
la source
9

sed, 449 octets

Suppose que sed doit être exécuté avec les -nroptions.

/\?|<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

Version non golfée:

# 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
Rayon
la source
1
Bienvenue sur Programmation Puzzles & Code Golf!
Dennis
2

Bash, 388 368 365

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

Petit test car:

$ 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
la source
1
Même si vous insistez pour éviter les caractères et les avertissements non imprimables, cela peut être beaucoup plus court. 1. Votre fichier compressé contient le nom du fichier d' origine, car_manufacturer.txt. 2. Une chaîne ici serait plus courte de 3 octets. 3. L'utilisation de zopfli au lieu de gzip vanilla permet d'économiser 12 octets supplémentaires.
Dennis
Merci pour le conseil. En effet, cela a permis d'économiser quelques octets. Mais pour rester dans l'ambiance du défi, la paresse a découragé d'installer zopfli ou l'un des programmes de compression de données PAQ. :)
LukStorms
1
La chaîne ici est un golf facile. Remplacez simplement <<Lpar <<<(base encoded stuff).
Dennis
Et 3 octets rasés. Agréable.
LukStorms du