快速高尔夫:金牌领袖


18

挑战

使用此处来自API的数据,输出在2016年里约奥运会上获得奥运金牌最多的三个国家的名称(即返回列表的第一个元素)。

例如,在发布时(UTC + 1,18:23 UTC,8月15日,星期一),美国,英国和中国拥有最多的金牌,因此输出为:

United States
Great Britain
China

国家名称必须用换行符分隔,并且您可能会有前导或尾随的换行符。

奥运会结束后,该程序不必按预期工作。

不允许使用URL缩短器,但可以使用JSON解析库。

这是代码高尔夫,因此以字节为单位的最短代码获胜。

我将继续努力在这里获得奥运主题的挑战

排行榜


6
你会说这是一个... 迷你高尔夫吗?
Deusovi

1
@Deusovi Ba-dum崩溃
衰减,

2
我真的希望有人发布一个Java解决方案,以便我可以看到我的C解决方案是否胜过了……
Dave

3
“英国...所以输出...英国”
trichoplax

1
@Dave NI运动员可以选择代表GB团队或爱尔兰团队。如果要求NI运动员加入GB团队,那就是UK团队。
SGR

Answers:


12

bash + w3m + grep + cut,65 59 58 54字节

w3m medalbot.com/api/v1/medals|grep -m3 m|cut -d\" -f4
  • @Joe的建议少了6个字节。
  • 多亏@YOU,少了1个字节。
  • @manatwork的建议,使Medalbot API似乎在没有www的情况下可以工作因此少了4个字节子域也是如此

2
更改cut -d '"'cut -d\"保存两个字节。如果您使用w3m而不是,则curl -s可以再保存4个。

您可以将_n更改为m

@YOU:不是真的,因为这样它会返回更多的行比预期的,即“ID”:“德国”,ID“:‘哥伦比亚’等
Master_ex

如果它们不能为1到3,则可以-m3保护。

1
@YOU:我想这对于当前的得分是正确的,并且似乎对于2016年奥运会是可以的(除非他们将美国改为美国:P)。我会改变它。
Master_ex

13

C(+插座),433个 429 280 276 270 259字节

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

因此,事实证明C不能很好地从Internet下载资源并将其解析为JSON。谁知道?

该代码(自然)具有错误检查的超级松懈,所以我猜如果badgebot.com要发送恶意数据,它们将能够触发缓冲区溢出,等等。最新的代码也期望常量的某些值(例如AF_INET = 2),到处都可能是这样,但并不能保证。

这是原始代码,它并不那么脆弱(但仍然不是很健壮或安全):

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

分解:

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

这对于服务器来说不是很好,因为我们不Connection: close\r\n作为HTTP请求的一部分发送。它也省略了Accept标头,因为Medalbot.com似乎在任何情况下都不使用压缩,并且在此之后丢失了空格Host:(再次,服务器似乎可以这样做)。似乎没有其他东西可以删除。


奥运会结束后,此程序最有可能的行为是segfault尝试读取内存位置9。信息结构,实际上可能不太危险。但是谁能告诉这些邪恶的黑客呢?


1
是的,这对那些黑客是有害的。好消息是,我们正在一个网站上,任何形式的黑客都不太可能出现……
不再转向反时钟了

1
那真是个飞跃!
NonlinearFruit

2
@NonlinearFruit是的,当您小心翼翼并直接在代码中使用实现定义的数字时,可以保存多少个字符真是令人惊讶!这已成为“最疯狂,最危险,最有可能打破但尚可运行的C语言下载方式的方法?”
戴夫

我们只是希望,小鲍比桌(Bobby Tables)在今年没有任何亲戚竞争。
GuitarPicker

可读性也是鳕鱼高尔夫运动的首批伤亡之一。。。
NonlinearFruit

12

PowerShell v4 +,88 69字节

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

使用iwr(的别名Invoke-WebRequest)获取API。我们将其作为输入参数输入到ConvertFrom-Json内置组件,该内置组件将JSON文本拉入自定义对象数组。我们将该对象数组封装在paren中,采用前三个元素[0..2],然后采用.country_name每个元素。

多对象属性至少需要v4 +,否则我们需要使用类似的东西|Select "country_name"。至少需要v3 +的ConvertFrom-Json内置版本。

PS C:\Tools\Scripts\golfing> .\olympics-gold-leader.ps1
United States
Great Britain
China

您可以放下http://www.,PS不介意http://或网站有关www.。我的PS(5.1.14393)似乎也不在乎.content
尼克T

@NickT感谢您参加高尔夫比赛。我没有意识到这ConvertFrom-Json并不需要显式地只需要.contentWeb请求的一部分,但是它也可以在我的设置中使用。
AdmBorkBork

6

R,98,112,108个字节

打高尔夫球4感谢@miff

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

第一行使用JSON库导入数据。第二行获取相关的国家名称。它按金牌升序对国家/地区进行排序,对索引进行反转,并采用前3个进行打印。


1
我认为您可以替换rev(order(a$g))order(-a$g)以保存4个字节
Miff

5

JavaScript(ES6),122字节

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

由于浏览器安全问题,此代码必须在上运行medalbot.com。但是,它没有利用这一优势,并且可能在其他地方运行。另请注意,我插入了该\n字符,但只算作一个,因为我可以将其替换为一个

Node.js(ES6),173字节

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

如果API一次返回所有数据,则本来会短得多,但是由于它分两部分返回,因此我必须将这些部分连接起来并组合起来,然后解析它们。

Node.js(ES6)+请求,138字节

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

更好,但仍不如浏览器版本好。感谢提取API!Request是一个流行的HTTP客户端库,用于简化请求,您可以在此处看到它的生效。


哪种浏览器在任何浏览器中都有效?您能将其中最短的答案放在最前面吗(排行榜)
Beta Decay

这些功能中最顶级的功能在大多数现代浏览器中都有效,而且最短。另外两个是在Node.js中的一种在服务器上编写JavaScript的方式(以及其他功能)。
市长蒙蒂

@βετѧΛєҫαγ请注意,它不适用于任何版本的IE或Safari
MayorMonty 2016年

我明白了,我渐渐挂在CORS问题
β衰变

4

bash + w3m + jq83 59个字节

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

感谢乔丹的三个字节。

多亏了您24个字节!事实证明数据已排序。哇。:D


1
您可以直接省略.|和索引结果sort_by,也可以使用[:3][]代替来保存另一个字节[0,1,2]。总计:sort_by(-.gold_count)[:3][].country_name
约旦

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

4

Java的8,261个 258字节

这使用lambda来保存几个字节,并使用网络库来获取网页。除此之外,还只是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){}}

这是我的(旧的)POJO,用于测试(和打高尔夫球):

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

更新资料

  • -3 [16-08-17]将打印语句移入 for循环
  • -5 [16-08-16]改进了正则表达式替换
  • -9 [16-08-16]删除了java.net导入

EEP。我需要保存一些字节…
戴夫

我赶上了!现在仅落后15个字节!
戴夫

好吧,我至少领先了几个小时。它对我不利,但是您可以通过使循环从3 倒数而不是向上数节省更多的字节。
戴夫

@Dave我只是尝试了布尔中断条件,i但是如果您正在考虑的话,Java不会将布尔转换为int,反之亦然。同样,您对我的最后编辑感到非常紧张。
NonlinearFruit

3

MATL,67字节

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

该功能无法在线运行,因为不允许使用功能Xiurlread)。

示例运行:

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

说明

这将内容作为字符串读取,然后将正则表达式'(?<="c.+e": ")[^"]+'应用于提取国家/地区名称。正则表达式使用with "c.+e"来代替,"country_name"以减少代码长度。

'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

3

Python 3中,202,164个字节。

Python 3不会进行简短的url / json处理。:/
没意识到API已经按黄金计数排序

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

3

Python 2中,120个 113字节

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

谢谢@Nick T和@Value Ink


1
from urllib import*并且urlopen稍后使用会节省1个字节。另外,您应该能够使用打印语句并将其放在冒号之后,从而避免缩进。
价值墨水

1
如果将urlopen对象提供给list(),这样做是否与相同.readlines()
尼克T

3

JavaScript + jQuery,114100字节

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

出于跨源请求的原因,必须从medalbot.com域(使用jQuery)运行该请求。

历史

  • -14个字节,感谢@YetiCGN
  • -2字节归功于Yay295

或在没有网络安全性的情况下运行chrome {chrome.exe --disable-web-security}
2b77bee6-5445-4c77-b1eb-4df3e5 '16

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

2

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

使用Luis Mendo 的MATL answer中的正则表达式模式的修改,并由@Jordan进行了进一步优化,因为Ruby不支持lookbehinds中的量词。

@Jordan的-18个字节。

puts Net::HTTP.get("www.medalbot.com","/api/v1/medals").scan(/"c.+"(.+)"/)[0,3]

您可以省略.map(&:last)全部12个字节,而忽略了领导//api多一个。
约旦

此外,较短的正则表达式似乎可以正常工作:/"cou.+"(.+)"/
约旦

或:/y_.+"(.+)"/
约旦

@Jordan省略了开头,导致/我的Ruby版本出现错误。也许是我所在的网络?随你。我使用的正则表达式与您建议的正则表达式略有不同,但长度相同。
价值墨水

有趣。FWIW我正在使用2.3.1。
约旦

2

PowerShell,60岁

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

与TimmyD相同的基本想法(在我发布之前没有看到他们的答案),但简短得多:-)


1
|% c*解析是如何工作的?我的意思是,确实如此,我只是尝试了一下,但这是一些奇怪的语法(它甚至在我的ISE中也突出显示为错误)。
AdmBorkBork

1
@TimmyD:ForEach-Object具有一个参数集,该参数集可扩展单个属性,或调用带有参数的方法:ForEach-Object [-MemberName] <String>。该-MemberName参数支持通配符,因此在这种情况下,它将扩展唯一与该通配符匹配的成员:country_name。也节省了不少字符;-)
Joey

2

Mathematica 96 66字节

@alephalpha找到了一种直接从文件工作的方式(无需保存),从而节省了30个字节!

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

Import将该文件作为原始JSON文件导入。 [[;;3,2]]接受1-3行,第二个条目(国家/地区名称)。


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

2

PHP,205139124116111109字节

我只想对PHP 7使用一次新的飞船运算符(编辑:它是多余的,因为不需要排序):

<?$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";}

如果我们省略了不必要的排序步骤,并假设API传递了已经按gold_count降序排序的数据(看起来是这样),则可以进一步缩短此时间:

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

谢谢!我刚刚看到所有其他条目都在排序,以为我错过了一些东西。
YetiCGN '16

1
为什么将“ country_name”放在变量中?而且,由于error_reporting的默认值不显示通知,因此您可以省略双引号。而且Medalbot API似乎在没有www的情况下也可以工作。子域。然后,您就不需要括号了echo
manatwork '16

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!
YetiCGN

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

1

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.


1

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


1

Python 2, 117 bytes

from requests import *
for x in get('http://www.medalbot.com/api/v1/medals').json()[:3]:
    print(x['country_name'])

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.
NoOneIsHere

1
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".
Mego

1

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.


1

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

Can you remove the space in "g = new Gson()"?
Rɪᴋᴇʀ

2
Wait, doesn't this need some imports to compile?
Dave

import statements need to be added to byte count?
yitzih

how do you calculate imports?
yitzih

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
Dave

1

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


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.
YetiCGN

1

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!


3 symbols shorter than Clojure and JS? I'll take that.
CypherAJ

0

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"])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.