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


26

Оскільки багато вундеркіндів, можливо, знають, що більшість сторінок (95% я думаю) у вікіпедії врешті-решт призводять до такої філософії:

Клацніть на першому не курсивному чи в дужках посиланні, що знаходиться на іншій звичайній статті: (тобто не Файл: або Спеціальний:, але такі речі, як Вікіпедія: добре), і повторюйте цю, доки ви не потрапите на філософію.

Сценарій повинен:

  • Візьміть першу сторінку як вхідну інформацію
  • Роздрукуйте назву кожної статті, до якої вона потрапляє
  • І надрукуйте, скільки статей знадобилося, щоб потрапити до «Філософії», і якщо вона цього не сказала.

Ви починаєте з 1000 очок і втрачаєте по одному на кожен символ у коді, бонусні бали за:

Виявлення циклічних статей і зупинка: +50

Виявлення циклічних статей та запитання, чи повинен користувач перейти до наступного посилання на статтю: +170

Дозвіл за замовчуванням на колишній чек у вигляді аргументу командного рядка чи подібного: +140

Найвищий результат виграє.


7
+1, великий виклик! Виявлення дужок важко: P
Дверна ручка

1
Я відчуваю, що це може використати дещо краще визначення, але я не впевнений, як саме так.
Іссі

3
Втратіть один бал за кожен набраний символ. Хм. Чудово, я це отримав, я просто копіюю і вставляю символи! Балів не втрачено!
Джастін

5
Не змінюйте правила після того, як відповіді вже розміщені; це досить грубо і, як правило, нахмурилося в громаді тут ...
Doorknob

Відповіді:


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 Будь ласка, не змінюйте правила після того, як відповіді вже розміщені; це досить грубо ...
Doorknob

5

"БАШ " - (Якщо не помиляюся: 1000 - 397 + 170 + 140 = 913 балів)
"БАШ" - (Якщо не помиляюсь: 1000 - 386 + 170 + 140 = 924 бали)

"БАШ" - (Якщо не помиляюся: 1000 - 381 + 170 + 140 = 929 балів)

BASH наводиться в лапках, оскільки це суміш інструментів, що використовуються в * nix-оболонках, але загорнуті в баш-скрипт.

Редагувати 1:

  • Видалено http://за curlзамовчуванням до цього.
  • Змінено href=збіг на якорях на f=як <a>немає інших нормальних атрибутів, що закінчуються f. (Це можливість користувацьких тегів. Досі цього не бачили.)
  • Встановити повідомлення про вихід не на, !Philа не на NoPhil. Це один трохи виверткий , як можна було б також сказати , наприклад !, 0, N, !Pабо аналогічний.
  • Вигадка друга: -son curlможе бути видалений, щоб зменшити ще на три байти, але це призведе до безладного виводу. Не впевнений, чи це проблема.
  • Оновлена довідка на цій сторінці.

Використовуючи примх, код отримав би 379 байт, 931 бал.

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

Редагувати 2:

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

Використовуючи примх, код отримав би 374 байти, 936 балів.


Я викликаю Cthulhu та йду за рішенням регулярного виведення + bash / shell / * nix.

Викрадено:

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

  • Визначте цикл і запитайте, чи слід брати наступне посилання.
  • Необов'язково виберіть наступне посилання на дублікат як варіант.

Вимоги:

  • 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 Мені доведеться більше
Doorknob

Ye;), але не впевнений, що це дійсний код. Використовуючи інструменти таким чином.
Руніум

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.
Стійка

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

Scala (294 знаків => 1000-294 + 140 = 846 балів)

Оновлене рішення, яке автоматично приймає наступне посилання, якщо таке вже було використано. Дякуємо за 140 бонусних балів.

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

Регулярне вираження: у мене є 2 форми регулярного виразу.

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

Я буду використовувати другий регулярний вираз, поки не знайду тестовий випадок, коли він не працює або ОП згадує, що збирати посилання з бічної панелі заборонено (на мою думку, інформаційні панелі все ще входять власне стаття, більше резюме).


Зменшене джерело:

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 <ім'я файла> [args ..]". Використовуйте args(0)для отримання першого аргументу, позбавлення від своїх objectта mainвизначень, і я думаю, ви можете також усунути їх :Int. pastebin.com/YqywKcG8
KChaloux

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

Я спробую позбутися основного методу. І так, рекурсивні дзвінки змусили мене додати :Intтуди. Пізніше сьогодні я також додаю читабельну форму 333 char рішення, яке я маю. Дякую за пропозиції @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.