Fork me on GitHub

2012/05/17


このエントリーをはてなブックマークに追加
逆FizzBuzz問題 (Inverse FizzBuzz) - 猫とC#について書くmatarilloの雑記

逆FizzBuzz問題 (Inverse FizzBuzz) General | Inverse Fizzbuzz - just another scala quant を日本語にしました。 ちなみに...

http://d.hatena.ne.jp/matarillo/20120515/p1
逆FizzBuzzって、オートマトンなので正規表現を使うと楽に出来るはず。
#!perl
use strict;
use warnings;
use Test::More;

sub inv_fizzbuzz {
  my ($fz$n$pat) = (''1join ',*?'@_);
  while (1) {
    $fz .= $n % 15 > 0 ?
             $n % 3 > 0 ?
               $n % 5 > 0 ?
                 ',''buzz,''fizz,''fizzbuzz,';
    if ($fz =~ /($pat)/) {
      my $rhs = $1;
      my $lhs = substr($fz0index($fz$rhs) + 1);
      $lhs =~ s/(fizz|buzz)//g;
      $rhs =~ s/(fizz|buzz)//g;
      $lhs = length($lhs);
      $rhs = $lhs + length($rhs||'');
      return [$lhs$rhs];
    }
    $n++;
  }
}

is_deeply(inv_fizzbuzz('fizz'), [33]);
is_deeply(inv_fizzbuzz('buzz'), [55]);
is_deeply(inv_fizzbuzz('fizz''buzz'), [35]);
is_deeply(inv_fizzbuzz('buzz''fizz'), [56]);
is_deeply(inv_fizzbuzz('fizz''fizz''buzz'), [610]);
is_deeply(inv_fizzbuzz('fizz''fizz'), [69]);
is_deeply(inv_fizzbuzz('fizz''buzz''fizz'), [36]);
is_deeply(inv_fizzbuzz('fizzbuzz''fizz'), [1518]);

done_testing;
追記
Vimだとこうか?
functions:inv_fizzbuzz(...)
  let [fz, np= [''1join(a:000',\{-}')]
  while 1
    let fz .= n%15>0?n%3>0?n%5>0?",""buzz,""fizz,""fizzbuzz,"
    let m = matchstr(fz, p)
    if len(m) > 0
      let lhs = len(split(fz[:stridx(fz, m)-1], ','1))
      return [lhs, lhs + len(split(m, ','1))-1]
    endif
    let n += 1
  endwhile
endfunction

2012/05/10


このエントリーをはてなブックマークに追加
mattn/go-mruby - GitHub

go-mruby make interface to embed mruby into go.

https://github.com/mattn/go-mruby
Matzさんにヒントも貰いながら、さっき出来ました。
メソッドは RunEval があり、mrubyの評価値を取得する事が出来ます。Go言語から渡した引数が ARGV になります。なので mruby 上では String とは限りません。
package main

import "github.com/mattn/go-mruby"

func main() {
    mrb := mruby.New()
    defer mrb.Close()

    println(mrb.Eval(`"hello " + ARGV[0]`"mruby").(string))

    for _, i := range mrb.Eval(`ARGV.map {|x| x + 1}`123).([]interface{}) {
        println(i.(int32)) // 2 3 4
    }
}
良かったら遊んでみて下さい。

2012/05/09


このエントリーをはてなブックマークに追加
しなちく 「お前それ、シナチクって言いたかっただけやろ」

...
...
...
...

「そうですが、何か」

mruby で mruby-httpmruby-uv を使い、sinatra ライクなのが動くまでに到った。
ショボいアプリケーションなら書ける様になったけど、mrubyはまだファイルIOが出来ないのでアプリと呼べる様な物が動くにはまだまだ先。
require 'HTTP'
require 'UV'

# {{{
module Sinatic
  @routes = { 'GET' => [], 'POST' => [] }
  def self.route(method, path, opts, &block)
    @routes[method] << [path, opts, block]
  end
  def self.do(r)
    @routes[r.method].each {|path|
      if path[0] == r.path
        param = {}
        r.body.split('&').each {|x|
          tokens = x.split('=')
          param[tokens[0]] = HTTP::URL::decode(tokens[1])
        }
        body = path[2].call(r, param)
        return [
          "HTTP/1.0 200 OK",
          "Content-Type: text/html; charset=utf-8",
          "Content-Length: #{body.size}",
          """"].join("\r\n") + body
      end
    }
    return "HTTP/1.0 404 Not Found\r\nContent-Length: 10\r\n\r\nNot Found\n"
  end
  def self.run()
    s = UV::TCP.new()
    s.bind(UV::ip4_addr('127.0.0.1'8888))
    s.data = []
    s.listen(50) {|x|
      return if x != 0
      c = s.accept()
      c.read_start {|b|
        h = HTTP::Parser.new()
        h.parse_request(b) {|r|
          i = b.index("\r\n\r\n") + 4
          r.body = b.slice(i, b.size - i)
          c.write(::Sinatic.do(r)) {|x| c.close }
        }
      }
      s.data << c
    }
    while 1 do
      NOTE: must be call run_once to run GC.
      UV::run_once()
    end
  end
end

module Kernel
  def get(path, opts={}, &block)
    ::Sinatic.route 'GET', path, opts, &block
  end
  def post(path, opts={}, &block)
    ::Sinatic.route 'POST', path, opts, &block
  end
end
# }}}

get "/foo.js" do
'$(function() {
  $("#foo").text("hello world");
})'
end

get "/" do
'
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="/foo.js"></script>
<div id="foo"></div>
<form action="/add" method="post">
<label for="name"/>お名前</label>
<input type="text" id="name" name="name" value="">
<input type="submit">
</form>
'
end

post "/add" do |rparam|
"
<meta http-equiv=refresh content='2; URL=/'>
通報しますた「#{param['name']}
"
end


Sinatic.run

# vim: set fdm=marker:

2012/05/02


このエントリーをはてなブックマークに追加
BigQueryが正式版としてリリースされたようです。
Google、ビッグデータ分析サービス「BigQuery」を一般公開 - ITmedia ニュース

米Googleは11月14日(現地時間)、同社のクラウド上でいわゆる「ビッグデータ」を分析する企業向けサービス「Google BigQuery Service」のプレビュー版を公開したと発表した。正式版は有料になる見込みだが、現在は無料で利用できる。

http://www.itmedia.co.jp/news/articles/1111/15/news028.html
サンプルデータも幾つかある様で、githubのリポジトリ情報を格納している物もあったので試しにGo言語からクエリを発行して問い合わせてみた。 以下コード。
package main

import (
    "code.google.com/p/goauth2/oauth"
    "code.google.com/p/google-api-go-client/bigquery/v2"
    "encoding/gob"
    "fmt"
    "log"
    "net/http"
    "net/http/httptest"
    "net/url"
    "os"
    "os/exec"
    "path/filepath"
    "runtime"
    "time"
)

func osUserCacheDir() string {
    switch runtime.GOOS {
    case "darwin":
        return filepath.Join(os.Getenv("HOME"), "Library""Caches")
    case "linux""freebsd":
        return filepath.Join(os.Getenv("HOME"), ".cache")
    }
    log.Printf("TODO: osUserCacheDir on GOOS %q", runtime.GOOS)
    return "."
}

func tokenFromWeb(config *oauth.Config) *oauth.Token {
    ch := make(chan string)
    randState := fmt.Sprintf("st%d", time.Now())
    ts := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
        if req.URL.Path == "/favicon.ico" {
            http.Error(rw, ""404)
            return
        }
        if req.FormValue("state") != randState {
            log.Printf("State doesn't match: req = %#v", req)
            http.Error(rw, ""500)
            return
        }
        if code := req.FormValue("code"); code != "" {
            fmt.Fprintf(rw, "<h1>Success</h1>Authorized.")
            rw.(http.Flusher).Flush()
            ch <- code
            return
        }
        log.Printf("no code")
        http.Error(rw, ""500)
    }))
    defer ts.Close()

    config.RedirectURL = ts.URL
    authUrl := config.AuthCodeURL(randState)
    go openUrl(authUrl)
    log.Printf("Authorize this app at: %s", authUrl)
    code := <-ch
    log.Printf("Got code: %s", code)

    t := &oauth.Transport{
        Config:    config,
        Transport: http.DefaultTransport,
    }
    _, err := t.Exchange(code)
    if err != nil {
        log.Fatalf("Token exchange error: %v", err)
    }
    return t.Token
}

func openUrl(url string) {
    try := []string{"xdg-open""google-chrome""open"}
    for _, bin := range try {
        err := exec.Command(bin, url).Run()
        if err == nil {
            return
        }
    }
    log.Printf("Error opening URL in browser.")
}

func tokenCacheFile(config *oauth.Config) string {
    return filepath.Join(osUserCacheDir(), url.QueryEscape(
        fmt.Sprintf("go-api-demo-%s-%s-%s", config.ClientId, config.ClientSecret, config.Scope)))
}

func tokenFromFile(file string) (*oauth.Token, error) {
    f, err := os.Open(file)
    if err != nil {
        return nil, err
    }
    t := new(oauth.Token)
    err = gob.NewDecoder(f).Decode(t)
    return t, err
}

func saveToken(file string, token *oauth.Token) {
    f, err := os.Create(file)
    if err != nil {
        log.Printf("Warning: failed to cache oauth token: %v", err)
        return
    }
    defer f.Close()
    gob.NewEncoder(f).Encode(token)
}

func getOAuthClient(config *oauth.Config) *http.Client {
    cacheFile := tokenCacheFile(config)
    token, err := tokenFromFile(cacheFile)
    if err != nil {
        token = tokenFromWeb(config)
        saveToken(cacheFile, token)
    } else {
        log.Printf("Using cached token %#v from %q", token, cacheFile)
    }

    t := &oauth.Transport{
        Token:     token,
        Config:    config,
        Transport: http.DefaultTransport,
    }
    return t.Client()
}

func main() {

    var config = &oauth.Config{
        ClientId:     "XXXXXXXXXXXXX.apps.googleusercontent.com",
        ClientSecret: "YYYYYYYYYYYYYYYYYYYYYYYY",
        Scope:        bigquery.BigqueryScope,
        AuthURL:      "https://accounts.google.com/o/oauth2/auth",
        TokenURL:     "https://accounts.google.com/o/oauth2/token",
    }

    bigqueryService, err := bigquery.New(getOAuthClient(config))
    if err == nil {
        table, err := bigqueryService.Jobs.Query("XXXXXXXXXXXXX", &bigquery.QueryRequest {
            Query: "SELECT repository_description FROM [publicdata:samples.github_timeline] where repository_url = 'https://github.com/mattn/growl-for-linux'",
        }).Do()
        if err == nil {
            for _, row := range table.Rows {
                for _, f := range row.F {
                    println(f.V)
                }
            }
        }
    }
}
XXXXXXXXXXXXX にはプロジェクトIDを(ClientIDの一部になってるみたい)、YYYYYYYYYYYYYYYYYYYYYYYY には ClientSecret を埋めて実行して下さい。発行しているクエリは以下。
SELECT repository_description FROM [publicdata:samples.github_timeline] where repository_url = 'https://github.com/mattn/growl-for-linux'
これを実行すると以下のデータが得られた。
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
Growl Implementation For Linux #growl4linux
実行はそれほど速くありませんでした。巨大なデータをオンラインで扱えるインフラとしては面白いかなーと思った。
ただ最近の API は OAuth な物が多く、実行するにはアクセストークンが必要になり、アクセストークンを得るにはブラウザを起動する必要がある。今回 Go言語のdatabase/sqlドライバの一つに加えようと思ってけどちょっと難しいかも。どっちかっていうとユーザ単位にアクセストークンを取らせる様なコンシューマサービス向けなのかな。