challenge LL Golf Hole 1 - tinyurl.comを使ってURLを短縮する

tinyurl.com( http://tinyurl.com/ )のサービスを利用し、 http://ll.jus.or.jp/2008/info/xgihyo というURLを短縮しなさい。tinyurl.comのalias機能は使わないものとする。 なお、参考までに短縮したURLは http://tinyurl.com/5mngx8 となる。

余力のあるものはこのプログラムを短くしてみたり、短くしてみたり、短くしてみよ。

※LL Future実行委員の高野光弘です。この出題は LL Future公式の出題であり、優れたものについてはLL Golfのセッションでご紹介させていただくかもしれません。ご理解の上、ご投稿ください。また、LL Futureのチケットは現在も発売中です。よろしければ、メインイベントの方にもぜひご参加ください。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#!/usr/bin/env ruby

require 'rubygems'
require 'mechanize'

def tinyurl(url, _alias = nil)
    m = WWW::Mechanize.new
    res = m.get('http://tinyurl.com/')
    form = res.forms[1]
    form['url'] = url
    form['alias'] = _alias if _alias
    res = m.submit(form)
    regexp = Regexp.new('.*(http\:\//tinyurl.com/[a-z0-9-]+).*')
    match = regexp.match(res.body)
    return match[1] if match
end

if __FILE__ == $0 then
    puts tinyurl('http://ll.jus.or.jp/2008/info/xgihyo')
end

Posted feedbacks - Nested

Flatten Hidden
RSSでは配信されてないみたいですけどこれもお題ですかね?
なんか、1-linerで済んじゃったんですけど...
そういうことじゃないのかなぁ...

perl -MLWP::Simple -E 'say get(q{http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo})'

回答例が異様に長くてすみません〜。趣旨のご理解ありがとうございます。

まさにそういう感じのコードを待ってました!ありがとうございます!

TinyURL APIとな!?

1
ruby -ropen-uri -e "puts open('http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo').read"

1バイトだけ短く。

1
ruby -rnet/http -e "puts Net::HTTP.get('tinyurl.com','api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo')"

こそこそ・・・

1
2
3
#! /usr/bin/env ruby
require 'open-uri'
puts *open('http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo')
一応gorubyの例として
1
goruby -ropen-uri -e'pr *op("http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")'
もっと短くなりました。 :D

perl -MLWP::Simple -E 'say get "http://easyurl.jp/edz"'

おおう! あれ?でも、tinyurlを二回使おうとすると変なことに。

と思いつつ、http's':// の https://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2 008/info/xgihyo を圧縮した http://tinyurl.com/6hyq2m でアクセスしてみたら・・・キター(笑

Lisp 系は Golf 向きじゃないかなあ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
(use rfc.http)

(print
 (cond
  ((#/http:\/\/tinyurl.com\/[a-z0-9-]+/
    (values-ref
     (http-get "tinyurl.com"
               "create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")
     2))
   => (cut <> 0))
  (else #f)))
HTTPを使用しました。golfっていう感じじゃないけど。
$ runhaskell TinyURL.hs
http://tinyurl.com/5mngx8
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
module Main where                                                                                                            

import Control.Arrow
import Data.Maybe
import Network.HTTP
import Network.URI

main = f "http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo"

f = runKleisli $ arr parseURI >>> arr fromJust >>> arr request
      >>> Kleisli simpleHTTP >>> arr (either show rspBody) >>> Kleisli putStrLn

request uri = Request {rqURI = uri, rqMethod = GET, rqHeaders = [], rqBody = ""}
UNIXシェル上の一行野郎じゃないといけない雰囲気を感じたので努力してみました。
ライブラリが組み込まれたコアを利用する必要があります。
SBCLで書いていますが、他の処理系でも同じような感じになると思います。
1
sbcl --noinform --core your.core --eval '(progn(princ(kmrcl:awhen(drakma:http-request"http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")(when(ppcre:scan"http://tinyurl.com\/[a-z0-9-]+"kmrcl:it)kmrcl:it)))(terpri)(quit))'

ごめんなさいごめんなさい

1
2
#/bin/sh
wget -qO - http://tinyurl.com/api-create.php?url=$0

ではpure bashで。要enable-net-redirections。

1
(echo -ne 'GET /api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo\r\nHost: tinyurl.com\r\n\r\n';while read s;do :;done<&1;echo $s>&2)>/dev/tcp/tinyurl.com/80
余談ですが、#6844の先頭行が間違ってました。#! と書かないと。
なくても動くけど・・・。

Cで書きたい。でも、どっちかというとこれはbash ワンライナー?

1
echo "main(){printf(\"`curl 'http.php?url=http://ll.jus.or.jp/2008/info/xgihyo'`\");}" | (gcc -xc -;./a.out)

HttpURLConnectionを用いてサンプルのRubyプログラムをできるだけ忠実にJavaに変換しました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import java.net.*;
import java.io.*;
import java.util.regex.*;

public class TinyURL {
    public static final String SAMPLE_URL = "http://ll.jus.or.jp/2008/info/xgihyo";
    private static final Pattern TINYURL_PAT = Pattern.compile("http://tinyurl\\.com/[a-z0-9-]+");
    private static final String CONVURL = "http://tinyurl.com/create.php";

    public static String tinyURL(String url, String alias) throws IOException {
        URL tinyUrl = new URL(CONVURL);
        HttpURLConnection uc = (HttpURLConnection) tinyUrl.openConnection();
        String query = "url=" + URLEncoder.encode(url, "UTF-8");
        if (alias != null)
            query += "&alias=" + URLEncoder.encode(alias, "UTF-8");
        byte[] ba = query.getBytes("us-ascii");
        uc.setRequestMethod("POST");
        uc.setDoOutput(true);
        uc.setFixedLengthStreamingMode(ba.length);
        uc.connect();
        try {
            OutputStream os = uc.getOutputStream();
            os.write(ba);
            BufferedReader r = new BufferedReader(new InputStreamReader(uc.getInputStream(), "iso-8859-1"));
            String line;
            while ((line = r.readLine()) != null) {
                Matcher m = TINYURL_PAT.matcher(line);
                if (m.find()) {
                    return m.group();
                }
            }
            return null;
        } finally {
            uc.disconnect();
        }
    }
    
    public static String tinyURL(String url) throws IOException {
        return tinyURL(url, null);
    }

    public static void main(String[] args) throws IOException {
        System.out.println(tinyURL(SAMPLE_URL));
    }
}

Rだって、ワンライナーくらいできるんだからね!(趣旨が違う)

1
R -q -e "readLines('http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo', warn=F)"

Squeak Smalltalk で。

1
(HTTPSocket httpGet: 'tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo') contents

どれだけ圧縮できるサービスを利用するかって話に帰着しちゃうのかな

1
curl url.ms/qJI

readしなくても*で展開する方法もあります

1
ruby -ropen-uri -e'puts *open("http://url.ms/qJI")'
1
2
3
4
5
6
7
8
9
private import std.stdio, std.string, std.socket, std.socketstream;

void main() {
    auto s = new SocketStream(new TcpSocket(new InternetAddress("tinyurl.com", 80)));
    scope(exit) s.close;
    
    s.writeString("GET /api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo HTTP/1.1\r\nHost: tinyurl.com\r\n\r\n");
    foreach(char[] line; s) if(line.startsWith("http://")) writeln(line);
}

こういうことですか?

1
2
"http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo"からHTTPデータ取得
それを"http:\/\/tinyurl.com\/[a-z0-9-]+"で正規表現マッチして表示
ワンライナー ブームにGroovyも便乗します。
2行だけど ><

実行結果
------------------------
http://tinyurl.com/5mngx8
1
2
url = new URL("http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")
println url.getText()
1
groovy -e "print new URL('http://url.ms/qJI').text"

ネット上で、この手の問題を解くためのプログラム集を見つけたので、それを活用して解いています。

Gauche での one-liner となっており、トータルで 163byte です。どう書く?org の問題だったら大抵のものは 163byte 前後で解けると思います。

1
gosh -ugauche.process -urfc.http -E'with-output-to-process"gosh"(cut print(values-ref(http-get"ja.doukaku.org""/comment/6838/download")2)):output"/dev/tty"' -Eexit

この仕組みは面白いですね :-)

Rubyでも書いてみました。

1
ruby -ropen-uri -e'eval open("http://ja.doukaku.org/comment/6891/download").read'
1
ruby -ropen-uri -e'eval open("http://tinyurl.com/5kzlfb").read'
実行はしないでください。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/env ruby

require 'rubygems'
require 'mechanize'

$a = ('0'..'9').to_a + ('a'..'z').to_a

def num2str(n)
  s = ""
  while (n > 0)
    n,r = n.divmod 36
    s << $a[r]
  end
  return s.empty? ? "0": s
end

m = WWW::Mechanize.new
s = ""
#n = 539933837
n = 0
loop {
  begin
    s = "http://tinyurl.com/" + num2str(n)
    res = m.get(s)
    break if (res.uri.to_s == "http://ll.jus.or.jp/2008/info/xgihyo")
  rescue
  end
  n += 1
}

puts s

PHPがなかったので登録して書いてみます。第二問も出るのかな?

1
<?=join(file('http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo'));
Console.in を変更して無理矢理短く。インタプリタ上で実行。
1
Console.setIn(new java.net.URL("http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo").openStream);print(readLine)
WWW::Shortenモジュールを利用する。
1
perl -MWWW::Shorten::TinyURL -e 'print makeashorterlink("http://ll.jus.or.jp/2008/info/xgihyo")'
WWW::Shortenモジュールを利用する。
1
perl -MWWW::Shorten::TinyURL -e 'print makeashorterlink "http://ll.jus.or.jp/2008/info/xgihyo"'
#6827 の前に考えてたものを出し忘れていました。
しかしやはりXSLTはGolfに向かない。
1
2
3
<html x:version="2.0" xmlns:x="http://www.w3.org/1999/XSL/Transform">
<x:value-of select="unparsed-text('http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo')"/>
</html>
シンプルにいきます. とりあえずwithSocketsDoは省略で227打.
1
2
3
4
5
import Network
import IO
main=do h<-connectTo"tinyurl.com"(PortNumber 80);hPutStr h"GET /api-create.php?u
rl=http://ll.jus.or.jp/2008/info/xgihyo HTTP/1.0\r\nHost: tinyurl.com\r\n\r\n";h
Flush h;hGetContents h>>=putStr.last.lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
using System;
using System.Net;
using System.Text.RegularExpressions;

class Program
{
    static void Main(string[] args)
    {
        string url = "http://tinyurl.com/create.php?url=" + args[0];
        WebClient wc = new WebClient();
        string r = wc.DownloadString(url);
        MatchCollection mc = Regex.Matches(r, "<blockquote><b>([^<]+)</b>");
        Console.WriteLine(mc[1].Groups[1].Value);
    }
}
lxml
1
2
3
4
5
6
7
from urllib2 import urlopen
from lxml.html import parse, submit_form

form = parse(urlopen('http://tinyurl.com/')).getroot().forms[1]
form.fields['url'] = 'http://ll.jus.or.jp/2008/info/xgihyo'
root = parse(submit_form(form)).getroot()
print root.xpath('//blockquote/b')[1].text

parseに直接urlを渡すように修正。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
--- a/lxml.py   Tue Sep 02 15:50:19 2008 +0900
+++ b/lxml.py   Tue Sep 02 15:57:27 2008 +0900
@@ -1,7 +1,6 @@
-from urllib2 import urlopen
 from lxml.html import parse, submit_form

-form = parse(urlopen('http://tinyurl.com/')).getroot().forms[1]
+form = parse('http://tinyurl.com/').getroot().forms[1]
 form.fields['url'] = 'http://ll.jus.or.jp/2008/info/xgihyo'
 root = parse(submit_form(form)).getroot()
 print root.xpath('//blockquote/b')[1].text

Rhinoで。そのまんますぎる。

1
readUrl("http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import re
from urllib2 import urlopen
from ClientForm import ParseResponse
from htmllib import HTMLParser
from formatter import NullFormatter

response = urlopen('http://tinyurl.com/')
form = ParseResponse(response, False)[1]
form['url'] = 'http://ll.jus.or.jp/2008/info/xgihyo'

h = HTMLParser(NullFormatter())
h.feed(urlopen(form.click()).read())
h.close

r = re.compile(r'http://tinyurl.com/\w+')
for i in h.anchorlist:
    if r.match(i):
        print i
scala.io.Sourceを使ってストリームを出力してみる。
Scalaはscalaパッケージから相対的に名前空間にアクセスできるのでscala.io.Sourceではなくてio.Sourceでも問題ない。
なおSourceはソースファイルを読み込むためのクラスであるため本来の使い方じゃないし、文字エンコードもutf-8をデフォルトにしているので、アレではある。
scala h1.scala で実行。
1
for(c<-io.Source.fromURL("http://tinyurl.com/api-create.php?url=http://ll.jus.or.jp/2008/info/xgihyo")) print(c)
かなり無駄なバージョン。
GETですけどAPIを使わずにTinyURLを取得して、Regexで抜き出してます。
scala h13.scala で動かします。
1
2
3
4
5
import io._
val url="http://ll.jus.or.jp/2008/info/xgihyo"
val t=new StringBuilder;for(c<-Source.fromURL("http://tinyurl.com/create.php?url="+url))t.append(c);
val r="""(?is).*characters:\s+<blockquote><b>([^\s]*)</b><br>.*</blockquote>.*""".r
t.toString match{case r(tu)=>println(tu) case _ =>}

普通に書いてみた

1
require'open-uri';puts open('http://tinyurl.com/create.php?url=http://ll.jus.or.jp/2008/info/xgihyo',&:read)[%r|http://tinyurl.com/\w+|]

Index

Feed

Other

Link

Pathtraq

loading...