Сколько символов на персонажа?


15

На http://shakespeare.mit.edu/ вы можете найти полный текст каждой пьесы Шекспира на одной странице (например, « Гамлет» ).

Напишите скрипт, который получает URL-адрес пьесы из stdin, такой как http://shakespeare.mit.edu/hamlet/full.html , и выводит количество текстовых символов, которые каждый игровой персонаж говорил с stdout, сортируя в соответствии с кем говорил больше всего.

Названия пьесы / сцены / акта, очевидно, не считаются ни диалогом, ни именами персонажей. Текст, выделенный курсивом и [ текст в квадратных скобках] не являются реальным диалогом, их не следует считать. Пробелы и другие знаки препинания в диалоге должны учитываться.

(Формат пьес выглядит очень согласованным, хотя я не посмотрел их все. Скажите, если я что-то упустил. Ваш сценарий не должен работать на стихи.)

пример

Вот смоделированный раздел из Много шума из ничего, чтобы показать, что я ожидаю для вывода:

Больше шума из ничего

Сцена 0.

посыльный

Я буду.

БЕАТРИС

Делать.

Леонато

Ты никогда не будешь.

БЕАТРИС

Нет.

Ожидаемый результат:

LEONATO 15
Messenger 7
BEATRICE 6

счет

Это код гольф. Победит самая маленькая программа в байтах.


8
Что если кто-то сделал этот вызов Шекспиру в Шекспире? Было бы удивительно, если бы это было даже возможно ...
fuandon

Можем ли мы предположить, что у нас есть список персонажей в игре? Или мы должны вывести символы из текста? Последнее очень сложно, учитывая, что некоторые символы (например, Messenger) имеют сочетание прописных и строчных букв. Другие имеют имена только с заглавными буквами (например, LEONATO); и некоторые из них являются составными именами.
DavidC

Да, вы должны вывести имена. Они отформатированы совсем не так, как диалоги, поэтому, учитывая различия между ними, HTML не должен быть слишком сложным.
Увлечения Кэлвина

1
Следует ли считать «Все» отдельным персонажем?
es1024

1
@ es1024 Да. Любой игровой персонаж с уникальным названием считается отдельным, даже если результат не совсем имеет смысла.
Увлечения Кэлвина

Ответы:


4

PHP (240 символов)

Делит HTML на строки (используя в качестве разделителя), затем запускает несколько регулярных выражений для извлечения произнесенных имен и слов. Сохраняет длину слов, произнесенных в массив. Golfed:

<?@$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";

Ungolfed:

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

Примечание: это считает «Все» отдельным символом.

Пример:

$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

1
Пожалуйста, покажите несколько примеров выходных данных.
DavidC

@DavidCarraher Пример был добавлен.
es1024

3

Реболь - 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]]

Вероятно, это может быть дальше, однако вряд ли получится получить ответ ниже, чем уже предоставлено :(

Ungolfed:

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

Эта программа удаляет [текст в квадратных скобках], а также удаляет окружающие пробелы из диалога. Без этого вывод идентичен ответу es1024 .

Пример:

$ 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

0

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

объяснение

Это слегка модифицированная версия, которая добавляет информацию о печати (см. Вставку).

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

Примечания

  • Я удаляю текст в квадратных скобках, а также вхождение «aside:», которого нет в скобках (я также обрезаю пробельные символы). Вот след выполнения с сопоставляемым текстом и суммой для каждого символа для Гамлета .

  • Как и другие ответы, All считается персонажем. Может быть заманчиво добавить значение all ко всем другим символам, но это будет неверно, поскольку «All» относится к символам, фактически присутствующим на сцене, что требует сохранения контекста присутствия (отслеживание «выхода») exeunt "и" введите "показания). Это не сделано.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.