トップ 最新 追記

Route 477



2010-01-17

[ruby] shinhさんの迷路ゴルフ解読した

ビフォー:

q=gets(p)*1,~/S/
(a,i,*q=q
a[i]<?S&&a[i]=?$
4.times{|x|q+=[a*1,x]if$_[x=-~x%3*-~~/$/-~/$/+-x/2+i]!=$_[x]=?*})while/G/
puts a

アフター:

seen = gets(nil)
queue = [[seen.dup, ~/S/]]
wid = ~/$/

while seen =~ /G/
  maze, here = *queue.shift
  maze[here] = ?$ unless maze[here] == ?S

  4.times{|k|
    d = (k+1) % 3
    n = here + (d-1)*wid  + (d + -k/2)
      #           h                  w
      # k=0  1-1= 0        1+  0  =  1         2
      # k=1  2-1= 1        2+ -1  =  1        3$0
      # k=2  0-1=-1        0+ -1  = -1         1
      # k=3  1-1= 0        1+ -2  = -1
    if seen[n] != ?*
      queue.push([maze.dup, n])
    end
    seen[n] = ?*
  }
end
puts maze

キューを使った幅優先探索(BFS)でした。

  • str*1って意味あるのかと思ったら目的はstr.dupだった
  • +-x/2って-(x/2)でいいんじゃないかと思ったらマイナスのときに駄目だった

[mac] 特定のFlashを含むサイトがフリーズします、助けて

1/17午前は大丈夫だったんですけど、午後から特定のFlashを含むサイトをMacBook(10.5.8)で見るとブラウザごとフリーズするようになった(Safari4, Firefox3, Chrome, Opera9/10で確認)。

Flashをアンインストールすると普通に見れるようになるので犯人なのは間違いないんですが…。

本日のツッコミ(全2件) [ツッコミを入れる]

willnet [僕も同じ症状になったことありますねー いろいろ調べたもののよくわからず、最終的にmacの再インストールをしてしまい..]

yhara [怖いですよねぇ。今回は結局再起動したら直りました。]


2010-01-25 Ruby基礎文法最速マスター

Perl基礎文法最速マスターをだいたいそのまま、Rubyに置き換えてみました。

他の言語をある程度知っている人はこれを読めばRubyの基礎をマスターしてRubyを書くことができるようになる…かも知れません。無保証です。

参考:

1. 基礎

インタラクティブRuby (irb)

irbを使うと、Rubyのプログラムを簡単に練習することができます。

/Users/yhara $ irb
irb(main):001:0> puts "hello"
hello
=> nil
irb(main):002:0> 1 + 1
=> 2

以下の説明は、irbを起動して、自分で試しながら読むと習得が早いと思います。

表示 (print, puts, p)

 print "foo"   #=> 改行なし
 puts "foo"    #=> 改行あり
 p 123         #=> デバッグ用

いわゆる「printfデバッグ」は、Rubyでは「pデバッグ」になります。

変数の宣言

Rubyには変数宣言はありません。また変数の型もないので、一つの変数にいろいろなクラスのオブジェクトを代入することができます。

 a = 123
 a = "abc"   #=> aを上書きする

Rubyでは先頭の一文字によって変数の種類が変わります。

 foo   #=> ローカル変数
 @foo  #=> インスタンス変数(@)
 @@foo #=> クラス変数(@@)
 $foo  #=> グローバル変数($)
 FOO   #=> 定数(大文字から始まる)

コメント

「#」以降はコメントになります。

 # コメント

スクリプトの実行

 $ ruby foo.rb

出力結果をファイルに書き出すにはリダイレクトを使います。

 $ ruby foo.rb > out.txt

2. 数値

整数小数が使えます。

 num = 1
 num = 1.234
 num = 100_000_000

四則演算

 num = 1 + 1
 num = 1 - 1
 num = 1 * 2
 num = 5 / 2    #=> 2 (整数どうしの割り算は整数になる)
 num = 5.0 / 2  #=> 2.5 (どちらかが小数なら結果も小数)
 num = 5 % 2    #=> 1 (余りをとる)

インクリメントとデクリメント

Rubyには++演算子がないので、+=や-=を使います。

 i += 1
 i -= 1

3. 文字列

文字列はシングルクォートかダブルクォートで囲みます。ダブルクォートの中では\t(タブ)や\n(改行)などの特殊文字を利用することができます。またダブルクォートで囲まれた文字列の中では「#{}」を使って任意の式を展開することができます。

 str1 = 'abc'
 str2 = "def"
 str3 = "a\tbc\n"
 str4 = "#{str1} def"  #=> "abc def"

文字列操作

結合

 str1 = "aaa" + "bbb"
 str2 = ["aaa", "bbb", "ccc"].join(",")

分割

 record = "aaa,bbb,ccc".split(/,/)

長さ(文字数)

 length = "abcdef".length
 length = "abcdef".size     # String#sizeとString#lengthは同じ動作。好きな方をどうぞ

切り出し

 substr = "abcd"[0, 2]   #=> "ab" (0番目から2文字)

検索

 idx = "abcd".index(/bc/)  #=> 1

4. 配列

配列は「[]」を使います。

 ary = [100, 200, 300]

要素の参照と代入

 a = ary[0]   #=> 100
 b = ary[1]   #=> 200
 ary[0] = 1
 ary[1] = 2

要素の個数

 n = ary.length
 n = ary.size     # Array#sizeとArray#lengthは同じ動作。好きな方をどうぞ

配列の操作

 ary = [1, 2, 3]
 # 先頭を取り出す
 a = ary.shift   #=> aは1、aryは[2,3]に
 # 先頭に追加
 ary.unshift(5)  #=> aryは[5,2,3]に
 # 末尾を取り出す
 b = ary.pop     #=> bは3、aryは[5,2]に
 # 末尾に追加
 ary.push(9)     #=> aryは[5,2,9]に

5. ハッシュ

ハッシュ(辞書)は「{}」を使います。

 hash = {"a" => 1, "b" => 2}

キーには文字列よりも、シンボル(英語しか使えないが軽い文字列みたいなもの)を使うことが多いですが。

 hash = {:a => 1, :b => 2}

要素の参照と代入

 hash["a"]  #=> 1
 hash["b"]  #=> 2
 hash["c"] = 5
 hash["d"] = 7

ハッシュの操作

キーの取得

 hash.keys   #=> ["a", "b", "c", "d"]  (Ruby 1.8.xでは順不動)

値の取得

 hash.values #=> [1, 2, 5, 7] (同上)

キーの存在確認

 hash.key?("a")  #=> true

ハッシュのペアの削除

 hash.delete("a")

6. 制御文

Rubyでは、条件文で偽と見なされるのはfalseとnilのみで、それ以外のオブジェクトは 全て真と見なされます(0や空文字列も真)。

if文

if a == 1
  ...
elsif b == 2
  ...
else 
  ...
end

while文 (あまり使いませんが)

i = 0
while i < 5
  ...
  i += 1
end

Array#eachとブロックを使った繰り返し

[1, 2, 3].each do |i|    # 「do |..| .. end」のことをブロックと呼びます
  puts i                 # Array#eachは、各要素をブロックに渡して実行してくれます
end                      # 1, 2, 3と順に表示します。

[1, 2, 3].each{|i|       # ブロックには「{|..| .. }」というちょっと短い記法もあります。
  puts i                 # 上の記法とは(結合順位が違うだけで)全く同じ動作になります。
}

Integer#timesとブロックを使った繰り返し

5.times do |i|           # 0, 1, 2, 3, 4と順に表示します
  puts i
end

5.times do               # 値を使わないときは、「|..|」の部分は書かなくて構いません
  puts "hello"
end

Kernel#loopとブロックを使った無限ループ

loop do
  puts "stop me!"        # 無限に表示し続けるので、Ctrl-Cで止めてください。
end

その他の繰り返し

Enumerableモジュールには、繰り返しを行う便利なメソッドがたくさん定義されています。

条件に合うものだけを選ぶ

 [1,2,3,4,5].select{|x| x.even?}  #=> [2,4]

条件に合うものを除く

 [1,2,3,4,5].reject{|x| x.even?}  #=> [1,3,5]

条件に合う最初のものを返す

 [1,2,3,4,5].detect{|x| x.even?}  #=> 2

等しい値があるか調べる

 [1,2,3,4,5].member?(3)           #=> true

条件に合うものがあるか調べる

 [1,2,3,4,5].any?{|x| x.even?}    #=> true

全ての要素が条件に合うかを調べる

 [1,2,3,4,5].all?{|x| x.even?}    #=> false

条件に合うものの個数を数える

 [1,2,3,4,5].count{|x| x.even?}   #=> 2

最大のものを返す

 [1,2,3,4,5].max                  #=> 5

最小のものを返す

 [1,2,3,4,5].min                  #=> 1

加工結果が最大のものを返す

 [1,-2,3,4,-5].max_by{|x| x.abs}  #=> -5

加工結果が最小のものを返す

 [1,-2,3,4,-5].min_by{|x| x.abs}  #=> 1

昇順にソートする

 [1,-2,3,4,-5].sort               #=> [-5, -2, 1, 3, 4]

加工結果で昇順にソートする

 [1,-2,3,4,-5].sort_by{|x| x.abs} #=> [1, -2, 3, 4, -5]

加工結果を配列で返す

 [1,-2,3,4,-5].collect{|x| x.abs} #=> [1, 2, 3, 4, 5]

selectにはfind_all、rejectにはdelete_if、detectにはfind、member?にはinclude?、collectにはmapという別名があります。 *1

*1 Rubyistはcollect派とmap派に二分されますが、筆者はmap派です。理由はタイプ数が少ないからです

7. サブルーチン

Rubyには「サブルーチン」というものはありませんが、 トップレベルでメソッド定義を行うことで、どこからでも呼べるメソッドを定義することができます。 これはサブルーチンのように使うことができます。

def sum(x, y)
  return x + y
end

p sum(1,2)        #=> 3

8. ファイル入出力

読み込み

とりあえずFile.readだけ覚えておけばなんとかなると思います。

str = File.read("foo.txt")  #=> strに、foo.txtの内容を丸ごと含む文字列が代入される

書き込み

File.openで開いて、IO#writeで書き込みます (IO#putsとかもあります)。

File.open("out.txt", "wb") do |f|
  f.write str
end

知っておいた方がよい文法

Rubyの真偽値

前述のように、falseとnilが偽、それ以外の全ての値は真です。

「nil」は値がないことを示す特別な値です。例えば、配列で範囲外の要素を取ろうとするとnilが返ってきます。

 ary = [1,2,3]
 ary[100]           #=> nil

コマンドライン引数

ARGVという組み込み定数に入っています。

 # ruby foo.rb a.txt b.txt としたとき:
 p ARGV     #=> [a.txt, b.txt]

C言語と違って、ARGV[0]にプログラム名が入っていたりはしません。プログラム名は$0という変数から取得できます。

 # ruby foo.rb a.txt b.txt としたとき:
 p $0       #=> foo.rb

unless式

ifの逆です。

 unless a == 1 do
   ...
 end

後置のif (if修飾子)

Rubyではifやunlessを文の後ろに置くことができます。

 puts "ok" if x == 1
 puts "ng" unless x == 1

クラス定義

クラスは「class..end」で定義します。

class Person
  def initialize(name, age)
    @name, @age = name, age
    @address = nil
  end
  attr_reader :name, :age
  attr_accessor :address
end

jhon = Person.new("Jhon", 15)
p jhon.name
jhon.address = "USA, Earth"

その他のよく使うクラス

あとは DirRangeTime くらいですかね。

余談

本体に入らなかった、Rubyの「仕組み」についての話です。

全てがオブジェクト

Rubyでは、全ての値が、いずれかのクラスに属するオブジェクトです。 例えば数値の「1」はFixnumクラス、文字列「"foo"」はStringクラス、 配列「[1,2,3]」はArrayクラスのオブジェクトです。

全てがメソッド

Rubyには「関数」のようなものはなく、printやputsでさえもKernelモジュールに定義されたメソッドです。

 puts "foo"              # これは、
 self.puts "foo"         # これの省略形
 p self                  #=> main (トップレベルのselfは、mainという特別なオブジェクト)
 p self.class            #=> Object (mainは、Objectクラスのインスタンス)
                         #          (Objectクラスは、Kernelモジュールをインクルードしている)
                         #          (なので、トップレベルでputsと書ける)

Kernelモジュールに定義されたメソッドは、プログラムのどこからでも呼び出せます。

Rubyでは演算子もメソッドです。例えば「1 + 2」はInteger#+の呼び出し、 「ary[1]」はArray#[]の呼び出し、「ary[1] = 2」はArray#[]=の呼び出しです。

(おまけ)Ruby書籍紹介

筆者の独断と偏見によるRuby書籍紹介です。

  • 他のプログラミング言語をマスターしていて↓
    • Rubyの特徴を手早く知りたい
      • 4873113679
    • Rubyを網羅的に学びたい
      • 4873113946
    • 認定試験に備えたい
      • 4822234304
    • Java方面から来ました
      • Rubyとの違いを知りたい
        • 4048676210
      • JRubyに興味がある
        • 4881666452
      • 上司を説得したい
        • 4873113202
  • プログラミングとかあんまり慣れてない↓
    • これ一冊でOK、的な本がほしい
      • 4797336617
    • 何かを作りながら学びたい
      • 4777512924 4797352604
  • コンピュータにあまり慣れてない↓
    • 初歩から応用まで一冊で
      • 4798019437
    • 基礎から応用までじっくりと
      • 4798117994 4798118001 479811801X
    • 堅苦しいのはいやなの
      • 4844327704
  • 基礎は分かったんで↓
    • どんなことができるのか知りたい
      • 4863540221 4797340045
    • なんか作ってみたい
      • 4839927847 4839932115 483993178X 4839931496
    • Webアプリがやりたい
      • 4274067858 4873114381
    • 「まつもとゆきひろ」を「ひろゆき」と間違えないようになりたい
      • 4822234312
本日のツッコミ(全5件) [ツッコミを入れる]

Before...

sorah [Enumertableのminの部分がmaxになってるような・・]

こう [ひろゆきワロタ]

雲のパン屋 [classのところで書き忘れ? jhon = Person.new("Jhon", 15) p jhon.name..]


2010-01-27

[ruby] 文法最速(略)について

普段ニッチな記事しか書かないので全体のhotentryに入ることってないんですが、Rubyの話でも間口が広ければちゃんと入るんですね。間違いはこっそり直しています。ご指摘ありがとうございます。

実はtDiaryの1日分がまるごと1エントリになってるんですが、これはブックマークの分散を防ぐためと、ネストが深くなりすぎるのを防ぐためでした。

「基礎としてどのような項目が必要十分か?」を考えるのが一番大変なところであって、 僕はそれに乗っかっただけなので楽させてもらいました。他の人もどんどん 「Common Lisp基礎文法最速マスター」とか「Clojure基礎文法最速マスター」とか「R6RS基礎文法最速マスター」とか書けばいいと思います(Lisp限定か)。


2010-01-29

[ruby] Rackミドルウェアのコンテスト、優勝者が決定

Rackミドルウェアのコンテスト「CodeRack」の結果発表があったようです。

では、上位3位の発表です!

3位:RackProctitle

Rubyプロセスのタイトルに、処理中のURLや処理時間を入れることで、時間がかかっているプロセスをpsで見つけやすくする。

2位:Rack::Superlogger

Rackレベルでログを取る。いろいろなフレームワークを使い分けているときに、全部同じログ形式になるので、解析しやすい。

1位:Rack::GeoIPCountry

アクセス元のIPから国名を推測し、env['X_GEOIP_COUNTRY'] に入れてくれる。

特別賞(?) : RedisRequestLimiter

Redis(KVS)を使って、短時間に大量にアクセスしてくるユーザを弾く。

以下、決勝敗退ミドルウェアです。他にも、99個の全応募作の中に面白いものが眠っているかも…

  • Rack::MemoryBloat (メモリの増大を検出する)
  • Rack::Validate (ページをw3cのhtmlチェッカーにかける)
  • Rack::CacheBuster (「30分後に新バージョンをデプロイするから、クライアントのキャッシュがその時間に切れるように設定して」)
  • Rack::DomainSprinkler (画像などのドメインを、分散用サーバに振り分ける)
  • LiveStats (現在のセッション数を表示する)

[ruby] SinatraベースのIRCクライアント、WebIRC

IRCに繋ぎたいけど、ウィンドウが増えるのが嫌という人向け。

ローカルで動いているからか、軽快に動作するという印象。 複数サーバに接続できるなど、なかなか良くできてます。*1

8e06316d501933ca9a8449c22e5604b8.png

*1 ircnet存続ということで、freenodeと同時接続したいケースはまだまだ多そう