2009年10月27日火曜日

Haskell その2

今度はリストを逆順にする関数を作る。

module Main where
import Text.Printf

main = do print (reverse([1,2,3,4,5]))
print (reverse1([1,2,3,4,5]))
print (reverse2([1,2,3,4,5]))
print (reverse3([1,2,3,4,5]))
print (reverse4([1,2,3,4,5]))

reverse1 x | length x == 1 =x
| length x > 1 =reverse1(tail x) ++ head x:[]
reverse2 (x:xs) | length xs == 1 =xs++x:[]
| length xs > 1 =reverse2(xs)++x:[]
reverse3 x=foldl (flip (:)) [] x
reverse4 =foldl (flip (:)) []
最初のreverseは最初から定義されている関数で、その名の通りリストを逆順にする。
reverse1 x | length x == 1 =x
| length x > 1 =reverse1(tail x) ++ head x:[]
これは引数xの長さが1ならxをそのまま返し、xが1より大きければxの先頭の要素を除いたリストを逆順にしたリストにxの先頭の要素を連結した結果を返す関数である。
++はリストの連結を行う演算子で:はリストの先頭に要素を追加する演算子である。
[]は空リストである。
reverse2 (x:xs) | length xs == 1 =xs++x:[]
| length xs > 1 =reverse2(xs)++x:[]
この関数は、リストを引数に取り、その先頭をxに、それ以外をxsとする。
xsの長さが1のとき、xsとxを連結したリストを返す。xsの長さが1より大きいとき、xsを逆順にしたリストにxを連結したリストを返す。
xsのsは英語の複数形で、こういう命名規則なのだそうだ(がどこで見たのかは忘れた…)。
別に従わないとコンパイルが通らないというわけではない。
reverse3 x=foldl (flip (:)) [] x
この関数も引数にリストを取り、それをxとする関数である。
これもリストxを反転した結果を返す関数であるが、少しややこしい。
foldlは引数を3つ取り、第3引数のリストの左側の要素から順に処理を行う関数である。
その処理をC言語風に書くと、第1引数を+、第2引数をa、第3引数のi番目の要素をx[i]、処理結果をrとして、
r = a
for(i=0; i<length x; ++i)
r = r + x[i]
return r
のようになる。

flipは2引数関数の引数を入れ替える関数である。f(x,y)ならf(y,x)になる。
:は右側(第2引数)にリスト、左側(第1引数)に追加する要素を書くが、そのままではfoldlが演算子:を呼び出すときに左右が逆になってしまう。そこで、flipを使って逆向きにする。

以上より、引数で与えられたリストの先頭の要素から順に新しいリストの左側に追加していくという処理になっており、リストの順序が逆向きになることがわかる。

reverse4 =foldl (flip (:)) []
この関数は、foldlの第3引数が指定されていない関数になっている。つまり、reverse4は引数を1つ取る関数である。
foldlの第1,第2引数が指定されている関数であるともいえる。

ああ、ややこしい。

2009年10月25日日曜日

Haskell その1

erlangはネイティブのバイナリファイルが生成できなかったので、
今度はそれができるHaskellを試してみた。

C++系統の言語とは異なりすぎているので、
なかなか慣れるまでに時間がかかる。
とりあえず、絶対値を求める関数を作った。

module Main where
import Text.Printf

main = do printf "abs -10 is %d\n" (10::Int)
printf "abs -10 is %d\n" ((abst (-10)) ::Int)
printf "abs -20 is %d\n" (absi (-20))

abst x = if x < 0 then -x else x

absi :: Int -> Int
absi x = if x < 0 then -x else x

順に説明する。調べ始めたばかりなので、
間違いが混じっているかもしれない。

 module Main where
はプログラムのエントリポイントを指定している。
C++で言うところのmain関数の名前を指定している。
 import Text.Printf
printfを使うために必要
 main = do
これ以降にメイン関数の定義を書く。
printfは書式付の関数。10::IntはInt型の数字として10を使用することを明示している。明示しないとコンパイルエラーになる。
先に、abstとabsiについて説明する。
abst x = if x < 0 then -x else x
これは、引数xを取る関数abstの定義であって、もしxが0より小さければ-xを、そうでなければxを返すことを表している。
absi :: Int -> Int
これはabsiの関数の宣言でInt型の引数を取り、戻り値の型もIntであることを宣言している。
absi x = if x < 0 then -x else x
はabsiの定義であり、内容はabstと同じ。
printfの説明に戻る。
printf "abs -10 is %d\n" ((abst (-10)) ::Int)
abstに-10を引数として渡して、得られる値を出力するということである。
-10を()で囲っているが、囲まないと-と10が分かれてしまってエラーとなる。
さらに::Intで戻り値の型を指定している。
abstは関数の定義だけを行って、型がどうなっているかの宣言を記載していないので、ここで明示しないと型が曖昧だと言われ、エラーとなる。
printf "abs -20 is %d\n" (absi (-20))
こちらは::Intが不要である。関数の宣言で戻り値がIntであることを明示しているためである。

その他、コードを書くときのルールであるが、インデントによってブロックの範囲が決められる。
タブの使用には注意が必要である。
うっかりスペース4個のタブを使うとコンパイルエラーになる。
スペース8個のタブなら問題ない。

2009年10月18日日曜日

サイレンサー(ただし戦車砲の)

http://gigazine.net/index.php?/news/comments/20091018_tank_silencer/
(笑)
砲身の先にながーいのがくっつくのかと思いきや、
ぶっとい!
こんなの↓

    ■■■
    ■■■
    ■■■
■■■■■■■  □□□
■■■■■■■――□□□
■■■■■■■  □□□
    ■■■
    ■■■
    ■■■
□:戦車本体
―:砲身
■:サイレンサー

実験用らしい。当然だが。

2009年10月10日土曜日

世界の大学ランキング

今年の世界の大学ランキングが出ていた。
http://www.topuniversities.com/university-rankings/world-university-rankings/2009/results

上位の大部分はアングロサクソン系。
日本の大学で100位以内を抜き出すと、
=====
東京大学 22位
京都大学 25位
大阪大学 43位
東京工業大学 55位
名古屋大学 92位
東北大学 97位
=====

時系列で、総合ランキングの順位の変化を見てみた。
下位の大学(といっても、世界で見てだが)が徐々に
順位を上げている。

分野別のデータもあったので、それらもグラフにしてみた。
まずは、自然科学。総合順位とあまり大差ない。


次に工学とITのランキング。工業大学というだけあって、
東京工業大学が順位を伸ばしている。

最後に、ライフサイエンス系。
上位3大学とそれ以外の差が大きい。
なぜだろう。資金力の差なのか!?

2009年9月23日水曜日

温室効果ガス25%削減

日本は温室効果ガスを1990年を基準に25%削減するらしい。
いつも思うのだが、
(1)なぜ1990年を基準とするのか。
(2)25%削減するとどうなるのか。
の2つが報道されない。

(1)は1人あたりの排出量のほうが公平だし、
(2)は達成できても今より温暖化は進む。

もちろん、1人あたりで計算すると先進国が極めて
不利だからだろうし、達成基準なんて「えいやっ」
って決めてるだけだろう。
どうなるかの予測はしてるだろうが。

2009年2月14日土曜日

テトぐるみ

消波ブロック(「テトラポッド」は商標)のぬいぐるみ。
猫の枕にいいらしい。
数十個あれば、部屋の中が海岸っぽくなるかも!?

テトぐるみの写真
http://blog.livedoor.jp/sohsai/archives/51464356.html

ここで買えるらしい。
http://www.syumatutanken.net/200810/cgi-bin/shop/main.cgi?class=all&word=%83e%83g%82%AE%82%E9%82%DD

2009年2月11日水曜日

C++0xの右辺値参照

右辺値参照の詳しい説明がここに。
http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

そしてありがたいことに日本語訳がここに。
http://d.hatena.ne.jp/ntnek/20090210/p1

これでもわからなければ、記事を参照しながら
gccで色々試せばよさそうだ。