Wikipédia: la philosophie!


26

Comme beaucoup de geeks peuvent connaître la plupart des pages (95% je pense) sur wikipedia, elles mènent finalement à une philosophie comme celle-ci:

Cliquez sur le premier lien non italique ou entre parenthèses qui renvoie à un autre article normal: (c'est-à-dire pas Fichier: ou Spécial:, mais des choses comme Wikipedia: sont OK) et répétez sur celui-ci jusqu'à ce que vous atteigniez la philosophie.

Le script doit:

  • Prendre une première page en entrée
  • Imprimez le nom de chaque article auquel il parvient
  • Et imprimez le nombre d'articles qu'il a fallu pour arriver à la philosophie, et s'il ne l'a pas dit.

Vous commencez avec 1000 points, et perdez un pour chaque personnage du code, des points bonus pour:

Détection d'articles en boucle et arrêt: +50

Détecter les articles en boucle et demander si l'utilisateur doit aller au lien suivant sur l'article: +170

Autoriser une valeur par défaut sur l'ancien contrôle comme argument de ligne de commande ou similaire: +140

Le score le plus élevé l'emporte.


7
+1, grand défi! Cette détection de parenthèses est difficile: P
Poignée de porte

1
J'ai l'impression que cela pourrait utiliser une meilleure définition, mais je ne sais pas encore exactement comment.
Iszi

3
Perdez un point pour chaque caractère tapé. Hmm. Génial, je l'ai, je vais juste copier-coller les caractères! Aucun point perdu!
Justin

5
Veuillez ne pas modifier les règles une fois que les réponses ont déjà été publiées; c'est assez désagréable et généralement mal vu dans la communauté ici ...
Poignée de porte

Réponses:


8

Rubis, 1000 - 303 299 337 - 50 373 - 170 382 - 170 - 140 379 - 170 - 140 caractères = 697 701 713 797 928 931

Je suis sûr qu'il y a de nombreuses améliorations à apporter.

(Cela nécessite Nokogiri)

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

Exemple d'exécution:

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

Échantillon un où je devais aller à un lien différent

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

Astuces que j'ai utilisées:

  • J'ai utilisé le sélecteur p apour obtenir uniquement des liens non italiques, car tous les liens dans l'article réel qui ne sont pas en italique sont toujours dans les éléments de paragraphe de Wikipedia.

hmmm ... je devrais peut-être interdire tout sauf les bibliothèques qui viennent avec la langue ...
AlphaModder

@ user1825860 Ce n'est pas en fait une bibliothèque fournie avec la langue; c'est un bijou. J'ai édité ma réponse. Mais vraiment, vous voulez relever ce défi déjà difficile et nous obliger à ne pas trop utiliser les bibliothèques d'analyse HTML? : P
Poignée de porte

je ne le refuse pas mais tu perds des points: P
AlphaModder

Vous devriez relire le premier message et modifier en conséquence: P
AlphaModder

2
@ user1825860 Veuillez ne pas modifier les règles une fois que les réponses ont déjà été publiées; c'est assez grossier ...
Poignée de porte

5

"BASH " - (Si vous ne vous trompez pas: 1000 - 397 + 170 + 140 = 913 points)
"BASH" - (Si vous ne vous trompez pas: 1000 - 386 + 170 + 140 = 924 points)

"BASH" - (Si vous ne vous trompez pas: 1000 - 381 + 170 + 140 = 929 points)

BASH est délibérément entre guillemets car il s'agit d'un mélange d'outils utilisés dans les shells * nix mais enveloppés dans un script bash.

Modifier 1:

  • Supprimé http://par curldéfaut.
  • La href=correspondance des ancres avec f=as <a>n'a pas d'autres attributs normaux se terminant par f. (C'est une possibilité de balises personnalisées. Je n'en ai pas vu jusqu'à présent.)
  • Définissez le message de sortie sur introuvable sur au !Phillieu de NoPhil. Celui - ci est un peu bizarre comme on pourrait dire aussi , par exemple !, 0, N, !Pou similaire.
  • Quirk two: -son curlpourrait être supprimé pour réduire de trois octets supplémentaires, mais cela produirait une sortie désordonnée. Je ne sais pas si c'est un problème.
  • Aide mise à jour sur cette page.

En utilisant des excentricités, le code se retrouverait à 379 octets, 931 points.

Je pourrais également implémenter @plannapus l' utilisation de la boîte de navigation correspondante (espérons-le) en (p|ul).*?<(\1)ajoutant six octets (en soustrayant six points).

Modifier 2:

Permet ${#c[@]}d'imprimer les degrés de séparation au lieu du $icompteur.

En utilisant des excentricités, le code se retrouverait à 374 octets, 936 points.


J'invoque Cthulhu et opte pour une solution regexp + bash / shell / * nix.

Volé:

Mis en œuvre:

  • Détectez la boucle et demandez si le lien suivant doit être pris.
  • En option, sélectionnez le lien suivant sur la copie en option.

Exigences:

  • bash v.?
  • grepavec prise en charge -P(PCRE).
  • sed
  • curl
  • cut

Usage:

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.

Code en ligne. Copiez dans un fichier. chmod +x filename. Géré par le ./script /wiki/…shell 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[@]};

Code développé et expliqué:

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[@]}

Bon sang, tu m'as battu d'un point! : P Je vais devoir jouer plus à ma solution
Poignée de porte

Oui;), mais je ne suis pas sûr que ce code soit valide. Utiliser des outils de cette façon.
Runium

5

JavaScript 726 (444 caractères [556] + 170)

Maintenant, j'apprécie que cela ne soit peut-être pas valide en tant que bookmarklet, mais j'ai quand même aimé le bricoler.

Utilisation: accédez à la page à partir de laquelle vous souhaitez démarrer et exécutez les éléments suivants dans la console:

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

Pour JavaScript, la sortie est la suivante:

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

Cette solution supposera que vous souhaitez passer au lien suivant sur une boucle en cours de détection, mais si vous modifiez le trueà la fin, falseune boîte de confirmation apparaîtra à la place (assez ennuyeux ...) vous ne savez pas si cela remplit les conditions requises pour le bonus secondaire ou non. Je suppose que non.

Dentelé:

(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

J'ai donc manqué à l'origine la partie sur l'ignorance des éléments dans les parens, ajoutant que cela le rendait beaucoup plus verbeux, donc j'espère jouer au bas de cette fonction de filtrage (ou, espérons-le, la remplacer entièrement).

Fonctionne à la fois dans Chrome et Firefox (testé dans Firefox 26)


2
Semble génial, mais échoue dans Firefox 20.
boothby

Argghh! Je n'ai testé que Chrome. Je vais y jeter un œil!
Dom Hastings

@boothby Devrait fonctionner dans Firefox maintenant ... Je veux quand même travailler sur les liens que je choisis!
Dom Hastings

5

C # - 813 caractères

Score: 1000-813 + 50 + 170 + 140 = 547 :(

Pas de bibliothèques externes. Détection de boucle .

Le premier argument est l'article source, le deuxième est l'article cible.

Version golfée:

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);
    }
}

Version intelligible:

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);
    }
}

Exemple d'exécution, de "Sky" à "Philosophy":

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 caractères => 1000-294 + 140 = 846 points)

La solution mise à jour qui prend automatiquement le lien suivant si celui-ci a déjà été consommé. Merci pour les 140 points bonus.

Logique: récupérez le premier lien "/ wiki" qui ne contient pas de ":" (il ignore donc les liens "Fichier:"). Rincer et répéter avec récursivité en retournant le compte + 1 à chaque fois. Je garde une liste de toutes les sorties précédentes à portée de main afin que le programme ne passe pas dans une boucle infinie.

Expression régulière: J'ai 2 formes d'expression régulière.

  • "<p>.*?\"/wiki/([^:]*?)\".*?/p>"qui trouve des liens dans les <p>balises
  • "p>.*?/wiki/([^:]*?)\""qui est une balise légèrement plus expérimentale qui a fait ses preuves mais qui donne des résultats différents car elle récupère parfois des liens dans la barre d'informations de droite. Ce sont des articles réguliers donc je pense qu'il est toujours valable. S'il est décidé de ne pas l'être, l'OP (ou quelqu'un d'autre) peut me laisser un commentaire et je peux mettre à jour ma solution pour un meilleur reg-ex.

Je vais utiliser la deuxième expression régulière jusqu'à ce que je trouve un cas de test où cela ne fonctionne pas ou que l'OP mentionne que la récupération de liens dans la barre latérale n'est pas autorisée (à mon avis, les barres d'informations font toujours partie de l'article lui-même; plutôt un résumé).


Source minifiée:

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

Source lisible:

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

Exemple de sortie:

Contribution

Space_toilet

Sortie

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 ne nécessite ni objet ni méthode principaux. Vous pouvez l'exécuter avec l'interpréteur en tant que "scala <nomfichier> [args ..]". Utilisez args(0)pour obtenir le premier argument, se débarrasser de vos objectet maindéfinitions, et je pense que vous pouvez supprimer le :Inttrop. pastebin.com/YqywKcG8
KChaloux

Il s'avère que vous ne pouvez pas supprimer le : Int. Je ne savais pas que vous faisiez un appel récursif. De plus, mon pastebin a été tiré de votre ancienne source lisible, mais les mêmes concepts s'appliquent.
KChaloux

Je vais essayer de me débarrasser de la méthode principale. Et oui, les appels récursifs m'ont fait ajouter le :Intlà. Plus tard dans la journée, j'ajouterai également une forme lisible de la solution 333 car j'ai. Merci pour les suggestions @KChaloux
javatarz

1
Comme je l'ai dit, la référence à object Q extends App { ... }est totalement inutile si vous exécutez le code avec l'interpréteur plutôt que de le compiler avec scalac. Il suffit de courir avecscala <filename> [args..]
KChaloux

4

R, 379 caractères; 1000-379 + 170 = 791 points

Version demandant aux utilisateurs comment procéder lors de la détection d'une boucle

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)

Avec indentations et commentaires:

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)

Exemple d'exécution:

> 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 caractères; ??? points

Version qui, par défaut, prend le premier lien non redondant (c'est-à-dire sans boucle).

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)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.