Википедия: Философия!


26

Как многие гики могут знать, большинство страниц (я думаю, 95%) википедии в конечном итоге ведут к философии, например так:

Нажмите на первую не курсивную или в скобках ссылку, которая относится к другой обычной статье: (т.е. не File: или Special:, но такие вещи, как Wikipedia: все в порядке), и повторяйте эту ссылку, пока не дойдете до философии.

Сценарий должен:

  • Возьмите первую страницу в качестве ввода
  • Напечатайте название каждой статьи, к которой оно относится
  • И напечатать, сколько статей потребовалось, чтобы добраться до Философии, и если это не так.

Вы начинаете с 1000 очков и теряете по одному за каждого персонажа в коде. Бонусные очки за:

Обнаружение зацикливания статей и остановка: +50

Обнаружение зацикливания статей и запрос на переход пользователя к следующей ссылке на статью: +170

Разрешение по умолчанию для первой проверки в качестве аргумента командной строки или аналогичного: +140

Самый высокий балл выигрывает.


7
+1, отличный вызов! Это обнаружение скобок трудно: P
дверная ручка

1
У меня такое ощущение, что это могло бы использовать какое-то лучшее определение, но я пока точно не знаю, как именно так.
Изи

3
Потерять одно очко за каждый набранный символ. Хм. Отлично, я понял, я просто скопирую и вставлю символы! Нет потерянных очков!
Джастин

5
Пожалуйста, не меняйте правила после того, как ответы уже опубликованы; это довольно грубо и обычно осуждается в сообществе здесь ...
Дверная ручка

Ответы:


8

Рубин, 1000 - 303 299 337 - 50 373 - 170 382 - 170 - 140 379 - 170 - 140 символов = 697 701 713 797 928 931

Я уверен, что есть много улучшений.

(Это требует Нокогири)

require'open-uri'
require'nokogiri'
x="/wiki/"+gets.chomp
r=[n=i=0]
until x=~/\/Philosophy/
d=Nokogiri.HTML open"http://en.wikipedia.org#{x}"
x=d.css('p a').select{|a|t=a.xpath('preceding::text()').map(&:text)*'';t.count('(')==t.count(')')&&a.attr('href')=~/^.wiki[^:]+$/}[i].attr'href'
i=0
puts r.index(x)?"#{$><<'i=';i=($*[0]||gets).to_i;''}": r.push(x)[-1][6..-1]
n+=1
end
p n

Пример выполнения:

c:\a\ruby>wikipedia_crawl_philosophy
Latin (note: this is my input)
Classical_antiquity
History
Umbrella_term
Terminology
Word
Linguistics
Science
Knowledge
Fact
Proof_(truth)
Argument
Logic
Reasoning
Consciousness
Quality_(philosophy)
Property_(philosophy)
Modern_philosophy
Philosophy
18

Пример того, где я должен был перейти на другую ссылку

c:\a\ruby>wikipedia_crawl_philosophy
Snow
Precipitation_(meteorology)
Meteorology
Atmospheric_physics
Synoptic_scale_meteorology
i=2 // I put the 0-indexed number of the link I wanted to go to (so, the third link)

Weather
Atmosphere
Gas
State_of_matter#The_four_fundamental_states
Physics
Natural_science
Sciences
Knowledge
Fact
Proof_(truth)
Argument
Logic
Reasoning
Consciousness
Quality_(philosophy)
Property_(philosophy)
Modern_philosophy
Philosophy
25

Трюки, которые я использовал:

  • Я использовал селектор p aтолько для получения не курсивных ссылок, потому что все ссылки в реальной статье, которые не являются курсивом, всегда находятся в элементах абзаца в Википедии.

хммм ... может быть, я должен запретить любые, кроме библиотек, которые поставляются с языком ...
AlphaModder

@ user1825860 На самом деле это не библиотека, которая поставляется с языком; это драгоценный камень. Я отредактировал свой ответ. Но на самом деле, вы хотите принять этот и без того сложный вызов и заставить нас не использовать библиотеки HTML для разбора? : P
Дверная ручка

я не запрещаю это, но вы теряете очки: P
AlphaModder

Вы должны перечитать первый пост и отредактировать соответственно: P
AlphaModder

2
@ user1825860 Пожалуйста, не меняйте правила после того, как ответы уже опубликованы; это довольно грубо ...
Дверная ручка

5

«BASH » - (Если не ошибаюсь: 1000 - 397 + 170 + 140 = 913 баллов)
«BASH» - (Если не ошибаюсь: 1000 - 386 + 170 + 140 = 924 балла)

"BASH" - (Если не ошибаюсь: 1000 - 381 + 170 + 140 = 929 баллов)

BASH специально указан в кавычках, поскольку представляет собой набор инструментов, используемых в оболочках * nix, но заключенных в сценарий bash.

Изменить 1:

  • Удалено http://по curlумолчанию для этого.
  • Изменено href=соответствие для якорей, так f=как <a>оно не имеет других нормальных атрибутов, заканчивающихся на f. (Это возможность пользовательских тегов. Пока не видел.)
  • Установить сообщение о выходе не найдено !Philвместо NoPhil. Это один немного изворотливый , как можно было бы также сказать , например !, 0, N, !Pили аналогичный.
  • Куирк два: -sна curlможет быть удален , чтобы уменьшить еще три байта, но это дало бы грязный выход. Не уверен, что это проблема.
  • Обновленная справка на этой странице.

Используя причуды, код получился бы в 379 байтах, 931 балле.

Я также мог бы реализовать @plannapus с использованием соответствующего (надеюсь) навигационного блока , добавив (p|ul).*?<(\1)добавление шести байтов (вычитая шесть точек).

Изменить 2:

Используется ${#c[@]}для печати степеней разделения вместо $iсчетчика.

Используя причуды, код получился бы в 374 байтах, 936 пунктах.


Я вызываю Ктулху и выбираю решение regexp + bash / shell / * nix.

Stolen:

Реализовано:

  • Определите цикл и спросите, нужно ли брать следующую ссылку.
  • При желании выберите следующую ссылку на дубликат в качестве опции.

Требования:

  • bash v.?
  • grepс поддержкой -P(PCRE).
  • sed
  • curl
  • cut

Использование:

script PATH [OPTIONS]

Print separation of article from ``PATH'' to ``Philosophy'' on Wikipedia.
Degrees of separation, if found, is printed as last line. 
If not found last line yields ``!Phil''.

PATH    
     Absolute path to starting article, e.g: /wiki/Word 
OPTIONS
     y   Automatically select next link if already visited.
     n   (Or other) Quit if next link already visited.
BUGS
     1. On previous visit; "next link" is not checked. Thus if next link
     has already been visited we get eternal loop. Not sure if this
     disqualify +170 points.
     2. Sure there are.

Встроенный код Скопировать в файл. chmod +x filename, Запустите ./script /wiki/…из оболочки Bash.

u=($1);c=($1);while ! [[ "$u" =~ /Philosophy$ ]];do echo "$u";u=($(curl -s "en.wikipedia.org$u"|tr '\n' ' '|grep -Po '<p>.*?</p>'|sed 's/>[^<]*([^)]*)//g'|grep -o '<a [^>]*f="/wiki/[^":]*"'|cut -d\" -f2));for x in "${c[@]}";do if [ "$x" = "$u" ];then [ $2 ] &&s=$2||read -p "${u[0]}?" s;[ $s = y ] &&u[0]=${u[1]}||{ echo "!Phil";exit;} fi;done;c=("${c[@]}" "$u");done;echo ${#c[@]};

Расширенный и объясненный код:

u=($1); # Array of paths.
c=($1); # Array of visited paths.
# While $u != /Philosophy, ugly trick is to use $u instead of ${u[0]}.
while ! [[ "$u" =~ /Philosophy$ ]];do   
        echo "$u";      # Print current page.
        # curl   : prints retreived page to stdout. "-s" could be skipped.
        # tr     : replace all newline with space. This is a ®sanity thing when it comes to 
        #          twidling with html using regex.
        # grep 1 : match <p> tags. Using -P's ungreedy *?.
        # sed    : remove all occurences of "(" something ")".
        # grep 2 : match links where "href" attribute starts with /wiki/ and is not e.g. File:
        # cut    : match actual href value.
        # Result is added to array ``u''.
        u=($(curl -s "en.wikipedia.org$u" |
                tr '\n' ' ' | 
                grep -Po '<p>.*?</p>' | 
                sed 's/>[^<]*([^)]*)//g' | 
                grep -o '<a [^>]*f="/wiki/[^":]*"' | 
                cut -d\" -f2));

        # For previously visited pages as x.
        for x in "${c[@]}"; do 
                # If x equals to first page ...
                if [ "$x" = "$u" ]; then        
                        # Use option or ask.
                        [ $2 ] && s=$2 || read -p "${u[0]}?" s; 
                        # If response is "y" use next link, else exit with status.
                        [ $s = y ] && u[0]=${u[1]} || { 
                                echo "!Phil"; 
                                exit;
                        } 
                fi;
        done;
        # Append current link to "visited"
        c=("${c[@]}" "$u"); 
done;
# Print number of visited pages.
echo ${#c[@]}

Черт возьми, ты побил меня на одно очко! : P Я собираюсь
сыграть

Ye;), но не уверен, что это правильный код. Используя инструменты таким образом.
Runium

5

JavaScript 726 (444 символа [556] + 170)

Теперь я ценю, что это может быть недействительным как букмарклет, но я все равно с удовольствием возился с ним.

Использование: перейдите на страницу, с которой вы хотите начать, и запустите в консоли следующее:

(function(a){c=0,o="";$(u="html")[u](f=$('<iframe src="'+location+'?">').on("load",function(){$=f.contentWindow.$;p=f.contentDocument.title[s="split"](" - ")[0];c++;p=="Philosophy"?document.write("<pre>"+o+p+"\n"+c):(i=RegExp("^"+p+"$","m").test(o)?a||confirm("Loop, try next?")?2:0:1)&&(f.src=$("p>a").filter(function(){return(t=$(this).parent()[u]()[s](this.outerHTML)[0])[s]("(").length==t[s](")").length})[--i].href);o+=p+"\n"})[0])})(true)

Для JavaScript вывод выглядит следующим образом:

JavaScript
Interpreter (computing)
Computer science
Science
Knowledge
Fact
Proof (truth)
Argument
Logic
Reason
Consciousness
Quality (philosophy)
Property (philosophy)
Modern philosophy
Philosophy
15

В этом решении предполагается, что вы хотите перейти к следующей ссылке в обнаруживаемом цикле, но если вы trueв конце falseизмените на нее, вместо этого появится всплывающее окно подтверждения (довольно раздражающее ...), не уверенное, подходит ли это для вторичный бонус или нет. Я предполагаю, что нет.

Отступ:

(function(l){
    c=0,o='';
    $(u='html')[u](f=$('<iframe src="'+location+'?">').on('load',function(){ // Firefox needs the ? to properly load the frame
        $=f.contentWindow.$; // reference repeated calls as strings to save more bytes
        p=f.contentDocument.title[s='split'](' - ')[0]; // get the title

        c++;
        p=='Philosophy'?
            document.write('<pre>'+o+p+'\n'+c): // pre for nice formatting
            (i=RegExp('^'+p+'$','m').test(o)?
                l||confirm('Loop, try next?')?
                    2: // desired index + 1 so we can use as a boolean
                    0
                :
                1)&&
            (f.src=$('p>a').filter(function(){
                return (t=$(this).parent()[u]()[s](this.outerHTML)[0])[s]('(').length == t[s](')').length // shorter, but still not overly happy with this...
            })[--i].href);
            o+=p+'\n' // update output
    })[0])
})(true) // change this to show confirm box when loop detected

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

Работает как в Chrome, так и в Firefox (протестировано в Firefox 26)


2
Выглядит потрясающе, но терпит неудачу в Firefox 20.
Boothby

Argghh! Я только тестировал Chrome. Я посмотрю на это!
Дом Гастингс

@boothby Должен работать в Firefox сейчас ... Все еще хочу работать над ссылками, которые я выбираю, хотя!
Дом Гастингс

5

C # - 813 символов

Оценка: 1000-813 + 50 + 170 + 140 = 547 :(

Нет внешних библиотек. Обнаружение петли .

Первый аргумент - исходная статья, второй - целевая статья.

Гольф версия:

class Program
{
    static void Main(string[] a)
    {
        Func<XmlDocument,IList<string>> G=delegate(XmlDocument xd){return xd.SelectNodes("//p//a[starts-with(@href,'/wiki/') and not(contains(@href,':'))]").Cast<XmlNode>().Select(n=>n.Attributes["href"].InnerText).ToList();};Action<string> W=delegate(string s){Console.WriteLine(s);};var h=new HashSet<string>();var c=new WebClient();var x=new XmlDocument();var t=c.DownloadString(@"http://wikipedia.org/wiki/"+a[0]);int i=0,C=0;
    GO:
        x.LoadXml(t);var ns=G(x);
    COL:
        var f=ns[i];if(f.Equals("/wiki/"+a[1],StringComparison.OrdinalIgnoreCase)){goto END;}if(h.Contains(f)){W("loop: "+f);i++;goto COL;}else{h.Add(f);i=0;C++;}W(f);t=c.DownloadString(@"http://wikipedia.org"+f);goto GO;
    END:
        W("Found in "+C);
    }
}

Разумная версия:

class Program
{
    // arg[0] source article. arg[1] target article
    static void Main(string[] arg)
    {
        Func<XmlDocument, IList<string>> G = delegate(XmlDocument xd)
        {
            return xd.SelectNodes("//p//a[starts-with(@href,'/wiki/') and not(contains(@href,':'))]").Cast<XmlNode>().Select(n => n.Attributes["href"].InnerText).ToList();
        };
        Action<string> W = delegate(string s) { Console.WriteLine(s); };
        var h = new HashSet<string>(); var c = new WebClient(); var x = new XmlDocument();
        var allText = c.DownloadString(@"http://wikipedia.org/wiki/" + arg[0]);
        int i = 0; int C = 0;
    GO:
        x.LoadXml(allText);
        var ns = G(x);
    COL:
        var f = ns[i];
        if (f.Equals("/wiki/" + arg[1], StringComparison.OrdinalIgnoreCase))
        {
            goto END;
        }
        if (h.Contains(f))
        {
            W("loop: " + f); i++; goto COL;
        }
        else
        {
            h.Add(f); i = 0; C++;
        }
        W(f);
        allText = c.DownloadString(@"http://wikipedia.org" + f);
        goto GO;
    END:
        W("Found in " + C);
    }
}

Пример прогона от «Скай» до «Философия»:

C:\>wiki.exe Sky Philosophy

/wiki/Earth
/wiki/Geometric_albedo
/wiki/Phase_angle_(astronomy)
/wiki/Observational_astronomy
/wiki/Astronomy
/wiki/Natural_science
/wiki/Sciences
/wiki/Latin_language
/wiki/Classical_antiquity
/wiki/History
/wiki/Ancient_Greek
/wiki/Greek_language
/wiki/Modern_Greek
loop: /wiki/Greek_language
/wiki/Colloquialism
/wiki/Word
/wiki/Linguistics
/wiki/Science
loop: /wiki/Latin_language
/wiki/Knowledge
/wiki/Fact
/wiki/Latin
loop: /wiki/Classical_antiquity
/wiki/Italic_languages
/wiki/Indo-European_languages
/wiki/Language_family
/wiki/Language
/wiki/Human
/wiki/Extinct
/wiki/Biology
loop: /wiki/Natural_science
/wiki/Life
loop: /wiki/Earth
/wiki/Physical_body
/wiki/Physics
loop: /wiki/Greek_language
loop: /wiki/Natural_science
/wiki/Matter
/wiki/Rest_mass
/wiki/Center_of_momentum_frame
loop: /wiki/Physics
/wiki/Inertial_frame
loop: /wiki/Physics
/wiki/Frame_of_reference
loop: /wiki/Physics
/wiki/Coordinate_system
/wiki/Geometry
loop: /wiki/Ancient_Greek
/wiki/Mathematics
/wiki/Quantity
/wiki/Property_(philosophy)
/wiki/Modern_philosophy
Found in 41

C:\>

5

Скала (294 символа => 1000-294 + 140 = 846 баллов)

Обновленное решение, которое автоматически берет следующую ссылку, если она уже была использована. Спасибо за 140 бонусных баллов.

Логика: выберите первую ссылку "/ wiki", в которой нет символа ":" (поэтому она игнорирует ссылки "File:"). Промойте и повторите с рекурсией, возвращая счетчик + 1 каждый раз. Я держу список всех предыдущих выводов под рукой, чтобы программа не входила в бесконечный цикл.

Регулярное выражение: у меня есть 2 формы регулярного выражения.

  • "<p>.*?\"/wiki/([^:]*?)\".*?/p>"который находит ссылки в <p>тегах
  • "p>.*?/wiki/([^:]*?)\""Это немного более экспериментальный тег, который доказал свою работоспособность, но дает другие результаты, потому что иногда он выбирает ссылки с правой панели информации. Это регулярные статьи, поэтому я считаю, что это все еще актуально. Если будет объявлено, что это не так, ОП (или кто-то еще) может оставить мне комментарий, и я смогу обновить свое решение до лучшего уровня.

Я собираюсь использовать второе регулярное выражение до тех пор, пока не найду тестовый пример, где он не работает или OP не упоминает, что поиск ссылок из боковой панели не разрешен (по моему мнению, информационные панели все еще являются частью сама статья; больше резюме).


Минифицированный источник:

object W extends App{print(x(Seq(args(0))));def x(s:Seq[Any]):Int={val? =s.last;println(?);?match{case "Philosophy"=>1;case _=>x(s:+"p>.*?/wiki/([^:]*?)\".*?/p>".r.findAllMatchIn(io.Source.fromURL("http://en.wikipedia.org/wiki/"+ ?).getLines.mkString).map(_ group 1).filter(!s.contains(_)).next)+1}}}

Читаемый Источник:

object W extends App {
  print(x(Seq(args(0))))

  def x(s: Seq[Any]): Int = {
    val ? = s.last
    println(?)
    ? match {
      case "Philosophy" => 1
      case _ => x(s :+ "p>.*?/wiki/([^:]*?)\"".r.findAllMatchIn(io.Source.fromURL("http://en.wikipedia.org/wiki/" + ?).getLines.mkString).map(_ group 1).filter(!s.contains(_)).next) + 1
    }
  }
}

Пример вывода:

вход

Space_toilet

Выход

Space_toilet
Weightlessness
G-force
Weight
Force
SI_unit
French_language
Second_language
Language_acquisition
Word
Linguistics
Science
Latin_language
Pontifical_Academy_for_Latin
Pope_Benedict_XVI
Pope_Benedict_(disambiguation)
Regnal_name#Catholic_Church
Monarch
State_(polity)
Community
Commutative_property
Mathematics
Quantity
Property_(philosophy)
Modern_philosophy
Philosophy
26

1
Scala не требует основного объекта или метода. Вы можете запустить его с интерпретатором как «scala <filename> [args ..]». Используйте, args(0)чтобы получить первый аргумент, избавиться от своего objectи mainопределения, и я думаю, что вы можете удалить :Intтоже. pastebin.com/YqywKcG8
KChaloux

Оказывается, вы не можете удалить : Int. Не понял, что вы делаете рекурсивный вызов. Также мой pastebin был взят из вашего старого читаемого источника, но применяются те же понятия.
KChaloux

Я попробую избавиться от основного метода. И да, рекурсивные вызовы заставили меня добавить :Intтуда. Позже сегодня я также добавлю удобочитаемую форму имеющегося у меня решения на 333 символа. Спасибо за предложения @KChaloux
javatarz

1
Как я уже сказал, ссылка на object Q extends App { ... }абсолютно ненужна, если вы запускаете код с интерпретатором, а не компилируете с помощью scalac. Просто беги сscala <filename> [args..]
KChaloux

4

R 379 символов; 1000-379 + 170 = 791 баллов

Версия, которая спрашивает пользователей, как действовать при обнаружении зацикливания

library(XML);w="http://en.wikipedia.org";W="/wiki/";n=1;A=c(scan(,""));while(A[n]!="Philosophy"){a=paste0(w,W,A[n]);d=sapply(strsplit(grep(W,sapply(xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),`[`,'href'),v=T),"/"),`[`,3);B=d[-grep(":",d)];n=n+1;if(B[1]%in%A)if(readline("Loop!2nd link?")=="n")break;A[n]=head(B[!B%in%A],1);cat(A[n],"\n")};cat(n-1)

С отступами и комментариями:

library(XML) #Uses package XML
w="http://en.wikipedia.org"
W="/wiki/"
n=1
A=c(scan(,"")) #Stdin + makes it a vector so we can store each iteration
while(A[n]!="Philosophy"){
    a=paste0(w,W,A[n])
    d=sapply(strsplit(grep(W,sapply( #The heart of the program
             xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),
             `[`,'href'),v=T),"/"),`[`,3)
    B=d[-grep(":",d)] #get rid of Templates, Files ,etc...
    n=n+1
    #Ask user if should proceed when loop encountered 
    #(any answer other than "n" is considered agreement):
    if(B[1]%in%A)if(readline("Loop!2nd link?")=="n")break
    A[n]=head(B[!B%in%A],1) #Take the first link that is not redundant
    cat(A[n],"\n")
    }
cat(n-1)

Пример выполнения:

> library(XML);w="http://en.wikipedia.org";W="/wiki/";n=1;A=c(scan(,""));while(A[n]!="Philosophy"){a=paste(w,W,A[n],sep="");d=sapply(strsplit(grep(W,sapply(xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),`[`,'href'),v=T),"/"),`[`,3);B=d[-grep(":",d)];n=n+1;if(B[1]%in%A)if(readline("Loop!2nd link?")=="n")break;A[n]=head(B[!B%in%A],1);cat(A[n],"\n")};cat(n-1)
1: Extended_ASCII
2: 
Read 1 item
Eight-bit 
Computer_architecture 
Computer_science 
Science 
Logic 
List_of_aestheticians 
Art 
Human_behavior 
Behavior 
Organism 
Biology 
Loop!2nd link?y
Mathematics 
Quantity 
Property_(philosophy) 
Modern_philosophy 
Philosophy 
16

R 325 знаков; ??? точки

Версия, которая по умолчанию принимает первую не избыточную ссылку (т.е. не зацикливающуюся).

library(XML);w="http://en.wikipedia.org";W="/wiki/";n=1;A=c(scan(,""));while(A[n]!="Philosophy"){a=paste0(w,W,A[n]);d=sapply(strsplit(grep(W,sapply(xpathApply(xmlParse(readLines(a)),"//p/a[@href]|//ul/li/a[@href]",xmlAttrs),`[`,'href'),v=T),"/"),`[`,3);B=d[-grep(":",d)];n=n+1;A[n]=head(B[!B%in%A],1);cat(A[n],"\n")};cat(n-1)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.