Wikipedia: Filosofia!


26

Come molti geek possono conoscere la maggior parte delle pagine (penso al 95%) su Wikipedia alla fine portano a una filosofia come questa:

Fai clic sul primo link non corsivo o tra parentesi che si trova su un altro articolo normale: (cioè non File: o Speciale :, ma cose come Wikipedia: sono OK) e ripeti su quello fino a quando non raggiungi la filosofia.

La sceneggiatura deve:

  • Prendi una prima pagina come input
  • Stampa il nome di ogni articolo a cui arriva
  • E stampa quanti articoli ci sono voluti per arrivare alla filosofia, e se non lo dicesse.

Inizi con 1000 punti e ne perdi uno per ogni personaggio nel codice, punti bonus per:

Rilevamento di articoli in loop e arresto: +50

Rilevamento di articoli in loop e richiesta se l'utente deve andare al collegamento successivo sull'articolo: +170

Consentire un valore predefinito sul primo controllo come arg della riga di comando o simile: +140

Il punteggio più alto vince.


7
+1, grande sfida! Questo rilevamento tra parentesi è difficile: P
Maniglia della porta

1
Ho la sensazione che questo potrebbe usare una definizione migliore, ma non sono sicuro di come ancora.
Iszi,

3
Perdere un punto per ogni carattere digitato. Hmm. Fantastico, ho capito, copierò e incollerò i personaggi! Nessun punto perso!
Justin,

5
Si prega di non modificare le regole dopo che le risposte sono già state pubblicate; è piuttosto scortese e generalmente malvisto nella comunità qui ...
Maniglia della porta

Risposte:


8

Rubino, 1000-330 299 337-50 373 - 170 382 - 170 - 140 379 - 170 - 140 caratteri = 697 701 713 797 928 931

Sono sicuro che ci sono molti miglioramenti da apportare.

(Questo richiede 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

Esempio di esecuzione:

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

Esempio uno in cui ho dovuto andare a un altro link

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

Trucchi che ho usato:

  • Ho usato il selettore p aper ottenere solo collegamenti non corsivi, perché tutti i collegamenti nell'articolo reale che non sono in corsivo sono sempre presenti negli elementi di paragrafo di Wikipedia.

hmmm ... forse dovrei vietare qualsiasi libreria tranne quella fornita con la lingua ...
AlphaModder

@ user1825860 In realtà non è una libreria fornita con la lingua; è un gioiello. Ho modificato la mia risposta. Ma davvero, vuoi prendere questa sfida già dura e costringerci a non usare anche le librerie di analisi HTML? : P
Maniglia della porta

non lo sto vietando ma perdi punti: P
AlphaModder,

Dovresti rileggere il primo post e modificarlo di conseguenza: P
AlphaModder

2
@ user1825860 Non modificare le regole dopo che le risposte sono già state pubblicate; è piuttosto scortese ...
Maniglia della porta

5

"BASH " - (Se non si sbaglia: 1000 - 397 + 170 + 140 = 913 punti)
"BASH" - (Se non si sbaglia: 1000 - 386 + 170 + 140 = 924 punti)

"BASH" - (Se non si sbaglia: 1000 - 381 + 170 + 140 = 929 punti)

BASH è racchiuso tra virgolette perché si tratta di una combinazione di strumenti utilizzati nelle shell * nix ma racchiusi in uno script bash.

Modifica 1:

  • Rimosso http://comecurl impostazione predefinita a questo.
  • href=Corrispondenza modificata su ancore in f=as <a>non ha altri attributi normali che finiscono inf . (È una possibilità di tag personalizzati. Non ho visto fino ad ora.)
  • Impostare il messaggio di uscita su Non trovato su !Philanziché su NoPhil. Questo è un po 'eccentrico come Si potrebbe anche dire ad esempio !, 0, N, !Po simili.
  • Quirk due: -soncurl potrebbe essere rimosso per ridurre di altri tre byte, ma ciò produrrebbe un output disordinato. Non sono sicuro se questo è un problema.
  • Guida aggiornata su questa pagina.

Usando le stranezze, il codice sarebbe finito a 379 byte, 931 punti.

Potrei anche implementare l' uso di @plannapus della casella di navigazione corrispondente (si spera) aggiungendo l' (p|ul).*?<(\1)aggiunta di sei byte (sottraendo sei punti).

Modifica 2:

Usando ${#c[@]}per stampare i gradi di separazione anziché il $icontatore.

Usando le stranezze, il codice sarebbe finito a 374 byte, 936 punti.


Richiamo Cthulhu e cerco una soluzione regexp + bash / shell / * nix.

Stolen:

implementato:

  • Rileva loop e chiedi se il prossimo link dovrebbe essere preso.
  • Opzionalmente selezionare il collegamento successivo su duplicato come opzione.

Requisiti:

  • bash v.?
  • grepcon -Psupporto (PCRE).
  • sed
  • curl
  • cut

Uso:

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.

Codice incorporato. Copia su file. chmod +x filename. Gestito da ./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[@]};

Codice espanso e spiegato:

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

Accidenti, mi hai battuto di un punto! : P Dovrò golf di più la mia soluzione
Maniglia della porta

Sì;), ma non sono sicuro che questo sia un codice valido. Utilizzando gli strumenti in questo modo.
Runium,

5

JavaScript 726 (444 caratteri [556] + 170)

Ora apprezzo che questo potrebbe non essere valido come bookmarklet, ma mi è comunque piaciuto armeggiare con esso.

Utilizzo: vai alla pagina da cui desideri iniziare ed esegui quanto segue nella 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)

Per JavaScript l'output è il seguente:

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

Questa soluzione presupporrà che si desideri passare al collegamento successivo su un loop rilevato, ma se si modifica truealla fine infalse verrà visualizzato un riquadro di conferma (piuttosto fastidioso ...) non sicuro se si qualifica per il bonus secondario o no. Presumo di no.

rientrato:

(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

Quindi originariamente mi mancava la parte sull'ignorare gli oggetti nelle parentesi, aggiungendo che lo rendeva molto più prolisso, quindi spero di golf che il filtro funzioni in giù (o si spera lo sostituisca completamente).

Funziona sia su Chrome che su Firefox (testato su Firefox 26)


2
Sembra fantastico, ma non funziona in Firefox 20.
stand dal

Argghh! Ho testato solo Chrome. Ci guarderò dentro!
Dom Hastings,

@boothby Ora dovrebbe funzionare su Firefox ... Voglio ancora lavorare sui collegamenti che sto scegliendo!
Dom Hastings,

5

C # - 813 caratteri

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

Nessuna libreria esterna. Rilevazione loop .

Il primo argomento è l'articolo di origine, il secondo è l'articolo di destinazione.

Versione golfizzata:

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

Versione intelligente:

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

Esempio di esecuzione, da "Sky" a "Filosofia":

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 caratteri => 1000-294 + 140 = 846 punti)

La soluzione aggiornata che prende automaticamente il collegamento successivo se ne è già stato utilizzato uno. Grazie per i 140 punti bonus.

Logica: scegli il primo link "/ wiki" che non contiene un ":" (quindi ignora i collegamenti "File:"). Risciacquare e ripetere con ricorsione restituendo il conteggio + 1 ogni volta. Tengo a portata di mano un elenco di tutte le uscite precedenti in modo che il programma non vada in un ciclo infinito.

Espressione regolare: ho 2 forme dell'espressione regolare.

  • "<p>.*?\"/wiki/([^:]*?)\".*?/p>"che trova collegamenti all'interno dei <p>tag
  • "p>.*?/wiki/([^:]*?)\""che è un tag leggermente più sperimentale che ha dimostrato di funzionare ma fornisce risultati diversi perché, a volte, raccoglie i collegamenti dalla barra delle informazioni sul lato destro. Questi sono articoli regolari, quindi credo che sia ancora valido. Se viene giudicato non valido, l'OP (o qualcun altro) può lasciarmi un commento e posso aggiornare la mia soluzione a un migliore reg-ex.

Userò la seconda espressione regolare fino a quando non troverò un caso di prova in cui non funziona o le menzioni OP che raccolgono i collegamenti dalla barra laterale non sono consentite (a mio avviso, le barre delle informazioni fanno ancora parte di l'articolo vero e proprio; più di una sintesi).


Fonte minimizzata:

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

Fonte leggibile:

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

Uscita campione:

Ingresso

Space_toilet

Produzione

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 non richiede un oggetto o metodo principale. Puoi eseguirlo con l'interprete come "scala <nomefile> [args ..]". Usa args(0)per ottenere il primo argomento, sbarazzarti di te objecte maindefinizioni, e penso che anche tu puoi rimuovere :Int. pastebin.com/YqywKcG8
KChaloux,

Si scopre che non è possibile rimuovere il : Int. Non avevo capito che stavi facendo una chiamata ricorsiva. Anche il mio pastebin è stato preso dalla tua vecchia fonte leggibile, ma valgono gli stessi concetti.
KChaloux,

Proverò a sbarazzarmi del metodo principale. E sì, le chiamate ricorsive mi hanno fatto aggiungere il :Intlì. Più tardi oggi aggiungerò anche una forma leggibile della soluzione di 333 caratteri che ho. Grazie per i suggerimenti @KChaloux
javatarz

1
Come ho detto, il riferimento a object Q extends App { ... }è totalmente inutile se si esegue il codice con l'interprete anziché compilare con scalac. scala <filename> [args..]
Corri

4

R, 379 caratteri; 1000-379 + 170 = 791 punti

Versione che chiede agli utenti come procedere quando viene rilevato il loop

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)

Con rientri e commenti:

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)

Esempio di esecuzione:

> 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 caratteri; ??? punti

Versione che, per impostazione predefinita, utilizza il primo collegamento non ridondante (ovvero non in loop).

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)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.