夏への扉

読んだ。面白かった。

夏への扉

夏への扉

雑にいうと、ライ麦畑の訳本っぽい文体のバック・トゥ・ザ・フューチャーという印象。いまWikipediaを見て、原作は1956年に発表されたと知ってびっくりした。1970年代くらいの作品だと勝手に思っていた。

主人公の感情のアップダウンが激しい。やはりウェットで卑近な感情が克明に描かれた作品は、小説を読んだという充足感をもたらしてくれる。たとえば、異星人と親しくなる歓びよりも、女に騙された怒りや悲しみの方が、より普遍的な感情なので、読みながら想像しやすいw わかりやすいのはよいことだと思う。

技術屋である主人公の描写に味がある。どんな状況でも、目の前の問題を解決する機械の設計を頭の片隅で考えはじめる主人公に笑ってしまう。いるよねこういう人。

そしてなんといっても、作品に登場するネコと、ネコと主人公の距離感が素晴らしかったです。

Rubyで配列に対するinclude?(x)の論理積をどう書くか

先日のどう書くで次のようなコードを書き、疑問に感じました。ダサすぎる……。

    if wall.include?(e) && wall.include?(w) && wall.include?(n)
        return s, "S"
    elsif wall.include?(n) && wall.include?(e) && wall.include?(s)
        return w, "W"
    elsif wall.include?(e) && wall.include?(s) && wall.include?(w)
        return n, "N"
    [...]
    end

というわけで、教えていただいた書き方を整理します。皆さまありがとうございます。

No. 書き方 教えてくれた人
1 ([e, w, n] - ar).empty? 神速さんゆろよろさん
2 [e,w,n].all?{|x| ar.include? x } まきさん鍋谷さん
3 [e,w,n].all?(&ar.method(:include?)) しえるさん
4 Set[e, w, n].subset? ar.to_set yancyaさん

短くてカッコいいのは1、動作がわかりやすいのは2、意図がわかりやすいのは4だと感じました。

というわけで、書き捨てのコードでは1を、その後も使うコードでは2か4を使おうと思います。

問題は3で、これはマジすごいですね。

methodメソッドが、arからinclude?メソッドを取り出して、Methodオブジェクトを返します。ブロックを引数に取れるall?メソッドには、to_procメソッドを持つオブジェクトを&で修飾して渡せます(Methodオブジェクトはto_procメソッドを持ちます)。実行時にtp_procメソッドが呼び出されます。

……ということだそうです。えーと。今のところ使わないと思いますが、すごいなと思いましたw

巨人たちの星

『星を継ぐもの』の続編『ガニメデの優しい巨人』を読み終わってすぐに、Kindleで買って読んだ。続々編。

巨人たちの星 (創元SF文庫)

巨人たちの星 (創元SF文庫)

宇宙スペクトル活劇でございという感じ。敵役が単調すぎるのが難。まあまあ面白かった。正直1作目が一番面白かったけど、そういうものだと思う。

1作目では登場人物の髪型や服装についての言及がほとんどなかったのに、この作品では描写が増えていて、作者の変化が伺える。物語も、男女の仲の話やら、スパイもののような展開やらと、フレーバーの種類が増えた。

主人公のハント博士は、1作目ではあまりにもスーパーマンぽい閃きの人だったので、いけ好かなかった。3作目ではかなり俗人的になり、これくらいがいいなと思った。

そういえば、この世界のコンピュータはよく喋る。馴れ馴れしかったりギャグを言ったりするのが面白い。無機質なサーバントではない。

まださらに続編があるらしいけど、同僚氏に貸してもらったマンガ版をそろそろ読みたい。

「第28回オフラインリアルタイムどう書く」のへなちょこ解答(Ruby)

土曜日は久しぶりにどう書くに行ってきました。

オフラインリアルタイムどう書くとは
皆で共通のお題を好きなプログラミング言語で解いて、結果を見せ合う会です。

今回の問題はこちら。

鍋谷さんの中二センスに完敗です。z軸の移動がないから螺旋ではないのでは?と思ったけど、本当に螺旋の問題を出されても困るので黙っておこうと思います。

自分の解答

初めてRubyで参戦しました。

時間内にデバッグが終わらず悔しい思いをしましたが、翌日1行足したらテストが通りました。

#!/usr/bin/ruby
# http://nabetani.sakura.ne.jp/hena/ord28spirwa/
 
def parse(input)
    wall, day = input.split(":")
    n, e, s, w = wall.split(",")
    rs = [0,0]
    1.upto(n.to_i) { |y| rs << [0, y] }
    1.upto(e.to_i) { |x| rs << [x, 0] }
    1.upto(s.to_i) { |y| rs << [0, -y] }
    1.upto(w.to_i) { |x| rs << [-x, 0] }
    return rs, day
end
 
def check(wall, n, e, s, w)
    if wall.include?(e) && wall.include?(w) && wall.include?(n)
        return s, "S"
    elsif wall.include?(n) && wall.include?(e) && wall.include?(s)
        return w, "W"
    elsif wall.include?(e) && wall.include?(s) && wall.include?(w)
        return n, "N"
    elsif wall.include?(n) && wall.include?(s) && wall.include?(w)
        return e, "E"
    elsif wall.include?(s) && wall.include?(w)
        return e, "E"
    elsif wall.include?(n) && wall.include?(w)
        return s, "S"
    elsif wall.include?(n) && wall.include?(e)
        return w, "W"
    elsif wall.include?(e) && wall.include?(s)
        return n, "N"
    elsif wall.include?(n)
        return w, "W"
    elsif wall.include?(e)
        return n, "N"
    elsif wall.include?(s)
        return e, "E"
    elsif wall.include?(w)
        return s, "S"
    end
    return nill
end
 
def walk(wall, posi)
    x, y = posi[0], posi[1]
    n, e, s, w = [x, y+1], [x+1, y], [x, y-1], [x-1, y]
    nxt, ch = check(wall, n, e, s, w)
    wall << nxt
    return wall, nxt, ch
end
 
def solve(wall, day)
    posi = [1, 1]
    wall << posi
    ch = ""
    0.upto(day) {|d|
        wall, posi, ch = walk(wall, posi)
    }
    return ch
end
 
DATA.each{|line|
    num, input, expected = line.split( /\s+/ )
    
    wall, day = parse(input)
    actual = solve(wall, day.to_i)
    
    error = (actual == expected) ? "" : " ** expected is : #{expected} **"
    puts "%s -> %s %s" % [input, actual, error]
}
__END__
#0 2,3,5,4:85 S
#1 1,2,3,4:1 E
#2 1,2,3,4:2 S

考え方

まず、入力値をx座標とy座標で表現される壁に変換します。中央が(0, 0)です。

次に、現在地に隣接する東西南北のマス目が「壁かどうか」をチェックします。どの方角が壁であるかによって、進める方向が一意に定まることを利用します。

たとえば、0日目。南と西が壁のときは、東に進みます。

1日目。0日目にいた場所はもう通れないので、以後は壁とみなします。進行方向のルールは0日目と同じ。南と西が壁のときは、東に進みます。

2日目。1日目にいた場所は、以後壁とみなします。西が壁のときは、南に進みます。

3日目。2日目にいた場所は、以後壁とみなします。北と西が壁のときは、南に進みます。

……といったルールを表現したのが、上のひどいif文です。ローテートすれば4分の1で済む気もしますが、全部書いてしまいました。

最後に、上記を旅の日数分だけ繰り返します。

「どこから移動してきたか」という状態を持たず、今いる場所の隣接マスだけを見て判定しているのがポイントです。鍋谷さんから指摘があったとおり、壁の形が凸型だから使える戦略でした。

他の人の解答

他の人の解答では、3方向の移動をまとめて1組と考える戦略や、「どこから移動してきたか」という状態を持つ戦略がありました。

詳しくは、Qiitaのコメント欄からお楽しみください。

第28回オフラインリアルタイムどう書くの問題 - Qiita

どう書くはRubyで解く人が多いので、いざ自分がRubyを書こうとした時に勉強になるのでありがたいですね。今回は、tap breakってなんやねんと思いました。

いつも通り楽しかったです。鍋谷さん、皆さん、ありがとうございました。

2015年1月に会社ブログに書いた記事と、振り返り

今の会社に入社して半年の区切りであるこの週末は、A型インフルエンザにかかって終日寝ていました。インフルエンザなんて、記憶にある限り最後にかかったのは阪神淡路大震災が起きた冬なので、20年ぶりに再会したことなります。そして、高熱さえ下がればもう大丈夫だろうと思っていたら、その後は風邪の症状に移行することを知りました。インフルエンザ恐るべし。

風邪の療養中には視覚情報を遮断すべしといいます。ではなにかを聴くならいいかなと思い、横になったままrebuild.fmを69あたりから順番に、最新に向かって聴きました。とても楽しかったです。日本語でこんなに面白い話が聴けるのは、ありがたいことだなぁと思いました。

1月、会社ブログに書いた記事は3本でした。

3本、というのは入社して以来の少ない本数ですが、正月休みにある程度方針を決めたので、後ろめたい気持ちはありません。

トータルで仕事の生産性を上げるために、今年は就業時間外に会社ブログを書かないことにしました。就業時間中にブログを書けるくらい他の業務を効率化する、とも言えます。(まあ上の3本目のレポートで、その誓いを早くも破ってしまったんですけど)

すくなくともブログを書くためにブログを書くのは思考停止なのでやめたい。たとえば、お客様からのお問い合わせにブログで回答する、という今の会社の素晴らしい伝統芸は、どんどんやっていきたいです。

  • 業務にベストを尽くす
  • 会社ブログは誠実に(なるべく間違いを書かないように)書く
  • この日記には勉強したことや分からないことを(間違いを恐れずに)書く

という方針にしました。

2月も仕事をがんばります。入社して半年たっても、仕事や職場が楽しいと思えるのは、幸せなことです。

疑問メモ: sedのマッチ

社長以下同僚の皆さんが息を吸うようにsedを使っていてカッコいいので自分も覚えようと思って

これを上からやってたんだけど、Using & as the matched stringでさっそく意味がわからない。

なお、リンク先では置き換え文字に「&」を使っているけど、特定の文字にした方が分かりやすそうなので、ここでは「x」に置き換えることにする。

$ echo "123 abc" | sed 's/[0-9]/x/'
x23 abc

わかる。

$ echo "123 abc" | sed 's/[0-9]*/x/'
x abc

わかる。

$ echo "abc 123" | sed 's/[0-9]/x/'
abc x23

うんうん。

echo "abc 123" | sed 's/[0-9]*/x/'
xabc 123

ファッ!?

$ echo "abc 123" | sed 's/[0-9][0-9]*/x/'
abc x

お、おぅ。

$ echo "abc 123" | sed 's/ [0-9]*/ x/'
abc x

これはわかる。「スペース123」とマッチしている。

結局「The first match for '[0-9]*' is the first character on the line, as this matches zero or more numbers. So if the input was "abc 123" the output would be unchanged (well, except for a space before the letters)」がよくわかってないなー。先に進もう。

ガニメデの優しい巨人

『星を継ぐもの』が面白かったので、続編を読んだ。

ガニメデの優しい巨人 (創元SF文庫)

ガニメデの優しい巨人 (創元SF文庫)

イギリスからヒューストン、月、最後には木星へと出かける前作と比べて、木星からはじまり地球へ帰る本作は、躍動感に少し欠ける。こたつでリラックスして長話を聞いていたら、最後にびっくりの結論が待っていたという印象だった。読後感が安楽椅子探偵っぽい。

穏やかで賢いガニメアンたちが好きになった。

しかし、生きた異星人とリアルタイムに邂逅する話は、読んでてちょっとさめちゃうなと思った(個人の現時点での好みです^^; そのうち変わるかも)。異星人の痕跡が見つかるとか未来から異星人がやってくるとかぐらいにとどめた話の方が、現実の延長線上で騙されたい欲求(?)を満たしてくれる気がする。

じつは会社の同僚氏からコミック版の『星を継ぐもの』全4巻を貸してもらって読みはじめたのだけど、どうも原作同タイトルの続編を含む内容らしいので、コミックを1巻まで読んだ段階でこちらを優先することにした。同僚氏にもfinalfusionさんにもお勧めされるだけあって、コミック版もとても面白い。

この後、小説版のさらに続編も読む予定。Kindle Voyageべんりだなぁ。