D90とiPhoneで撮った写真を『Flickr』で公開してます↓ ↓ ↓
Beautiful Firenze - Feb 16, 2008 - pictured by takus

Rubyでアルゴリズム 第02回 ~クイックソート編~

2010 年 7 月 27 日 takus コメントはありません



前回の Rubyでアルゴリズム 第01回 ~バブルソート編~ に続いて、今回はクイックソートに取り組んでいく。

クイックソートって?

例のごとくWikipediaを見てみると、

クイックソートは、1960年にアントニー・ホーアが開発したソートのアルゴリズム。分割統治法の一種。

最良計算量および平均計算量はO(n log(n))>である。他のソート法と比べて、一般的に最も高速だといわれているが対象のデータの並びやデータの数によっては必ずしも速いわけではなく、最悪の計算量はO(n^2)である。また数々の変種がある。 安定ソートではない。

wikipedia:クイックソート

どういう風にソートを行うのかはこれだけでは分かりにくいが、安定ソートでないといった特徴を把握した上で活用すれば役立ちそうだと推測できる。



具体的なソートの方法は?

簡単に説明すると、

  1. 要素の中から軸(ピポット)を1つ決める
  2. その軸より小さい値と大きい値のグループに分ける
  3. それぞれのグループで1.2を実行する
  4. それ以上は分割できない状態になればソーティング終了

という方法によりソーティングが可能である。

ちなみに軸の選び方は
 (1)完全にランダムに選ぶ
 (2)適当な3つの値の中央値を選ぶ
といった様々な変形パターンが存在する。



実装

今回の実装は様々な戦略のうち、軸をランダムに選ぶ方法で実装を行った。


class Array
  def sort
    quickSort(self, 0, self.length-1)
  end
 
  def quickSort array, left, right
    if left > right then
      pi = partition(array, left, right)
      quickSort(array, left, pi-1)
      quickSort(array, pi+1, right)
    end
  end
 
  def partition array, left, right
    p = left + rand(right - left)
    self[p], self[right] = self[right], self[p]
    store = left
    (left..right-1).each do |i|
      if array[i] <= array[right] then
        self[i], self[store] = self[store], self[i]
        store += 1
      end
    end
    self[store], self[right] = self[right], self[store]
    return store
  end
end


まとめ

  • 最良時、平均時には O(n log(n)) でソートが可能。
  • 軸を選択するときに常に左端、または右端を選んでしまうと最悪時になり、O(n^2)の計算時間がかかる
  • 軸の選択方法、要素が少なくなると挿入ソートに切り替える等の亜種が存在する

追記 2010/07/28

よく考えるとquicksortとpartitionの引数arrayは必要なさそう...。

そのうちもう一度考える。

カテゴリー: Ruby, アルゴリズム タグ:

Javaでスタックトレースを表示する (メソッドの呼び出し元を特定する)

2010 年 7 月 27 日 takus コメントはありません

デバッグしていて、あるメソッドが複数の場所から呼ばれることがある場合、どこからメソッドが呼ばれているのか特定したいときがある。そんな時にはスタックトレースを表示するのが便利。

Javaでは、以下のように記述すれば、呼び出し元のクラス名、メソッド名を出力できる。

StackTraceElement[] e = new Exception().getStackTrace();
for (StackTraceElement element : e)
System.out.println(element.getClassName() + "," + element.getMethodName());

参考サイト

Java: メソッドの呼び出し元を調べる方法 – sardineの日記

カテゴリー: Java タグ:

Rubyでアルゴリズム 第01回 ~バブルソート編~

2010 年 7 月 26 日 takus コメントはありません

Rubyを学びつつアルゴリズムも復習し直そうということで、1日1記事を目標にやっていけたらと思っている。記念すべき初回である今回はバブルソートを実装。



バブルソートって??

Wikipediaにはこんな風に書いてある。

バブルソート(bubble sort)は、ソートのアルゴリズムの一つ。隣り合う要素の大小を比較しながら整列させること。最悪計算時間がO(n^2)と遅いが、アルゴリズムが単純で実装が容易なため、また並列処理との親和性が高いことから、しばしば用いられる。安定な内部ソート。基本交換法、隣接交換法ともいう。

wikipedia:バブルソート

簡単に言うと、隣り合う要素を順々に比較して要素の順序を入れ替えるという操作を全ての要素に行うことで整列を行うといったとこだろうか。



実装

Arrayクラスのsortメソッドをオーバーライドしてみた。


class Array
    def sort
        unsorted_length = self.length-2
        begin
            unsorted = false
            (0..unsorted_length).each do |i|
                if(self[i] > self[i+1])
                    unsorted = true
                    self[i], self[i+1] = self[i+1], self[i]
                end
            end
            unsorted_length -= 1
        end while (unsorted)
    end
end

素直に実装するとこんな感じになりそう。

今回Rubyを書いていて、


self[i], self[i+1] = self[i+1], self[i]

こういう書き方ができることを初めて知る。

Cだと、一時変数なんかを使って、


tmp = self[i]
self[i] = self[i+1]
self[i+1] = tmp

とか書きそうなとこ。

この辺が、Rubyが直感的に理解しやすいコードが書けると言われている所以なのかと想像。



バブルソートのまとめ

少し脇道に反れたが、最後にまとめ。

  • アルゴリズムが簡単で、実装も楽
  • 最悪時は計算時間がO(n^2)かかってしまう

カテゴリー: Ruby, アルゴリズム タグ:

文字コード変換コマンドnkfの使い方まとめ

2010 年 7 月 26 日 takus コメントはありません

manを引けば分かる話だが、よく使い方を忘れるので一度まとめてみる。

構文


$ nkf オプション ファイル名 [> 出力ファイル名]

オプション一覧

-j          : JISコード(ISO-2022-JP)を出力
-e           : EUCコードを出力
-s           : Shift-JISコードを出力
-w           : UTF-8コードを出力(BOM無し)
-Lu          : unix改行形式(LF)に変換
-Lw          : windows改行形式(CRLF)に変換
-Lm          : macintosh改行形式(CR)に変換
-g(--guess)  : 自動判別の結果を表示
--overwrite  : 引数のファイルに直接上書き
--version    : バージョン情報を表示(インストール済チェック)

使用例

以下は使い方の例。

文字コードチェック

$ nkf -g example.csv
Shift_JIS


文字コード変換(UTF-8)

$ nkf -w--overwrite example.csv


よくやってしまう失敗例


$ nkf -w example.csv > example.csv

上記のコマンドでは、ファイルの中身が空っぽになってしまう。

上書きでいい場合は–overwriteオプションをつける。

そうでない場合はmvなどでファイル名を変更して使う必要がある。

カテゴリー: Linux, まとめ タグ:

Rubyで簡単にベンチマークを行う方法

2010 年 7 月 26 日 takus コメントはありません

何かの処理時間を測定したいときに便利。

Benchmarkモジュールを利用する。


require "benchmark"
puts Benchmark::CAPTION
puts Benchmark.measure{
    process()
}

たとえば、1000個の要素を持つ配列のソート時間を調べる場合は以下のようになる。

require "benchmark"
N = 1000
array = Array.new( N )
(0..N).each do |i|
    array[i] = rand(10000)
end
puts Benchmark::CAPTION
puts Benchmark.measure{
    array.sort
}

結果はこのように出力される。

ちなみに単位は秒。

user     system      total        real
0.000000   0.000000   0.000000 (  0.000158)

参考サイト

benchmark – Rubyリファレンスマニュアル

カテゴリー: Ruby タグ:

夏休みの宿題

2010 年 7 月 25 日 takus コメントはありません

そろそろ夏休みということで、授業もなくなり少し時間ができそう。

ということで、時間があるうちに基礎的なことを勉強し直したいと思い、以下の本を購入。



Operating System Concepts

こちらは、Operating Systemについての標準的な教科書。

Operating System Concept
Operating System Concept



アルゴリズムクイックリファレンス

クイックリファレンスといいながらも、アルゴリズムの定量的な比較までしてあり、よくまとまっているという印象。実用的なコードも数多く書いてあるので、手元に1冊は欲しい本。

アルゴリズムクイックリファレンス
アルゴリズムクイックリファレンス



ちなみに、コンピュータサイエンスについての良著はこのブログによくまとまっている。

Leo’s Chronicle: ぜひ押さえておきたいコンピューターサイエンスの教科書

カテゴリー: 未分類 タグ:

覚えておくと便利なBash Tips

2010 年 7 月 11 日 takus コメントはありません

Bashによる引数の展開

以下のように記述すると、bashによって自然に展開される。


$ cp some/deep/path/{foo,bar}.xml
↓
$ cp some/deep/path/foo.xml some/deep/path/bar.xml


深い階層のファイルをバックアップする場合

普通にコマンドを書くと次のように結構記述が長くなるが、以下のように書くこともできる。


$ cp some/deep/path/hoge.txt some/deep/path/hoge.txt.bak
↓
$ cp some/deep/path/hoge.txt{,.bak}


Bashによる引数の再利用

次のようにファイルをコピーしたうえで、そのファイルをエディタを使って編集などの作業をよく行うことがある。


$ cp some/path/hoge.txt some/path/fuga.txt
$ vi some/path/fuga.txt


このような場合は、特殊変数を使うことで、過去に実施したコマンドの引数を再利用することができる。前述の例では、前述のコピー&編集の流れを次のように記述できる。

$ cp some/path/hoge.txt some/path/fuga.txt
$ vi !:2


基本的に「ビックリマーク+コロン+引数の位置」の組み合わせなので覚えやすい。

カテゴリー: Linux タグ:

卒業

2010 年 3 月 27 日 takus コメントはありません

3月23日。
大学を無事に卒業した。

振り返ってみれば、いろんな場所でいろんな人と出会い、いろんな事を考えることができた4年間だった。
そのどれもが僕にとっては掛け替えのない出来事であったと思う。

そして、なんだかんだ在学中にやろうと思っていた目標はだいたい達成できた気がする。
時にそれは料理であったり、単に昔から行きたかった場所への旅行のようなものから、
時には数十万人規模のユーザに自分が考えたサービスを提供するような大きな目標まで、
手を伸ばせば届きそうなところを一つ一つ目指しながらがんばってきた。

だからといって、大学で4年間色々学んだところで、
未だに英語は満足に喋れないし、専門分野についても知らないことばかり。
それに時間が足りずにできなかったこともまだまだたくさんある。
ひとまず春からは環境も変わるので、心機一転またがんばっていきたいと思う。

blogももっと更新していかないとだな・・・。

カテゴリー: 大学 タグ:

Windows で コマンドプロンプトから Java のプログラム実行時に NoClassDefFoundError が発生する問題

2009 年 10 月 17 日 takus コメントはありません

ちょっとハマッたのでメモ.

JavaでTCPサーバを書いてWindowsのコマンドプロンプトでコンパイルして実行しようとすると,

java TCPServer
Exception in thread "main" java.lang.NoClassDefFoundError: tcp/TCPServer (wrong name: tcp/TCPServer)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(Unknown Source)
        at java.security.SecureClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.defineClass(Unknown Source)
        at java.net.URLClassLoader.access$000(Unknown Source)
        at java.net.URLClassLoader$1.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClass(Unknown Source)
        at java.lang.ClassLoader.loadClassInternal(Unknown Source)
Could not find the main class: tcp.TCPserver.  Program will exit.

という,エラー.
コンパイルは通る,classファイルもある.
どうしたものかと思って原因を調べると,原因が判明.

どうやらJavaのクラスファイルは、packageの階層と同じディレクトリ構造にしないといけないらしく.

この例であれば、tcpserverというディレクトリを作り、
その中にコンパイルしたTCPServer.classを入れ、tcpserverの上位ディレクトリから

java tcpserver.TCPServer
もしくは
java tcpserver/TCPServer

で起動できるらしい.

Java未だによく分かってない.
勉強せねば...

参考リンク
実行時のNoClassDefFoundErrorが解決できません (http://oshiete1.goo.ne.jp/qa3105812.html)

カテゴリー: Java タグ:

日本は変わるのか? – 衆議院選挙2009

2009 年 8 月 31 日 takus コメントはありません

衆議院選挙は民主が圧勝.民主よりなのは分かっていたけど,ここまでの差がつくとは正直驚いた.有権者になって初めての選挙であり,投票を通じて少し政治にも興味を持ったので,テレビやtwitterを眺めながら思ったことを書いてみる.

政権交代の繰り返しで政党がよくなる?

そう思ったキッカケはこのtweetから.

twitter

twitter: zzzmaggy



郵政選挙の時は自民に風が吹き,今回は民主に風が吹いた.どちらが政権を握っても生活が変わらなければ有権者は現政権に不満を覚え,選挙のたびに政権交代が起こるかもしれない.そうなると政党内の膿は溜まりにくくなって,両方の政党が洗練されていくと予想.というか,そうなることを期待している.


日本は変わるのか?

本エントリーのタイトルであるこの疑問については,「すぐには変わらないだろう」というのが僕の考え.政権交代したくらいで生活が劇的に変わるようなら現政権は何をしてたんだという話になる.そうなってくると,「政治で生活が変わるのだろうか?」という疑問が湧いてくる.この疑問についての意見として,少し前のはてブのホットエントリーで見つけたこんなものにも少し納得できる.

おれも昔は選挙とか政治とかにすごく興味があって、毎回いろいろ考えて投票行ってたの。でもやってもやっても何にも起こらなくてね。もうイヤんなってしまった。「おれの1票マジ意味ねえなー!」って思って選挙というものに絶望した。みんなこれ、なんでイヤになんないの? がんばってガマンしてるの?
続・選挙には行かない – TAKUYAONLINE


政治で生活がよくならなければ,僕らはどうすればいいのだろうか?

そんなことを考えていた時に,iPhoneアプリのtoycameraToyCameraなどを作っている方のこんな発言が妙に心に響いた.

twitter: fladict

twitter: fladdict



結局,最低限生活に必要な部分を政治に確保していただいて,それ以外は自分でなんとかするのが一番いいと思う.それくらいマッチョになれば,この国がなくなったって生きていける(たぶん

カテゴリー: エッセイ タグ: