19
\$\begingroup\$

"All roads lead to Rome" is a saying that essentially means there are plenty of different ways of achieving an objective.

Task

Your task is to write a program that finds a set of link connections from one Wikipedia page to the Wikipedia page about Rome.

Notice that it is not enough to find the word Rome with a hyperlink, Rome has to be linked to this specific page: "https://en.wikipedia.org/wiki/Rome"

Link connections

The Wikipedia pages are written in HTML, a markup language. With the appropriate syntax, a word or phrase can be annotated and turned into a hyperlink, which allows people to click the word/phrase and open a new Wiki page. You can see a couple of such link in the screenshot below:

enter image description here

Those annotated hyperlinks are what your program should locate and follow. To try and avoid some loopholes, we are going to restrict the links you are allowed to follow to the links within the div named content, which is roughly this part of the wiki page:

enter image description here

Loopholes

  • You are only allowed to query Wikipedia wiki pages on the internet. Your answer may not communicate with anything else. E.g., you are not allowed to download someone else's answer and run it.

  • You may not communicate with any wiki APIs or Wiki "meta" pages, such as the "Category" page.

This community is very clever and imaginative. As more loopholes arise, those may be explicitly disallowed in the challenge. The spirit of the challenge is to find a series of links a user could click in the content of wiki pages.

Input

Your code should take one of the two as input:

  • a string that, when appended to https://en.wikipedia.org/wiki/, gives a valid link to a valid Wikipedia page;
  • a string with the link already built for you.

You may assume there is a valid path between the input page and Rome's page.

Output

Your program should output the path taken so that the lengths you claim are actually verifiable. It is up to you to output the path in any way that is human readable and understandable. Some suggestions include:

  • the successive path links
  • the successive page names

Scoring

This is code-golf, so we care about byte count. You are allowed to define a string literal containing exactly these characters in this order: "https://en.wikipedia.org/wiki/" and not count it for the byte count of your program.

Test cases

At the time of writing, these pages had a 1-link path to Rome:

"https://en.wikipedia.org/wiki/Italy"
"https://en.wikipedia.org/wiki/A.S._Roma"
"https://en.wikipedia.org/wiki/Vatican_Hill"
"https://en.wikipedia.org/wiki/Europe"
"https://en.wikipedia.org/wiki/European_Union"

And these pages had a path of length at most 2 to Rome:

"https://en.wikipedia.org/wiki/Continent"
"https://en.wikipedia.org/wiki/France"

(feel free to suggest more!)

Please submit your code with a screenshot or a TIO link showing a path from a Wikipedia page of your choosing to Rome.

\$\endgroup\$
4
\$\begingroup\$

JavaScript (Node.js), 335 - 30 = 305 bytes

I'm not very happy with it, but let's get the ball rolling.

Takes input as a page name. Prints a list of page names, separated with linefeeds.

u=>(i=0,g=a=>(m=a.find(u=>u=='Rome'))?console.log((h=v=>g[v]==u?u:h(g[v])+`
`+g[v])(m)+`
`+m):require('https').get('https://en.wikipedia.org/wiki/'+(U=a[i++]),r=>r.on('data',s=>h+=s,h="").on("end",_=>g([...new Set([...a,...((h.match(/mw-b.*mw-d/s)||[''])[0].match(/(?<=href=".wiki.).*?(?=")/g)||[]).map(v=>(g[v]=g[v]||U,v))])]))))([u])

(Don't) try it online!

Example I/O

f("Commodore_64")

Results in:

Commodore_64
Christmas
Rome
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ (Don't) try it online! Literally lol! :D \$\endgroup\$ – Noodle9 Mar 4 at 18:29
  • \$\begingroup\$ What is taking over 60s on TIO if I didn't even call the function? Is the code doing some sort of setup? \$\endgroup\$ – RGS Mar 4 at 20:11
  • \$\begingroup\$ @RGS TIO has been quite disturbed today, so these 60 seconds are probably spent doing nothing at all. \$\endgroup\$ – Arnauld Mar 4 at 20:20
3
\$\begingroup\$

Python 3 + BeautifulSoup 4, 269 - 30 = 239 bytes

import bs4,requests as r
k=l=[(input(),)]
while'Rome'!=k[-1]:k=l.pop(0);l+=[k+(h[6:],)for h in[l.get('href')for l in bs4.BeautifulSoup(r.get('https://en.wikipedia.org/wiki/'+k[-1]).content).find(id='content').find_all('a')]if None!=h>h[:6]=='/wiki/'[':'in h:]]
print(k)

Input and output are page titles.

Example outputs

OVS_(company) => ('OVS_(company)', 'Albania', 'Rome')

Code_golf => ('Code_golf', 'Source_code', 'Free_speech', 'Rome')

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Java 10, 451 418 - 30 = 388 bytes

p->{for(;;)for(var t:p){if(t.endsWith(" Rome"))return t;String w="https://en.wikipedia.org/wiki/",c=t;try{try(var b=new java.io.BufferedReader(new java.io.InputStreamReader(new java.net.URL(w+t.replaceAll(".*?(\\S+)$","$1")).openStream()))){for(;(i=b.readLine())!=null;)c+=i;}for(var h:c.replaceAll(".*ole=.mai(.*)id=.catl.*","$1").split("href=./wiki/"))p.add(t+" "+h.substring(0,h.indexOf('"')));}finally{continue;}}}

Extremely slow would be an understatement, but it works..

Takes just the page (wrapped into a CopyOnWriteArraySet<String>) as input. Outputs the pages space-delimited as String.

Example run locally:

Input:  "Java_(programming_language)"
Output: "Java_(programming_language) Rust_(programming_language) Rome"

Explanation:

p->{                           // Method with Set<String> parameter and String return-type
  for(;;)                      //  Loop indefinitely:
    for(var t:p){              //   Loop over each String `t` in the input-CopyOnWriteArraySet:
                               //   (it's a CopyOnWriteArraySet, since we otherwise wouldn't
                               //    be able to add while iterating)
      if(t.endsWith(" Rome"))  //    If the current String `t` ends with " Rome"
        return t;              //     Return it as result
    String w="https://en.wikipedia.org/wiki/",
                               //    String with the base url of Wikipedia
           c=t;                //    Content-String (starts at `t` instead of "" to save a byte)
    try{try(var b=new java.io.BufferedReader(new java.io.InputStreamReader(new java.net.URL(w
                               //    Go to the Wikipedia website
          +t.replaceAll(".*?(\\S+)$","$1")
                               //    with everything after the last space in `t` as page
            ).openStream()))){ //    And open this website as a try-with-resources BufferedReader
        for(;(i=b.readLine())!=null;)
                               //     Read all lines of the page:
          c+=i;}               //      And append each line to the content-String
      for(var h:c.replaceAll(".*ole=.mai(.*)id=.catl.*","$1")
                               //    Take the content between 'ole="mai' and 'id="catl':
                               //    ('role="main"' and 'id="catlinks"')
                 .split("href=./wiki/"))
                               //    Split it on 'href="/wiki/', and loop over each part:
        p.add(                 //     Add to the input-Set:
           t+" "               //      The current String with an appended space
           +h.substring(0,h.indexOf('"')));
                               //      Appended with the leading part up until the first '"'
    }finally{                  //   If any error occurs accessing the page (i.e. going to "wiki/.")
      continue;}}}             //    Skip it, and go to the next iteration
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.