18
\$\begingroup\$

Challenge

Using data from the API here, output the names of the three countries with the most Olympic gold medals at the 2016 Rio Olympic Games (i.e. the first element of the returned list).

For example, at the time of posting (18:23 UTC+1, Monday, 15th August), the USA, the UK and China have the most gold medals, so the output would be:

United States
Great Britain
China

The country names must be separated by newlines and you may have a leading or trailing newlines.

Once the Olympics have finished, the program does not have to work as expected.

URL shorteners are disallowed but JSON parsing libraries are allowed.

This is code golf, so the shortest code in bytes wins.

I'm going to keep trying to get an Olympics themed challenge in here

Leaderboard

var QUESTION_ID=89919,OVERRIDE_USER=30525;function answersUrl(e){return"https://api.stackexchange.com/2.2/questions/"+QUESTION_ID+"/answers?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+ANSWER_FILTER}function commentUrl(e,s){return"https://api.stackexchange.com/2.2/answers/"+s.join(";")+"/comments?page="+e+"&pagesize=100&order=desc&sort=creation&site=codegolf&filter="+COMMENT_FILTER}function getAnswers(){jQuery.ajax({url:answersUrl(answer_page++),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){answers.push.apply(answers,e.items),answers_hash=[],answer_ids=[],e.items.forEach(function(e){e.comments=[];var s=+e.share_link.match(/\d+/);answer_ids.push(s),answers_hash[s]=e}),e.has_more||(more_answers=!1),comment_page=1,getComments()}})}function getComments(){jQuery.ajax({url:commentUrl(comment_page++,answer_ids),method:"get",dataType:"jsonp",crossDomain:!0,success:function(e){e.items.forEach(function(e){e.owner.user_id===OVERRIDE_USER&&answers_hash[e.post_id].comments.push(e)}),e.has_more?getComments():more_answers?getAnswers():process()}})}function getAuthorName(e){return e.owner.display_name}function process(){var e=[];answers.forEach(function(s){var r=s.body;s.comments.forEach(function(e){OVERRIDE_REG.test(e.body)&&(r="<h1>"+e.body.replace(OVERRIDE_REG,"")+"</h1>")});var a=r.match(SCORE_REG);a&&e.push({user:getAuthorName(s),size:+a[2],language:a[1],link:s.share_link})}),e.sort(function(e,s){var r=e.size,a=s.size;return r-a});var s={},r=1,a=null,n=1;e.forEach(function(e){e.size!=a&&(n=r),a=e.size,++r;var t=jQuery("#answer-template").html();t=t.replace("{{PLACE}}",n+".").replace("{{NAME}}",e.user).replace("{{LANGUAGE}}",e.language).replace("{{SIZE}}",e.size).replace("{{LINK}}",e.link),t=jQuery(t),jQuery("#answers").append(t);var o=e.language;/<a/.test(o)&&(o=jQuery(o).text()),s[o]=s[o]||{lang:e.language,user:e.user,size:e.size,link:e.link}});var t=[];for(var o in s)s.hasOwnProperty(o)&&t.push(s[o]);t.sort(function(e,s){return e.lang>s.lang?1:e.lang<s.lang?-1:0});for(var c=0;c<t.length;++c){var i=jQuery("#language-template").html(),o=t[c];i=i.replace("{{LANGUAGE}}",o.lang).replace("{{NAME}}",o.user).replace("{{SIZE}}",o.size).replace("{{LINK}}",o.link),i=jQuery(i),jQuery("#languages").append(i)}}var ANSWER_FILTER="!t)IWYnsLAZle2tQ3KqrVveCRJfxcRLe",COMMENT_FILTER="!)Q2B_A2kjfAiU78X(md6BoYk",answers=[],answers_hash,answer_ids,answer_page=1,more_answers=!0,comment_page;getAnswers();var SCORE_REG=/<h\d>\s*([^\n,]*[^\s,]),.*?(\d+)(?=[^\n\d<>]*(?:<(?:s>[^\n<>]*<\/s>|[^\n<>]+>)[^\n\d<>]*)*<\/h\d>)/,OVERRIDE_REG=/^Override\s*header:\s*/i;
body{text-align:left!important}#answer-list,#language-list{padding:10px;width:290px;float:left}table thead{font-weight:700}table td{padding:5px}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <link rel="stylesheet" type="text/css" href="//cdn.sstatic.net/codegolf/all.css?v=83c949450c8b"> <div id="answer-list"> <h2>Leaderboard</h2> <table class="answer-list"> <thead> <tr><td></td><td>Author</td><td>Language</td><td>Size</td></tr></thead> <tbody id="answers"> </tbody> </table> </div><div id="language-list"> <h2>Winners by Language</h2> <table class="language-list"> <thead> <tr><td>Language</td><td>User</td><td>Score</td></tr></thead> <tbody id="languages"> </tbody> </table> </div><table style="display: none"> <tbody id="answer-template"> <tr><td>{{PLACE}}</td><td>{{NAME}}</td><td>{{LANGUAGE}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table> <table style="display: none"> <tbody id="language-template"> <tr><td>{{LANGUAGE}}</td><td>{{NAME}}</td><td>{{SIZE}}</td><td><a href="{{LINK}}">Link</a></td></tr></tbody> </table>

\$\endgroup\$
12
  • 6
    \$\begingroup\$ Would you say this is a... mini-golf? \$\endgroup\$
    – Deusovi
    Commented Aug 15, 2016 at 19:30
  • 1
    \$\begingroup\$ @Deusovi Ba-dum crash \$\endgroup\$
    – Beta Decay
    Commented Aug 15, 2016 at 19:31
  • 2
    \$\begingroup\$ I really want somebody to post a Java solution so that I can see if my C solution beats it… \$\endgroup\$
    – Dave
    Commented Aug 15, 2016 at 19:41
  • 3
    \$\begingroup\$ "The UK ... so output ... Great Britain" \$\endgroup\$ Commented Aug 15, 2016 at 21:57
  • 1
    \$\begingroup\$ @Dave NI Athletes can choose to either represent Team GB or Team Ireland. If NI Athletes were required to join Team GB, then it would be Team UK. \$\endgroup\$
    – SGR
    Commented Aug 17, 2016 at 12:16

23 Answers 23

13
\$\begingroup\$

C (+sockets), 433 429 280 276 270 259 bytes

#define H"medalbot.com"
char**p,B[999],*b=B;main(f){connect(f=socket(2,1,getaddrinfo("www."H,"80",0,&p)),p[4],16);send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost:"H"\r\n\r\n",69);read(f,b,998);for(f=3;f--;puts(p))b=strchr(p=strstr(++b,"_n")+9,34),*b=0;}

So it turns out that C isn't great at downloading resources from the internet and parsing them as JSON. Who knew?

This code is (naturally) super lax with error checking, so I guess if medalbot.com wanted to send malicious data they'd be able to trigger buffer overflows, etc. Also the latest code expects certain values for the constants (e.g. AF_INET = 2) which will probably be the case everywhere, but it's not guaranteed.

Here's the original code which isn't so fragile (but still isn't very robust or safe):

#include<netdb.h>
#define H"medalbot.com"
char*b,*B,d[999];struct addrinfo*p,h;main(f){h.ai_socktype=SOCK_STREAM;getaddrinfo("www."H,"80",&h,&p);f=socket(p->ai_family,p->ai_socktype,p->ai_protocol);connect(f,p->ai_addr,p->ai_addrlen);send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost: "H":80\r\nConnection: close\r\n\r\n",92,0);recv(f,d,998,0);for(f=0,b=d;f<3;++f)B=strstr(b,"_n")+9,b=strchr(B,'}'),*strchr(B,'"')=0,puts(B);}

Breakdown:

                            // No imports needed whatsoever!
#define H"medalbot.com"     // Re-use the host in multiple places
char**p,                    // This is actually a "struct addrinfo*"
    B[999],                 // The download buffer (global to init with 0)
    *b=B;                   // A mutable pointer to the buffer

main(f){
    // Hope for the best: try the first suggested address with no fallback:
    // (medalbot.com runs on Heroku which has dynamic IPs, so we must look up the
    // IP each time using getaddrinfo)
    f=socket(2,1,getaddrinfo("www."H,"80",0,&p));
                            // 2 = AF_INET
                            // 1 = SOCK_STREAM
                            //     (may not match getaddrinfo, but works anyway)
                            // 0 = IP protocol (getaddrinfo returns 0 on success)
    connect(f,p[4],16);     // struct addrinfo contains a "struct sockaddr" pointer
                            // which is aligned at 32 bytes (4*8)

    // Send the HTTP request (not quite standard, but works. 69 bytes long)
    send(f,"GET http://"H"/api/v1/medals HTTP/1.1\r\nHost:"H"\r\n\r\n",69);
    // (omit flags arg in send and hope 0 will be assumed)

    read(f,b,998);          // Get first 998 bytes of response; same as recv(...,0)

    // Loop through the top 3 & print country names:
    // (p is re-used as a char* now)
    for(f=3;f--;puts(p))        // Loop and print:
        p=strstr(++b,"_n")+9,   //  Find "country_name": "
        b=strchr(p,34),         //  Jump to closing "
        *b=0;                   //  Set the closing " to \0
}

This isn't very nice for the server since we don't send Connection: close\r\n as part of the HTTP request. It also omits the Accept header since medalbot.com doesn't seem to be using compression in any case, and misses the space after Host: (again, the server seems to be OK with this). It doesn't seem as though anything else can be removed though.


Once the olympics end, the most likely behaviour for this program is to segfault trying to read memory location 9. Unless an evil hacker takes over the domain, in which case the most likely behaviour is for it to set some byte to 0 in the address info structs, which probably isn't too dangerous actually. But who can tell with these evil hackers?

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Yeah, it's a pest with those hackers. Good thing we're on a website on which hackers of any kind are unlikely to ever turn up... \$\endgroup\$ Commented Aug 16, 2016 at 18:26
  • 1
    \$\begingroup\$ That was quite the leap! \$\endgroup\$ Commented Aug 16, 2016 at 20:23
  • 2
    \$\begingroup\$ @NonlinearFruit yeah it's amazing how many characters can be saved when you throw caution to the wind and use implementation-defined numbers directly in the code! This has become an exercise into "what is the craziest, most dangerous, most likely to break — but currently functional — way to download text in C?" \$\endgroup\$
    – Dave
    Commented Aug 16, 2016 at 20:27
  • \$\begingroup\$ Let's just hope that little Bobby Tables doesn't have any relatives competing this year. \$\endgroup\$ Commented Aug 17, 2016 at 11:54
  • \$\begingroup\$ Readability is also one of the first casualties of cod golf. . . \$\endgroup\$ Commented Aug 17, 2016 at 21:46
12
\$\begingroup\$

bash + w3m + grep + cut, 65 59 58 54 bytes

w3m medalbot.com/api/v1/medals|grep -m3 m|cut -d\" -f4
  • 6 bytes less thanks to @Joe's suggestions.
  • 1 byte less thanks to @YOU.
  • 4 bytes less thanks to @manatwork's suggestion that the medalbot API seems to work without www. subdomain too.
\$\endgroup\$
5
  • 2
    \$\begingroup\$ Change cut -d '"' to cut -d\" to save two bytes. If you use w3m instead of curl -s you can save 4 more. \$\endgroup\$
    – Joe
    Commented Aug 15, 2016 at 19:16
  • \$\begingroup\$ you can change _n to m \$\endgroup\$
    – YOU
    Commented Aug 16, 2016 at 11:14
  • \$\begingroup\$ @YOU: Not really because that way it'll return more lines than expected, i.e. "id": "germany", id": "colombia" etc. \$\endgroup\$
    – Master_ex
    Commented Aug 16, 2016 at 11:17
  • \$\begingroup\$ if they cant be 1 to 3rd it will be fine, you have -m3 guard. \$\endgroup\$
    – YOU
    Commented Aug 16, 2016 at 11:19
  • 1
    \$\begingroup\$ @YOU: I guess this is true for the current score and it seems that it will be OK for the 2016 Olympics (except if they change United States to United States of America :P). I'll change it. \$\endgroup\$
    – Master_ex
    Commented Aug 16, 2016 at 11:32
12
\$\begingroup\$

PowerShell v4+, 88 69 bytes

(ConvertFrom-Json(iwr medalbot.com/api/v1/medals))[0..2].country_name

Uses iwr (the alias for Invoke-WebRequest) to grab the API. We feed that as the input parameter to the ConvertFrom-Json built-in that pulls the JSON text into a custom object array. We encapsulate that object array in parens, take the first three elements [0..2], and take the .country_name of each thereof.

Requires at least v4+ for the multiple-object-properties, else we'd need to use something like |Select "country_name" instead. Requires at least v3+ for the ConvertFrom-Json built-in.

PS C:\Tools\Scripts\golfing> .\olympics-gold-leader.ps1
United States
Great Britain
China
\$\endgroup\$
2
  • \$\begingroup\$ You can drop http://www. and PS doesn't mind about http:// or the site about www.. My PS (5.1.14393) also doesn't even seem to care about the .content. \$\endgroup\$
    – Nick T
    Commented Aug 16, 2016 at 5:45
  • \$\begingroup\$ @NickT Thanks for the golfs. I didn't realize that ConvertFrom-Json didn't explicitly need only the .content portion of the web request, but it works on my setup as well. \$\endgroup\$ Commented Aug 16, 2016 at 12:24
6
\$\begingroup\$

R, 98, 112, 108 bytes

golfed 4 thanks to @miff

a=jsonlite::fromJSON(readLines("http://www.medalbot.com/api/v1/medals"))
cat(a$c[order(-a$g)[1:3]],sep="\n")

First line imports data using a JSON library. Second line grabs the relevant country names. It sorts the countries by gold medals in increasing order, reverses the indices, and takes the first 3, printing them.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ I think that you can replace rev(order(a$g)) with order(-a$g) to save 4 bytes \$\endgroup\$
    – Miff
    Commented Aug 17, 2016 at 10:22
5
\$\begingroup\$

JavaScript (ES6), 122 Bytes

fetch`http://www.medalbot.com/api/v1/medals`.then(a=>a.json()).then(b=>alert(b.slice(0,3).map(c=>c.country_name).join`\n`))

Due to a browser safety issue, this code must be run on medalbot.com. It does not however take advantage of that and could potentially be run elsewhere. Also note that I inserted the \n character, but am only counting is as one, because I could replace it with one

Node.js (ES6), 173 Bytes

require("http").get("http://www.medalbot.com/api/v1/medals",s=>s.on("data",d=>t+=d,t="").on("end",q=>console.log(JSON.parse(t).slice(0,3).map(a=>a.country_name).join`\n`)))

This would have been so much shorter if the API returned the data all in one stretch, but since it returns in two sections, I must concatenate the parts and combine them, and then parse them.

Node.js (ES6) + Request, 138 Bytes

require("request")("http://www.medalbot.com/api/v1/medals",(e,r,b)=>console.log(JSON.parse(b).slice(0,3).map(a=>a.country_name).join`\n`))

Better, but still not as good as the browser version. Thanks fetch API! Request is a popular HTTP client library used to simplify requests, and you can see that take effect here.

\$\endgroup\$
4
  • \$\begingroup\$ Which of these works in any browser? Can you put the shortest of those at the top of your answer (for the leaderboard) \$\endgroup\$
    – Beta Decay
    Commented Aug 15, 2016 at 18:37
  • \$\begingroup\$ The top one of these works in most modern browsers, and is also the shortest. The other two are in Node.js a way of writing JavaScript on the server (plus other things). \$\endgroup\$
    – bren
    Commented Aug 15, 2016 at 18:40
  • \$\begingroup\$ @βετѧΛєҫαγ Take note that it doesn't work in any version of IE or Safari \$\endgroup\$
    – bren
    Commented Aug 15, 2016 at 18:41
  • \$\begingroup\$ I see, I was getting hung up on the CORS problem \$\endgroup\$
    – Beta Decay
    Commented Aug 15, 2016 at 18:41
4
\$\begingroup\$

bash + w3m + jq, 83 59 bytes

w3m medalbot.com/api/v1/medals|jq -r '.[:3][].country_name'

Thanks to Jordan for three bytes.

Thanks to YOU for 24 more bytes! Turns out the data is sorted. Wow. :D

\$\endgroup\$
2
  • 1
    \$\begingroup\$ You can omit .| and index the result of sort_by directly, and you can save another byte by using [:3][] instead of [0,1,2]. All together: sort_by(-.gold_count)[:3][].country_name. \$\endgroup\$
    – Jordan
    Commented Aug 15, 2016 at 18:58
  • \$\begingroup\$ w3m medalbot.com/api/v1/medals|jq -r '.[:3][].country_name' \$\endgroup\$
    – YOU
    Commented Aug 16, 2016 at 13:21
4
\$\begingroup\$

Java 8, 261 258 bytes

This uses a lambda to save a couple bytes and the net library to get the webpage. Other than that is just Java.

()->{try{for(int i=0;i<3;System.out.println(new java.util.Scanner(new java.net.URL("http://www.medalbot.com/api/v1/medals").openConnection().getInputStream()).useDelimiter("\\A").next().split("\n")[i++*9+3].replaceAll(".* \"|\",","")));}catch(Exception e){}}

Here is my (old) POJO for testing (and golfing):

class QuickGolf {
  static void f(h x){x.g();}
  static interface h{ void g(); }
  static void main(String[] args){
    f(
      ()->{try{for(int i=0;i<3;i++){System.out.println(new java.util.Scanner(new java.net.URL("http://www.medalbot.com/api/v1/medals").openConnection().getInputStream()).useDelimiter("\\A").next().split("\n")[i*9+3].substring(21).replace("\",",""));}}catch(Exception e){}}
    );
  }
}

Update

  • -3 [16-08-17] Move print statement into for loop
  • -5 [16-08-16] Improved regex replace
  • -9 [16-08-16] Removed java.net import
\$\endgroup\$
4
  • \$\begingroup\$ Eep. I need to save some bytes… \$\endgroup\$
    – Dave
    Commented Aug 16, 2016 at 6:48
  • \$\begingroup\$ I'm catching up! Now just 15 bytes behind! \$\endgroup\$
    – Dave
    Commented Aug 16, 2016 at 20:08
  • \$\begingroup\$ Well, I was ahead for a few hours at least. It works against me, but you can probably save some more bytes by having the loop count down from 3 instead of up. \$\endgroup\$
    – Dave
    Commented Aug 17, 2016 at 22:06
  • \$\begingroup\$ @Dave I tried having the boolean break condition just bei but Java doesn't convert boolean to int or visa versa, if that was what you were thinking. Also you had me pretty nervous with that last edit. \$\endgroup\$ Commented Aug 18, 2016 at 2:32
3
\$\begingroup\$

MATL, 67 bytes

'http://www.medalbot.com/api/v1/medals'Xi'(?<="c.+e": ")[^"]+'XX3:)

This doesn't work online because function Xi (urlread) is disallowed.

Example run:

>> matl
 > 'http://www.medalbot.com/api/v1/medals'Xi'(?<="c.+e": ")[^"]+'XX3:)
 > 
United States
Great Britain
China

Explanation

This reads the contents as a string and then applies the regex '(?<="c.+e": ")[^"]+' to extract country names. The regex uses look-behind with "c.+e" instead of "country_name" to reduce code length.

'http://www.medalbot.com/api/v1/medals'   % Push string representing the URL
Xi                                        % Read URL contents as a string
'(?<="c.+e": ")[^"]+'                     % String for regex matching
XX                                        % Apply regex
3:)                                       % Get first 3 results
\$\endgroup\$
3
\$\begingroup\$

Python 3, 202, 164 bytes.

Python 3 does not do short url/json handling. :/
Didn't realize the API already sorts by gold count

from urllib.request import*
import json
print('\n'.join(x['country_name']for x in json.loads(urlopen('http://www.medalbot.com/api/v1/medals').read().decode())[:3]))
\$\endgroup\$
3
\$\begingroup\$

Python 2, 120 113 bytes

from urllib import*
for x in list(urlopen("http://www.medalbot.com/api/v1/medals"))[3:26:9]:
    print x[21:-4]

Thanks @Nick T and @Value Ink

\$\endgroup\$
2
  • 1
    \$\begingroup\$ from urllib import* and using just urlopen later saves 1 byte. Also, you should be able to take the print statement and put it right after the colon, saving you from the indentation. \$\endgroup\$
    – Value Ink
    Commented Aug 15, 2016 at 20:10
  • 1
    \$\begingroup\$ If you feed the urlopen object to list(), does that do the same thing as .readlines()? \$\endgroup\$
    – Nick T
    Commented Aug 16, 2016 at 17:06
3
\$\begingroup\$

JavaScript + jQuery, 114 100 bytes

$.get("www.medalbot.com/api/v1/medals",a=>alert(a[0][c='country_name']+'\n'+a[1][c]+'\n'+a[2][c]))

For the reason of Cross Origin Requests, this must be run from the medalbot.com domain (with jQuery).

History

  • -14 bytes thanks to @YetiCGN
  • -2 bytes thanks to Yay295
\$\endgroup\$
2
  • \$\begingroup\$ Or run chrome without web security { chrome.exe --disable-web-security } \$\endgroup\$ Commented Aug 15, 2016 at 18:41
  • 1
    \$\begingroup\$ save 2 bytes $.get("www.medalbot.com/api/v1/medals",a=>alert(a[0][c='country_name']+'\n'+a[1][c]+'\n'+a[2][c])) \$\endgroup\$
    – Yay295
    Commented Aug 16, 2016 at 18:20
2
\$\begingroup\$

Ruby, 97 79 + -rnet/http (11) = 90 bytes

Uses a modification of the regex pattern from Luis Mendo's MATL answer, further optimized by @Jordan, since Ruby doesn't support quantifiers in lookbehinds.

-18 bytes from @Jordan.

puts Net::HTTP.get("www.medalbot.com","/api/v1/medals").scan(/"c.+"(.+)"/)[0,3]
\$\endgroup\$
5
  • \$\begingroup\$ You can omit .map(&:last) entirely for 12 bytes, and omit the leading / in /api for one more. \$\endgroup\$
    – Jordan
    Commented Aug 15, 2016 at 19:38
  • \$\begingroup\$ Also, a shorter regex that seems to work fine: /"cou.+"(.+)"/ \$\endgroup\$
    – Jordan
    Commented Aug 15, 2016 at 19:41
  • \$\begingroup\$ Or: /y_.+"(.+)"/. \$\endgroup\$
    – Jordan
    Commented Aug 15, 2016 at 19:47
  • \$\begingroup\$ @Jordan omitting the leading / causes errors on my Ruby version. Or it might be the network I'm on? Whatever. I went with a slightly different regex than the one you suggested but same length. \$\endgroup\$
    – Value Ink
    Commented Aug 15, 2016 at 19:51
  • \$\begingroup\$ Interesting. FWIW I'm using 2.3.1. \$\endgroup\$
    – Jordan
    Commented Aug 15, 2016 at 19:52
2
\$\begingroup\$

PowerShell, 60

(iwr medalbot.com/api/v1/medals|convertfrom-json)[0..2]|% c*

Same basic idea as TimmyD (didn't see their answer before I posted), but quite a bit shorter :-)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ How the devil does that |% c* parsing work? I mean, it does, I just tried it, but that's some weird syntax (it even highlights in my ISE as an error). \$\endgroup\$ Commented Aug 16, 2016 at 20:10
  • 1
    \$\begingroup\$ @TimmyD: ForEach-Object has a parameter set that expands a single property, or calls a method with arguments: ForEach-Object [-MemberName] <String>. The -MemberName parameter supports wildcards, so in this case it expands the only member matching that wildcard: country_name. Saves quite a few characters, too ;-) \$\endgroup\$
    – Joey
    Commented Aug 16, 2016 at 20:14
2
\$\begingroup\$

Mathematica 96 66 bytes

@alephalpha found a way to work directly from the file (without saving it), thereby saving 30 bytes!

Import["http://www.medalbot.com/api/v1/medals","RawJSON"][[;;3,2]]

Import imports the file as a Raw JSON file. [[;;3,2]]takes rows 1-3, second entry (country name).

\$\endgroup\$
1
  • \$\begingroup\$ Import["http://www.medalbot.com/api/v1/medals","RawJSON"][[;;3,2]] \$\endgroup\$
    – alephalpha
    Commented Aug 16, 2016 at 11:46
2
\$\begingroup\$

PHP, 205 139 124 116 111 109 bytes

I just wanted to use the new spaceship operator for PHP 7 once (EDIT: It's superfluous, as sorting isn't required):

<?$d=json_decode(file_get_contents('http://www.medalbot.com/api/v1/medals'),1);usort($d,function($a,$b){$g='gold_count';return$b[$g]<=>$a[$g];});$c='country_name';foreach([0,1,2]as$i){echo$d[$i][$c]."\n";}

If we omit the unneccesary sorting step and assume the API delivers the data already sorted by gold_count descending (as it would seem), we can shorten this further:

while($i<3)echo json_decode(file_get_contents('http://medalbot.com/api/v1/medals'))[+$i++]->country_name."
";

Note: The line break within the string is intentional to save a byte from \n

History

  • Ommitted some quotes and braces that will throw notice's, removed the $c variable for country_name index. Thanks to @manatwork for these tipps to save even more characters.
  • Thanks to @jeroen for pointing out the shorter while loop, also switched to object access to go from 124 to 116
  • Saved 5 more bytes by calling the API within the loop. Granted, it takes longer and clobbers the API, but it's Code Golf. Needs PHP 5.5 to work because of array dereferencing.
  • Saved 2 more bytes by removing the short open tag, as per this meta answer
\$\endgroup\$
4
  • \$\begingroup\$ Thanks! I just saw all the other entries sorting and thought I missed something. \$\endgroup\$
    – YetiCGN
    Commented Aug 15, 2016 at 18:24
  • 1
    \$\begingroup\$ Why are you putting "country_name" in a variable? And anyway, as error_reporting's default value not displays notices, you can omit the double quotes. And the medalbot API seems to work without www. subdomain too. Then you not need the braces around echo. \$\endgroup\$
    – manatwork
    Commented Aug 16, 2016 at 7:24
  • \$\begingroup\$ Thanks a bunch! Well, it was late ... The $c variable is a leftover from a previous optimization that I threw away when I switched to the for loop. I guess clean coding (notice-free) is too deeply ingrained still so I don't even consider these optimizations you pointed out. So, thanks again! \$\endgroup\$
    – YetiCGN
    Commented Aug 16, 2016 at 7:37
  • \$\begingroup\$ replacing the foreach with the following forloop: for(;$i<3;)echo$d[+$i++][country_name]." " reduces it with 5 bytes. Last space being an enter offcourse. Or just as a while loop while($i<3) \$\endgroup\$
    – Jeroen
    Commented Aug 16, 2016 at 11:45
1
\$\begingroup\$

BASH + w3m + core utils, 70 bytes

w3m www.medalbot.com/api/v1/medals|grep -m3 tr|cut -f6- -d\ |tr -d \",

Looks like the output comes sorted already. Just need to throw out all of the extra text.

\$\endgroup\$
1
\$\begingroup\$

CJam (57 bytes)

"http://www.medalbot.com/api/v1/medals"gN/3>9%3<{'"/3=N}%

Online demo not available because it fetches content from the web. This cheats by not actually parsing JSON, but assuming that the structure won't change. (But then so do most of the existing answers, in different ways).

\$\endgroup\$
1
\$\begingroup\$

Python 2, 117 bytes

from requests import *
for x in get('http://www.medalbot.com/api/v1/medals').json()[:3]:
    print(x['country_name'])
\$\endgroup\$
2
  • \$\begingroup\$ Welcome to PPCG! You can save a few bytes by removing the space between import and *, and by moving the print to directly after the colon on line 2. We generally use #s instead of ** before and after for our headers. \$\endgroup\$ Commented Aug 15, 2016 at 22:00
  • 1
    \$\begingroup\$ We typically require submitters to include any third-party libraries required in the answer header. Since requests isn't a standard library module, this answer's language should be "Python 2 + requests". \$\endgroup\$
    – user45941
    Commented Aug 16, 2016 at 8:01
1
\$\begingroup\$

Clojure, 122 bytes

(fn[](mapv #(println(%"country_name"))(take 3(read-string(.replace(slurp"http://www.medalbot.com/api/v1/medals")":""")))))

No JSON library used :). Reads string from the URL, replaces colons with empty string and evals the string which results into Clojure map. Takes first 3 elements and maps eagerly function which prints country_name property of each elements.

\$\endgroup\$
1
\$\begingroup\$

Java 8 386 384 459 bytes

2 bytes saved from @Easterly Irk

My first code golf submission so I'm sure there's a way to save plenty of bytes, but oh well :)

It uses Gson to read the JSON

Requires:

import java.util.*;
import java.io.*;

Golfed code:

void p()throws Exception{List<A> a=new com.google.gson.Gson().fromJson(new InputStreamReader((InputStream)((new java.net.URL("http://www.medalbot.com/api/v1/medals").openConnection())).getContent()),new com.google.gson.reflect.TypeToken<List<A>>(){}.getType());a.sort((b,c)->c.gold_count.compareTo(b.gold_count));for(int i=0;i<3;)System.out.println(a.get(i++).country_name);}class A{String country_name;Integer gold_count;}

Ungolfed Code:

void p() throws Exception {
    List<A> a = new com.google.gson.Gson().fromJson(new InputStreamReader((InputStream)((new java.net.URL("http://www.medalbot.com/api/v1/medals").openConnection())).getContent()),new com.google.gson.reflect.TypeToken<List<A>>(){}.getType());
    a.sort((b, c) -> c.gold_count.compareTo(b.gold_count));
    for(int i=0; i<3;)
        System.out.println(a.get(i++).country_name);
}

class A {
    String country_name;
    Integer gold_count;
}
\$\endgroup\$
7
  • \$\begingroup\$ Can you remove the space in "g = new Gson()"? \$\endgroup\$
    – Riker
    Commented Aug 15, 2016 at 21:49
  • 2
    \$\begingroup\$ Wait, doesn't this need some imports to compile? \$\endgroup\$
    – Dave
    Commented Aug 15, 2016 at 22:04
  • \$\begingroup\$ import statements need to be added to byte count? \$\endgroup\$
    – yitzih
    Commented Aug 15, 2016 at 22:05
  • \$\begingroup\$ how do you calculate imports? \$\endgroup\$
    – yitzih
    Commented Aug 15, 2016 at 22:07
  • \$\begingroup\$ Don't know what the exact rules are for Java, since I haven't posted any here before, but the usual rule is that you have to count everything which is needed to make the code valid (and from quickly looking up the Java hints page I can see various suggestions about how to minimise the import code, so I guess it must be counted). But then again, I'm also trying to get my C answer to win against Java in this question, so I'm pretty biased :D \$\endgroup\$
    – Dave
    Commented Aug 15, 2016 at 22:16
1
\$\begingroup\$

R, 97 95 bytes

t=rjson::fromJSON(f="http://www.medalbot.com/api/v1/medals")
for(i in 1:3)cat(t[[c(i,2)]],"\n")

Little improvement over user5957401's answer, no sorting required, and shorter library name. Also my first attempt at golfing ;)

\$\endgroup\$
1
  • \$\begingroup\$ You can, as in every language, omit the "www." part of the domain and save 4 more bytes if your library follows the ensuing redirect. \$\endgroup\$
    – YetiCGN
    Commented Aug 18, 2016 at 12:54
1
\$\begingroup\$

Kotlin (Script), 125 121 119 bytes

java.net.URL("http://medalbot.com/api/v1/medals").readText().lines().filter{'m' in it}.take(3).map{println(it.split('"')[3])}

Runnable with kotlinc -script <filename> or through IDEA as *.kts file.

now, if we make a VERY big assumption about the format, including numbers of lines, we can trim it to:

java.net.URL("http://medalbot.com/api/v1/medals").readText().lines().slice(setOf(3,12,21)).map{println(it.split('"')[3])}

or even

java.net.URL("http://medalbot.com/api/v1/medals").readText().lines().slice(3..21 step 9).map{println(it.split('"')[3])}

Thanks to folks at Kotlin slack team for helping me trim a couple dozens of bytes!

\$\endgroup\$
1
  • \$\begingroup\$ 3 symbols shorter than Clojure and JS? I'll take that. \$\endgroup\$
    – CypherAJ
    Commented Aug 16, 2016 at 21:47
0
\$\begingroup\$

Javascript 167 bytes

x=new XMLHttpRequest();x.open("GET","http://www.medalbot.com/api/v1/medals",false);x.send()
i=-3;while(i++)console.log(JSON.parse(x.responseText)[i+2]["country_name"])
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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