読者です 読者をやめる 読者になる 読者になる

YAMAGUCHI::weblog

太めの女性の軍団が、本部をグルリと囲んでます。 現在恋人募集中! ポンコツミニチュア三等兵、中井です。

イタリア旅行記

misc

はじめに

こんにちは。気がつけばまたブログの更新が滞っていました。7月最終週〜8月第一週にかけてイタリアに旅行に行ってきたので、旅行記を残しておこうと思います。

旅程

今回の旅行ではイタリアの中央の3都市(フィレンツェベネチア、ローマ)を巡る旅行をしてきました。日程は7/28-8/5の7泊9日。事前情報でフィレンツェベネチアは街が小さいと聞いていたので、この2都市では2泊、ローマでは3泊の予定としました。各都市の移動は高速鉄道でした。

都市 日程
フィレンツェ 7/28-7/30
ベネチア 7/30-8/1
ローマ 8/1-8/4

またガイドブックは次のものを購入した。どれでも良かったけれど、立ち寄る3都市の情報が程よく均等に載っていたので。現地でもレストラン選びなどの時に役に立った。

イタリア (ララチッタ)

イタリア (ララチッタ)

気付き

色々と細かく書けると思うのですが、まずは旅程全体を通してと各都市での気付きを箇条書きで列挙。写真を見てからだとよりわかってもらえるかもしれないので置いときます。

全体として

  • イタリアではクレジットカード決済ではPIN番号を聞かれ、サインでの決済はほぼできない。おそらく偽装カード対策か。また現金払いのみのところも多い。
  • 英語は案外通じるが、イタリア語を幾つか覚えていったほうが当然楽しい。
    • 看板や印刷物などに対してはGoogle翻訳がものすごく便利。(後述)
  • 今回の日程(夏期)では日没は20:30前後で、街は日没に合わせて夜が始まる感じ。飲食店も日付が変わるまで開いている所も多い。
  • どの展示施設も事前にインターネット予約しておくべき。(後述)
    • 特にバチカン博物館は当日2時間近く炎天下で待つ人もいた。
  • 寺院などを巡る際は服装や荷物の大きさに注意。
    • 肌の露出があると入場拒否される可能性があるので、男性でも大きめのストールなどを持って行くと便利。(腰にまいて足全体を隠せる)
    • かばんもレンズ一本が入るカメラバック程度の大きさにおさえておかないと、クロークに預けなければならなかったり、下手をするとクロークすら無いので注意。
  • とにかく日差しが強く直射日光を浴びていると非常に暑い。一旦日陰などに入ると涼しい。帽子は持っていった方がいい。(自分は持って行かなかった)
  • 上記の状況なので水をとにかく飲んでいた。観光地の露店などでは500mlで€1とか取られるけど、スーパーなどにいけば1.5Lで€0.5とかで買える。
    • 何も言わないと炭酸入りが出てくる可能性もあるので、炭酸水(伊: frizzante)か自然水(伊: naturale)か表記を確認する。
    • 飲食店でも水は有料。1-1.5Lで€1-2くらい。その時も "still water" など水の種類を言うこと。
    • 街中に泉があり、飲用可のところが多数。水質は硬い。(後述)
  • 街中にトイレが少ない。
    • 食事のときや施設に行ったときトイレを都度借りたほうが良い。
    • 夏は特に水を四六時中飲んでいるのでトイレ探しは結構大事な要素。
    • 公衆トイレもあることもあるがたいてい有料。(ベネチアでは1回€1.5だった)
  • 公共WIfiはそんなにない。出来ることならSIMカードを買おう。(後述)
    • 飲食店でも「Free Wifi」の看板を掲げて入るものの、店員にいちいち聞くのは面倒。
    • 訪れた3都市では4Gが入りました。
  • 飲食店に飛び込みで入らないように注意。ボッタクリに合わないための対応。
    • 店に入る前にTripAdvisorやGoogle Placesで評価を確認。星の数が高くても「5つ星かつコメントなし」の評価ばかりのところは怪しい。日本語のレビューで高評価のところは結構信頼できる。
    • 疲れきっていたときにこれをしないで飛び込んだ店で見事にぼられた。(後述)
  • Google Mapsは最高に役に立った。
    • 周辺情報(レストラン、スーパー、薬局、観光スポット等々)
    • ルート検索での公共交通機関情報(バスのルート番号、水上バスの番号等々)
  • チップは本当にサービスに満足した時に支払う、という文化を感じた。
    • 向こうが欲しいと思っている場合はサービス料を予め上乗せしていたり、席料(コペルト)を取っていることも多い。

フィレンツェ

  • ルネサンス文化が色濃く残る街。街もルネサンス時代から残る建物が多く、景観の保存にも力を入れている印象。
  • 完全な観光都市というわけではなく、地元の人は観光以外の産業でも生活している印象。
    • 街も観光のみではなく、生活に必要な施設(スーパー、百貨店等々)も数多く見られる。
    • 飲食店・商品の価格も観光価格という印象はそこまで受けなかった。
  • 食事はトスカーナ料理なので肉が多い。
  • 主要箇所は全部徒歩で移動可能。むしろタクシーを捕まえるほうが難しい。
  • ウフィッツィ美術館をしっかり見たければ3時間以上は確保しておきたい。

ベネチア

  • 街並みは綺麗だが、水路は結構汚い。ただ臭くはなかった。路地は迷路のようで非常に楽しい。フィレンツェよりは広いものの、頑張れば全部徒歩で回れる広さ。
  • ご飯は他の都市に比べて2割ほど値段が高い。
    • ぼったくりも多い。旅行中唯一ぼったくられたのがベネチア
  • バーカロという立ち飲み居酒屋が最高に良い。ベネチアに行ったら食事の時間は気にせず、小腹が空いたらバーカロで軽く飲んで移動、というのが良いかもしれない。
  • 水上バスは時間帯によっては非常に混む。
  • ゴンドラは値段交渉をしようと思ったが軒並み公定料金で自分がまわったところでは交渉ができるところがなかった。
    • 値段は30分で€80と割高。二度と来ることもないと思ったので乗った。
    • ゴンドラに乗らなくても十分ベネチア観光は楽しめるので、乗らないという選択肢もあり。
  • サンマルコ広場は夜に行くと人も落ち着いていて綺麗。
    • サンマルコ寺院は荷物を預けないと入れない場合がある。
    • 満潮時に広場が浸水することがある。今回はたまたま少しだけ浸水した様子を見ることができた。
  • 完全な観光都市なので客引きなどは多い。

ローマ

  • 泉が街の至る所にある。
  • タクシーは色が白いものは安全。
  • カラカラ浴場跡での野外オペラの帰りはタクシーが必須。カーテンコール前に席を立てばすぐにタクシーに乗れる。
    • タクシー会社がタクシー待ちの列を整理していて、ボッタクリの心配もない。ホテルの人が「スペイン広場まで€13以上請求してくるようならすぐにぼったくりだと訴えろ」と事前に忠告してくれたが、見事€13で到着した。
  • スリが結構いる。細心の注意を。財布をポケットに入れておくなんて「スってくれ」と言っているようなもの。
  • 結構スーパーが多い。
  • 当たり前のように古代ローマ時代の遺跡が街中にある。とにかくスケールが大きく圧倒される。
  • バス網が発達していて非常に便利。地下鉄もそこそこ便利。
    • バス、地下鉄が時間を守ることはまずない。時間前に出発するとか当たり前。
    • バスではチケットを確認していない。適当。
  • ローマ市内から空港まではタクシーでのボッタクリが横行したため、最近は固定料金を設定することが多いとのこと。

細かなTipsなど

箇条書きで(後述)としたところに関して追記していきます。

インターネット予約

とにかく並びまくるので、出来る限りインターネットでチケットを予約していったほうが良い。またもし突発的にどこかの施設に行きたくなったとしても、携帯からインターネット予約でチケットが買えるならそのほうがよいこともある。とにかく炎天下長時間並ぶのは本当に疲れる。自分が予約していった施設は次。

Google翻訳

Word Lensを統合してから海外旅行に欠かせないアプリケーションになりました。人だったら英語でコミュニケーションをすることも可能ですが、掲示物・印刷物はGoogle翻訳がないと内容の確認が不可能です。試しにベネチア水上バスのチケットで見てみましょう。こちらがオリジナル。イタリア語だけでまったくわかりません。

これをGoogle翻訳にかけるとこうなります。

f:id:ymotongpoo:20150809210318p:plain

なんとなく分かる!

他にも店舗の営業時間やお店のメニューの解読にも役に立ちます。(後述)

プリペイドSIMカード

この時代なので旅行中に現地で情報を集めることはあたりまえだと思う。海外用のWifiルーターを借りてもいいんだろうけど、割高だし余計な荷物が増えるのは面倒。イタリアではVodafone、TIM、3IT、Windなどいくつかのキャリアがありますが、Vodafoneの情報が多かったのと、最初に泊まる都市のフィレンツェVodafoneのショップがあったので、そこで購入しました。

購入したのは「Vodafone Holiday」というプランのプリペイドSIM。300分の通話、SMS300通、4G回線の接続で2GBまでのデータ通信がついて€30という良心的な価格設定。

購入は簡単で、Vodafoneの店舗へ行き、「プリペイドSIMをくれ」と言ってパスポートを提示しただけです。するとユニバーサルSIMをくれるので裏面のスクラッチを削ってPIN番号を取得。

自分が使っている携帯はSIMフリー端末なので、挿して再起動したらPIN番号を聞かれるので入力したら使えました。注意事項として、SIMを挿してからアクティベーションまでに2時間は携帯の電源をオンにしてはいけないとのこと。その間に電源をオンにすると、SIMのサーバ側での設定がおかしくなることがあるそうです。というか自分がそうなりました。

ぼったくりについて

ぼったくりには遭わないように気をつけていたのですが、ベネチアで歩きまわりすぎて疲れてたので、レビューを調べもせずに適当に入ったトラットリアでふっかけられて口論になりました。値下げはしてもらったものの予算より1500円ほど多く取られました。こちらのサイト にあるところの重量制というやつです。「おすすめですよ」と言われたので「お腹は空いていないから、1人分を2人で分けるけどいいかな」と聞いたら「もちろんOK」と言われたのでそのまま注文。(その時は重量制であることを知らず、ただ具材についての説明を受けただけ。)

食べ終わって会計が出てきたら表示の価格€9に対しての4倍の€36という値段。これはおかしいとメインのウェイターを呼ぶと

  • ウェイター「これは重量制なのは当たり前だ」
  • 私「中身について聞いた時に何も言わなかっただろ」
  • ウェイター「それは中身についてしか聞かれてないからだ」
  • 私「特筆すべきことは無いかと聞いただろ」
  • ウェイター「俺の仕事は中身を説明することだけだ」
  • 私「中身の説明にグラム数が入ってないだろ!」
  • ウェイター「グラム数を説明する義務はない」
  • 私「言い値じゃないか。大体お腹いっぱいだから1人前の量だと言ったのに、他のパスタも400gもだすのか。」
  • ウェイター「それは違う。これだけ特別」
  • 私「あきらかに値段ふっかけてるじゃないか」

と押し問答の末、€20になりました。とはいえ、まずくはなかったものの、そこまで美味しいかったわけでもなく...完全なぼったくりではなかったものの、良い勉強になりました。

そもそもこれはメニューをもらった時点でGoogle翻訳にかけておけばよかったのですが、他のページのメニューはすべて英語が表記してあったので油断してました。こういうこともあって、それ以降は特に慎重にお店に入る前にかならずTripAdvisorやGoogle Placesでレビューをきちんと確認するようになりました。

泉について

まさしく回復の泉の街のあちこちにある。24時間出続けていて冷たい。タオルを濡らして涼んだりすることもできる。硬水だけど、そのまま飲んだりすることも可能。

参考

旅行の際に参考にしたサイトや書籍など。

「逆引きGolang」で気になったところ

Go

はじめに

こんにちは、タゾチャイティーラテです。最近急に蒸し暑くなったり、寒かったり中途半端な天気が多いですね。逆引きGolang というサイトが公開されてて面白いなあと思って見てたんですが、僕だったらこう書くなというものがいくつかあったので覚書きです。

文字列

部分文字列を置き換える

これは無理に strings 使わないほうが楽なんじゃないかと思いますがどうでしょう。自分で関数定義するのは面倒かもしれませんが。

package main

import "fmt"

func main() {
    s := "Apple Banana Orange"
    r1 := replace(0, 5, []rune(s), []rune("Vine"))
    fmt.Println(string(r1))
    r2 := replace(5, 6, r1, []rune("Lemon"))
    fmt.Println(string(r2))
}

func replace(start, length int, orig, target []rune) []rune {
    ret := make([]rune, len(orig)+len(target)-length)
    copy(ret, orig[0:start])
    copy(ret[start:], target)
    copy(ret[start+len(target):], orig[start+length:])
    return ret
}

16進文字列を整数に変換する

コメントに "0xを含んではいけない" とありますが、含んでも大丈夫です。その場合はbaseを0にします。baseを0にした場合は文字列の見て0が先頭にあれば8進数、0xであれば16進数と判断します。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    s := "0xff"
    sh, _ := strconv.ParseInt(s, 0, 64)
    fmt.Println(sh)
}

漢字コードを変換する

たぶん書きかけなんだろうけど、直接 EUCJP は呼べないので japanese.EUCJP.NewEncoder() としないと動かない。

日付と時刻

これは別に本文と関係ないけど、 time パッケージにはRFCとかで定義されてるフォーマットは定数で事前定義されてるっていうのをFYI。

const (
        ANSIC       = "Mon Jan _2 15:04:05 2006"
        UnixDate    = "Mon Jan _2 15:04:05 MST 2006"
        RubyDate    = "Mon Jan 02 15:04:05 -0700 2006"
        RFC822      = "02 Jan 06 15:04 MST"
        RFC822Z     = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
        RFC850      = "Monday, 02-Jan-06 15:04:05 MST"
        RFC1123     = "Mon, 02 Jan 2006 15:04:05 MST"
        RFC1123Z    = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
        RFC3339     = "2006-01-02T15:04:05Z07:00"
        RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
        Kitchen     = "3:04PM"
        // Handy time stamps.
        Stamp      = "Jan _2 15:04:05"
        StampMilli = "Jan _2 15:04:05.000"
        StampMicro = "Jan _2 15:04:05.000000"
        StampNano  = "Jan _2 15:04:05.000000000"
)

配列

配列に要素を追加する

append 使えばいいんですが、あんまり回数が多いと効率が悪いので、長さがわかってるならばバッファを確保したほうがよいと思う。

一致する要素を全て取り除く

まず全然関係ないけど、全体的にアンダースコア区切りの関数名がよく見られるけど、Goの慣習的には変数名も関数名もキャメルケースです。詳しくは ここ 参照。あと複数パッケージimportするときは括弧で囲ったほうが読みやすいかなあ。

deleteStrings()はまっすぐ書いたほうがスッキリ書けそう。

package main

import "fmt"

func main() {
    a := []string{"apple", "orange", "lemon", "apple", "vine"}

    str, a, err := deleteStrings(a, "apple")
    fmt.Println(str) // => "apple"
    fmt.Println(a)   // => "[orange lemon vine]"
    fmt.Println(err) // => "<nil>"

    str, a, err = deleteStrings(a, "apple")
    fmt.Println(str) // => ""
    fmt.Println(a)   // => "[orange lemon vine]"
    fmt.Println(err) // => "Couldn't find"
}

func deleteStrings(slice []string, s string) (string, []string, error) {
    ret := make([]string, len(slice))
    i := 0
    for _, x := range slice {
        if s != x {
            ret[i] = x
            i++
        }
    }
    if len(ret[:i]) == len(slice) {
        return "", slice, fmt.Errorf("Couldn't find")
    }
    return s, ret[:i], nil
}

おわりに

公式ドキュメントでは文法などはわかりやすく書いてあって、あのサイトだけひと通り読んでれば普通に書けるようになるのですが、やはり逆引き的にスニペットがあると便利ですね。これからも更新頑張ってください。

Ubuntu 15.04のサーバをWake on LANできるようにした

Ubuntu Mac

はじめに

最近、とある用途のために眠ってたマシンを引っ張り出してきた。こいつがまたいい働きをしてるんだけど、いくらファンが静か目とはいえうるさい。ということでWoLの設定をして、いい感じに必要なときだけ起動できる下地を作っておこうと思った。

BIOSの設定

まずBIOSの設定だけど当然使ってるマザーボードによって設定は違う。俺のおんぼろマザボ785GM-P45) の設定だと Power Management Setup → Wake Up Event Setup → Resume By PCI-E Device で Enable の設定をするだけ。

OSの設定

Ubuntu 15.04の方での設定は ethtool で実施。apt-getしようと思ったらすでに入ってた。

% sudo ethtool -s p5p1 wol g
% sudo ethtool p5p1
Settings for p5p1:
    Supported ports: [ TP ]
    Supported link modes:   10baseT/Half 10baseT/Full
                            100baseT/Half 100baseT/Full
                            1000baseT/Full
    Supported pause frame use: No
    Supports auto-negotiation: Yes
    Advertised link modes:  Not reported
    Advertised pause frame use: No
    Advertised auto-negotiation: Yes
    Speed: 1000Mb/s
    Duplex: Full
    Port: Twisted Pair
    PHYAD: 0
    Transceiver: internal
    Auto-negotiation: on
    MDI-X: Unknown
    Supports Wake-on: pg
    Wake-on: g
    Current message level: 0x0000003f (63)
                   drv probe link timer ifdown ifup

Wake-onが g になってるのを確認。このままだと再起動したら設定消えちゃうので、initスクリプトを新規作成。

% sudo vim /etc/init.d/wakeonlanconfig
#!/bin/bash
### BEGIN INIT INFO
# Provides:          wakeonlanconfig
# Required-Start:    $local_fs
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: wakeonlanconfig
### END INIT INFO
ethtool -s p5p1 wol g
exit
% sudo chmod +x /etc/init.d/wakeonlanconfig

これで再起動して起動後にちゃんとWake on LANが有効になってるか確認。

% sudo reboot
% sudo ethtool p5p1
Settings for p5p1:
...
    Wake-on: g
...

テストのために終了する。

% sudo shutdown -h now

MacWake on LANのクライアントの設定

MacPortsを使ってるんで探してみると便利なパッケージがあった。

% port info wol
wol @0.7.1 (net)
Variants:             universal

Description:          wol can send a Wake-On-Lan magic packet to a target ethernet address
Homepage:             http://wake-on-lan.sourceforge.net

Build Dependencies:   autoconf, automake, libtool
Platforms:            darwin, freebsd
License:              GPL-2+
Maintainers:          jeremyhu@macports.org, openmaintainer@macports.org

これをインストールして、試してみる。

% sudo port install wol
% wol <UbuntuマシンのMACアドレス>
Waking up XX:XX:XX:XX:XX:XX....

Ubuntuのマシンが起動した。便利。

Raspberry PiのWake on LANのクライアントの設定

Raspbianを使ってるんでaptで探してみると発見。

$ apt-cache show wakeonlan
Package: wakeonlan
Version: 0.41-11
Installed-Size: 56
Maintainer: Thijs Kinkhorst <thijs@debian.org>
Architecture: all
Depends: perl, perl-modules
Size: 11510
SHA256: d93c21fe7023fd98ec9461047a67f1099addae6a46278e2fb0aea97d55d73f60
SHA1: 988ce3c2f1c6d04f715da153b8a7bfc74dac895a
MD5sum: 6d4c609468083aeedc329a2df9b77079
Description: Sends 'magic packets' to wake-on-LAN enabled ethernet adapters
Homepage: http://gsd.di.uminho.pt/jpo/software/wakeonlan/
Description-md5: 1f4cb6ce85d821307a46719513c54d04
Tag: admin::boot, implemented-in::perl, interface::commandline,
 network::configuration, protocol::ethernet, protocol::udp,
 role::program, scope::utility, use::transmission
Section: net
Priority: optional
Filename: pool/main/w/wakeonlan/wakeonlan_0.41-11_all.deb

これをインストールして試してみる。

% sudo apt-get install wakeonlan
% wakeonlan <UbuntuマシンのMACアドレス>
Sending magic packet to 255.255.255.255:9 with XX:XX:XX:XX:XX:XX

起動した。

結論

便利なのでWoLをもっと気軽に使えるシステムを作りたい。

Goで再帰使うと遅くなりますがそれが何だ

Go

はじめに

こんにちは、Go界のうまい棒です。昼間にTwitter眺めてたら次のような記事を見かけました。

結果はあくまでフィボナッチ数列をナイーブに実装した場合なんで、まあ明らかに遅くなるよなあと予想通りの実行結果でした。

件のプログラム

ナイーブにフィボナッチ数列を実装してますね。

package main

import "fmt"

func fib(n int) int {
    if n < 2 {
        return n
    }
    return fib(n-2) + fib(n-1)
}

func main() {
    fmt.Println(fib(42))
}

これを実際にビルドして実行するとどれくらいかかるかというと、だいたい手元で2.5秒以上かかってますね。

% time go run fib1.go
267914296
go run fib1.go  2.55s user 0.06s system 94% cpu 2.763 total

なんで遅いのか

先のコードは最後が末尾再帰でない再帰呼び出しなので、コールスタックがめっちゃ積まれそうです。Goが再帰呼び出しが得意でないのは、Goランタイムのスタックサイズがデフォルトが小さく、かつスタックサイズの大きさを最小にするような最適化を行わないからです。さらにいうと、Goでは末尾再帰ですら最適化されません。

困ったらgo toolを使ってアセンブリを見てみると良いです。

$ go tool 6g -S fib.go > fib.asm

再帰の場合、途中のいろいろは抜かして関係しそうなところだけ抜粋。

"".fib t=1 size=128 value=0 args=0x10 locals=0x18
        0x0000 00000 (fib1.go:5)        TEXT    "".fib+0(SB),$24-16
        ...
        0x000f 00015 (fib1.go:5)        CALL    ,runtime.morestack_noctxt(SB)
        ...
        0x001f 00031 (fib1.go:6)        CMPQ    AX,$2
        ...
        0x002e 00046 (fib1.go:7)        RET     ,
        ...
        0x003a 00058 (fib1.go:9)        CALL    ,"".fib(SB)
        ...
        0x0055 00085 (fib1.go:9)        CALL    ,"".fib(SB)
        ...
        0x0070 00112 (fib1.go:9)        RET     ,

今回のコードは普通の再帰ですが、見ての通りfibがどんどん呼ばれてコールスタックが深くなっていきます。これは末尾再帰のコード書いても同様のアセンブリになります。階乗の計算をするコードを書いてみます。

package main

import "fmt"

func fact(n, p int) int {
        p = p * n
        if n == 1 {
                return p
        }
        return fact(n-1, p)
}

func main() {
        fmt.Println(fact(10, 1))
}

このアセンブリを見てみます。

"".fact t=1 size=96 value=0 args=0x18 locals=0x18
        0x0000 00000 (tailrec.go:5)     TEXT    "".fact+0(SB),$24-24
        ...
        0x000f 00015 (tailrec.go:5)     CALL    ,runtime.morestack_noctxt(SB)
        ...
        0x0024 00036 (tailrec.go:6)     IMULQ   AX,CX
        0x0028 00040 (tailrec.go:7)     CMPQ    AX,$1
        ...
        0x0037 00055 (tailrec.go:8)     RET     ,
        ...
        0x004c 00076 (tailrec.go:10)    CALL    ,"".fact(SB)
        ... 
        0x005f 00095 (tailrec.go:10)    RET     ,

fibと同様のアセンブリコードになってますね。

Goという言語

@mayahjp さんとも話してましたが、そもそも「Goが速い」というのが間違いで、たとえば「Goはビルドは遅くない」「普通にやってもまあ遅くないしLLよりは速く書けがち」「並行プログラミングが楽にできる」というところがいいのであって、システムプログラミングなどには向いてますが、数値計算などには向いてませんし、そういったものをするために開発された言語ではありません。(ただ先のエントリのベンチマークを見ても最適化を掛けないCよりは実行速度速くなってますよ。)

今回のフィボナッチ数列でのベンチマークはやってる処理自体はごくごく小さな演算で、パフォーマンスに寄与するのは

  1. 関数呼び出し自体のパフォーマンス
  2. コールスタックの最適化

です。そういった意味でGoは

  1. 関数呼び出し自体はgoroutineの管理などもあり、そもそもがgoroutineを大量に呼べるようにスタックサイズがデフォルトで小さく設定されていて、かつ自動で管理するようにランタイムで調整が入る。
  2. Goではスタックトレースで表示されることが大事なので、敢えて最適化していない*1 (2015.02.23 訂正。鵜飼さんご指摘ありがとうございます。)

という状況なので仕方ないかなと思います。

アルゴリズムでの最適化

もし今回のプログラムをアルゴリズムで最適化するのであればメモ化をするのが手っ取り早いでしょう。O(n)になります。

package main

import "fmt"

var mem = make(map[int]int, 100)

func fib(n int) int {
        if n < 2 {
                return n
        }
        if m, ok := mem[n]; ok {
                return m
        }
        m := fib(n-2) + fib(n-1)
        mem[n] = m
        return m
}

func main() {
        fmt.Println(fib(42))
}

これを実行すると0.12秒になりました。

% time go run fib4.go
267914296
go run fib4.go  0.12s user 0.04s system 89% cpu 0.178 total

ちなみにPythonで適当に書いても速いです。

def fib(n, mem):
    if n < 2:
        return n
    if n in mem:
        return mem[n]
    m = fib(n-2, mem) + fib(n-1, mem)
    mem[n] = m
    return m

if __name__ == "__main__":
    print(fib(42,{}))

実行すると0.01秒ですよ。十分速い。

% time python fib.py
267914296
python fib.py  0.01s user 0.01s system 92% cpu 0.024 total

おわりに

先のエントリの最後にもちょろっと書いてますが、マイクロベンチマークはそのベンチマークに特化した結果しか出ないので、あくまでマイクロベンチマークはマイクロベンチマークです。何が言いたいかというと、Nim使いたくなるようにその言語が得意とする領域のもっと良いサンプルで比較してほしいな、ということでした。おわり。

参考

YAMAGUCHI::weblogの2014年を振り返る

misc

はじめに

こんにちは、Go界のアラン・アーキンです。今日、また1歳年齢を重ねてしまいました。例のやつ貼っときます。

関連エントリ

1年の振り返りも8年目になりました。

ブログに関して

とにかくエントリの数が減ったなあという印象。書けないことが多いというより、社内でいろんな人と話をしているうちに満足してしまうということが多いのが原因だと思います。

Qiitaなどに書く記事などもあるけれど、もうちょっと自分の整理のために、初心に帰って、アウトプットの量を増やしていこう。

ymotongpooの2014年

昨年立てた目標

まず昨年末に立てた2014年の目標を振り返ります。

  • YouTube(のAPI)の人として認知してもらえるようになる
  • Go言語の更なる普及
  • 翻訳本出すぞ
  • カメラの機能をひと通り使いこなす

YouTube(のAPI)の人として認知してもらえるようになる

昨年10月にDeveloper Relationsチームに異動して、YouTube APIのDeveloper Advocateになりましたが、その後今年3月に組織再編があり全サービス・製品の担当となりました。 そのため、YouTube APIのみに割く時間というのはだいぶ減りましたが、それでもずっと継続してYouTube APIのサポートなどは続けているため、社内外からの問い合わせなどもずいぶんと多くいただいた一年でした。

特に今年一番大きかったのはYouTube APIWii U SDKへのインテグレーションです。任天堂社のご協力により、Wii Uでのゲームプレイ動画をパソコンを介することなく、直接YouTubeへとアップロードできるようになりました。

YouTube APIでは動画のアップロードの際、手元に動画ファイルが用意されていることが前提となります。ここで動画アップロード機能をゲーム本体あるいはゲーム用SDKに組み込むとなると、ゲームプレイ動画を「作成」する必要があります。 したがってYouTube APIWii U SDKに組み込むには次のような課題がありました。

  1. 通常は画面にレンダリングされるだけのゲームプレイ映像をキャプチャし、動画ファイルの形にエンコードする
  2. エンコード時間を短くしつつ、アップロードを行う
  3. ネットワークがトラブルにより切断された場合レジュームアップロードを行う

1と2に関してはYouTube APIおよびそのクライアントライブラリで提供しているものではなく、独自実装を行っていただく必要がありました。 しかしそこは任天堂社。白川さんを始めとする社の技術者の方々の技術力により見事に実現され、YouTube APIを用いたゲームプレイ動画アップロード機構のすばらしい参照実装となりました。

3に関してはブログエントリにあるとおり、YouTube APIで提供しているレジュームアップロード機能を利用しています。 Wii Uですので、携帯と違い、安定した帯域を持つ有線ネットワーク環境からアップロードされることを想定していますが、スムーズなレジュームアップロード機能により、よりユーザビリティが向上したと思います。

YouTube APIにはアップロード以外の機能がたくさんあり、Wii U SDKではそれらも多くの場所で利用されています。

また、カヤック社のLobi REC SDKでもYouTube連携の機能が加わり、モバイルゲームのゲームプレイ動画を簡単にYouTubeへとアップロードができるようになっています。これまで国外でもちらほらと聞いていた事例も日本国内で見られるようになったことは自分としても嬉しいものです。

今年はそういった意味ではYouTube APIは少なからずの広がりを見せていると思いますし、来年はゲームプレイ動画を活かした収益的な成功事例を少しでもお手伝いできればなと思っています。

Go言語のさらなる普及

上のトレンドは2013年1月からの"golang"というキーワードの検索ボリュームですが、順調に右肩上がりにボリュームが増えていることが見て取れます。

今年も昨年と同様に2回のGo Conferenceの運営に関わりました。 またカンファレンスだけでなく、その運営者周辺でカート大会をするという、ファンイベントにも参加して、非常に充実した1年でした。

とくに先月末に開催されたGo Conference 2014 autumnはこの会のターニングポイントになったと感じています。まずGoの生みの親であるRob Pikeがキーノートをしてくれたこと、そして僕が運営の表に立たなくなったことです。

前者に関しては、(Goに限らない)レジェンドが自らの言葉で、その設計思想を語ったことに大きな意味があると思っていて、キーノートや口頭でのQ&Aではフォーラムやメーリングリストで文字で読むよりも説得力がありました。 また後者に関しては、Go Conferenceがこれからも継続可能な形として存続できるように僕は今回を機に支援役に回ることにしました。結果@tenntennさんや@Jxck_さん、会場を提供してくれた@deeeetさん、Tシャツを用意してくださった@nuki_ponさん、そして当日運営を快く引き受けてくださった運営の方々みなさんのおかげで過去最大規模のイベントとなりました。

またGoConにかぎらず多くのGo関連イベントも開催されました。Go関連の日本語情報はGoogle+のコミュニティで数多く共有されているので、ぜひ参加&書き込んでください!

翻訳本出すぞ

出版することが出来ました。

すごいErlangゆかいに学ぼう!

すごいErlangゆかいに学ぼう!

英文翻訳をするという行為は自分の英語力と翻訳対象に対する理解を求められる、高度な技能だと思います。 この翻訳を通じて、自分の技術力を思い知らされると同時に、多くの方々のレビューを通じて非常に勉強させていただきました。

出版に至るまでの苦労などは、上にリンクされているエントリに任せるとして、今後も淡々と英語や技術系の勉強を行いつつ、より良い品質の翻訳ができるように努めていきます。

カメラの機能をひと通り使いこなす

昨年末にNikon D610を購入して以来、旅行やイベントのたびに一眼レフカメラを持ち歩いて、カメラの練習を続けています。その中で多くの機能を知り、状況に合わせた利用というものもできるようになってきました。ところが、今度は現像やクロップの技術がまだまだ未熟すぎて、もどかしい思いをすることも増えました。来年は現像も色々と試して、より深みのある写真を撮れるようにしたいなあ。

非常に奥が深い趣味なので、これからもこのカメラを使い続けて、いい写真撮るぞ。

来年に向けて

今年は変化が多い年だったけれど、来年は腰を据えて何かに取り組みたいと思う。

  • Go関連情報の継続的なアウトプット
    • なかなか出てない情報があるなあと思うのでその辺の情報を共有していきたい
  • Android開発の技術力の向上
    • 課長に質問する回数は減らしていきたい
  • 「通知」に関する研究
    • 最近は「通知」に興味があるので、いろいろな方に意見を聞いてまとめたい。
  • 英語力の向上
    • 最近英語記事読んでてわからない単語や表現が増えた気がする。良くない。
  • 仏教について学ぶ
    • 仏教おもしろい
  • 経済について学ぶ
    • 経済おもしろい
  • RAWデータの現像技術の向上