Combien de personnages par personnage?

15

Sur http://shakespeare.mit.edu/, vous pouvez trouver le texte intégral de chacune des pièces de Shakespeare sur une seule page (par exemple Hamlet ).

Écrivez un script qui reprend l'url d'une pièce de stdin, tel que http://shakespeare.mit.edu/hamlet/full.html , et génère le nombre de caractères de texte que chaque personnage de jeu a parlé à stdout, triés en fonction de qui parlait le plus.

Les titres de jeu / scène / acte ne comptent évidemment pas comme des dialogues, pas plus que les noms des personnages. Le texte en italique et le [texte entre crochets] ne sont pas de véritables dialogues, ils ne doivent pas être comptés. Les espaces et autres signes de ponctuation dans le dialogue doivent être comptés.

(Le format des pièces semble très cohérent même si je ne les ai pas toutes regardées. Dites-moi si j'ai oublié quelque chose. Votre script n'a pas à fonctionner pour les poèmes.)

Exemple

Voici une section simulée de Much Ado About Nothing pour montrer ce que j'attends pour la sortie:

Plus de bruit pour rien

Scène 0.

Messager

Je vais.

BEATRICE

Faire.

LEONATO

Vous ne le ferez jamais.

BEATRICE

Non.

Production attendue:

LEONATO 15
Messenger 7
BEATRICE 6

Notation

C'est le golf de code. Le plus petit programme en octets gagnera.

Loisirs de Calvin
la source
8
Et si quelqu'un faisait ce défi de Shakespeare à Shakespeare? Ce serait étonnant si c'était même possible ...
fuandon
Pouvons-nous supposer que nous avons une liste des personnages de la pièce? Ou faut-il déduire les caractères du texte? Ce dernier est très difficile étant donné que certains caractères (par exemple Messenger) ont un mélange de lettres majuscules et minuscules. D'autres ont des noms avec uniquement des lettres majuscules (par exemple LEONATO); et certains d'entre eux sont des noms composés.
DavidC
Oui, vous devez déduire les noms. Ils sont formatés très différemment du dialogue, donc étant donné le html, les différencier ne devrait pas être trop compliqué.
Calvin's Hobbies
1
Faut-il considérer «Tous» comme un caractère distinct?
es1024
1
@ es1024 Oui. Tout personnage de jeu avec un titre unique est considéré comme séparé, même si le résultat n'a pas vraiment de sens.
Calvin's Hobbies

Réponses:

4

PHP (240 caractères)

Divise le html en chaînes (en utilisant comme délimiteur), puis exécute quelques expressions régulières pour extraire le nom et les mots prononcés. Enregistre la longueur des mots prononcés dans le tableau. Golfé:

<?@$p=preg_match_all;foreach(explode('/bl',implode(file(trim(fgets(STDIN)))))as$c)if($p('/=s.*?b>(.*?):?</',$c,$m)){$p('/=\d.*?>(.*?)</',$c,$o);foreach($m[1]as$n)@$q[$n]+=strlen(implode($o[1]));}arsort($q);foreach($q as$n=>$c)echo"$n $c\n";

Non golfé:

<?php
$html = implode(file(trim(fgets(STDIN))));
$arr = explode('/bl',$html);
foreach($arr as $chunk){
    if(preg_match_all('/=s.*?b>(.*?):?</',$chunk,$matches)){
        $name = $matches[1];
        preg_match_all('/=\d.*?>(.*?)</',$chunk,$matches);
        foreach($name as $n)
            @$names[$n] += strlen(implode($matches[1]));
    }
}
arsort($names);
foreach($names as $name=>$count)
    echo "$name $count\n";

Remarque: Cela considère «Tous» comme un caractère distinct.

Exemple:

$php shakespeare.php <<< "http://shakespeare.mit.edu/hamlet/full.html"
HAMLET 60063
KING CLAUDIUS 21461
LORD POLONIUS 13877
HORATIO 10605
LAERTES 7519
OPHELIA 5916
QUEEN GERTRUDE 5554
First Clown 3701
ROSENCRANTZ 3635
Ghost 3619
MARCELLUS 2350
First Player 1980
OSRIC 1943
Player King 1849
GUILDENSTERN 1747
Player Queen 1220
BERNARDO 1153
Gentleman 978
PRINCE FORTINBRAS 971
VOLTIMAND 896
Second Clown 511
First Priest 499
Captain 400
Lord 338
REYNALDO 330
FRANCISCO 287
LUCIANUS 272
First Ambassador 230
First Sailor 187
Messenger 185
Prologue 94
All 94
Danes 75
Servant 49
CORNELIUS 45
es1024
la source
1
Veuillez montrer quelques exemples de sortie.
DavidC
@DavidCarraher Un exemple a été ajouté.
es1024
3

Rebol - 556 527

t: complement charset"<"d: charset"0123456789."m: map[]parse to-string read to-url input[any[(s: 0 a: copy[])some["<A NAME=speech"some d"><b>"copy n some t</b></a>(append a trim/with n":")some newline]<blockquote>newline any["<A NAME="some d">"copy q some t</a><br>newline(while[f: find q"["][q: remove/part f next find f"]"]s: s + length? trim head q)|<p><i>some t</i></p>newline][</blockquote>|</body>](foreach n a[m/:n: either none? m/:n[s][s + m/:n]])| skip]]foreach[x y]sort/reverse/skip/compare to-block m 2 2[print[x y]]

Cela pourrait probablement être approfondi, mais il est peu probable qu'il tombe en dessous des réponses déjà fournies :(

Non golfé:

t: complement charset "<"
d: charset "0123456789."
m: map []

parse to-string read to-url input [
    any [
        (s: 0 a: copy [])

        some [
            "<A NAME=speech" some d "><b>" copy n some t </b></a>
            (append a trim/with n ":")
            some newline
        ]

        <blockquote> newline
        any [
            "<A NAME=" some d ">" copy q some t </a><br> newline (
                while [f: find q "["] [
                    q: remove/part f next find f "]"
                ]
                s: s + length? trim head q
            )
            | <p><i> some t </i></p> newline
        ]
        [</blockquote> | </body>]
        (foreach n a [m/:n: either none? m/:n [s] [s + m/:n]])

        | skip
    ]
]

foreach [x y] sort/reverse/skip/compare to-block m 2 2 [print [x y]]

Ce programme supprime [texte entre crochets] et coupe également les espaces environnants du dialogue. Sans cela, la sortie est identique à la réponse es1024 .

Exemple:

$ rebol -q shakespeare.reb <<< "http://shakespeare.mit.edu/hamlet/full.html"
HAMLET 59796
KING CLAUDIUS 21343
LORD POLONIUS 13685
HORATIO 10495
LAERTES 7402
OPHELIA 5856
QUEEN GERTRUDE 5464
First Clown 3687
ROSENCRANTZ 3585
Ghost 3556
MARCELLUS 2259
First Player 1980
OSRIC 1925
Player King 1843
GUILDENSTERN 1719
Player Queen 1211
BERNARDO 1135
Gentleman 978
PRINCE FORTINBRAS 953
VOLTIMAND 896
Second Clown 511
First Priest 499
Captain 400
Lord 338
REYNALDO 312
FRANCISCO 287
LUCIANUS 269
First Ambassador 230
First Sailor 187
Messenger 185
Prologue 89
All 76
Danes 51
Servant 49
CORNELIUS 45
draegtun
la source
0

Lisp commun - 528

(use-package :plump)(lambda c(u &aux(h (make-hash-table))n r p)(traverse(parse(drakma:http-request u))(lambda(x &aux y)(case p(0(when(and n(not(ppcre:scan"speech"(attribute x"NAME"))))(setf r t y(#1=ppcre:regex-replace-all"aside: "(#1#"^(\\[[^]]*\\] |\\s*)"(text x)"")""))(dolist(w n)(incf(gethash w h 0)(length y)))))(1(if r(setf n()r()))(push(intern(text(aref(children x)0)))n)))):test(lambda(x)(and(element-p x)(setf p(position(tag-name x)'("A""b"):test #'string=)))))(format t"~{~a ~a~^~%~}"(alexandria:hash-table-plist h)))

Explication

Il s'agit d'une version légèrement modifiée qui ajoute des informations d'impression (voir coller).

(defun c (u &aux
                 (h (make-hash-table)) ;; hash-table
                 n ;; last seen character name
                 r p
                 )
      (traverse                 ;; traverse the DOM generated by ...
       (parse                   ;; ... parsing the text string
        (drakma:http-request u) ;; ... resulting from http-request to link U
        )

       ;; call the function held in variable f for each traversed element
       (lambda (x &aux y)
         (case p
           (0 ;a
            (when(and n(not(alexandria:starts-with-subseq"speech"(attribute x "NAME"))))
              (setf r t)
              (setf y(#1=ppcre:regex-replace-all"aside: "(#1#"^(\\[[^]]*\\] |\\s*)"(text x)"")""))
              (format t "~A ~S~%" n y) ;; debugging
              (dolist(w n)
                (incf
                    (gethash w h 0) ;; get values in hash, with default value 0
                    (length y)))) ;; length of text
            )
           (1 ;b
            (if r(setf n()r()))
            (push (intern (text (aref (children x)0)))n))))

       ;; but only for elements that satisfy the test predicate
       :test
       (lambda(x)
         (and (element-p x) ;; must be an element node
              (setf p(position(tag-name x)'("A""b"):test #'string=)) ;; either <a> or <b>; save result of "position" in p
              )))

        ;; finally, iterate over the elements of the hash table, as a
        ;; plist, i.e. a list of alternating key values (k1 v1 k2 v2 ...),
        ;; and print them as requested. ~{ ~} is an iteration control format.
  (format t "~&~%~%TOTAL:~%~%~{~a ~a~^~%~}" (alexandria:hash-table-plist h)))

Remarques

  • Je supprime le texte entre crochets ainsi que l'occurrence «côté:» qui n'est pas présente entre crochets (je coupe également les espaces). Voici une trace d'exécution avec le texte mis en correspondance et le total pour chaque personnage, pour Hamlet .

  • Comme d'autres réponses, All est supposé être un personnage. Il pourrait être tentant d'ajouter la valeur de tous à tous les autres personnages, mais ce serait incorrect car "Tous" fait référence aux personnages réellement présents sur scène, ce qui nécessite de garder un contexte de qui est présent (suivi de "sortie" "exeunt "et" enter "). Ce n'est pas fait.

coredump
la source