トップ «前の日記(2007-02-15) 最新 次の日記(2007-02-17)» 編集

じじぃの日記、ツッコミ可

Twitter: @jijixi_org
Xbox Live: jijixi

初心者が書いた OCaml 入門
Spotlight tips サイト内リンク集
1970|01|02|
2003|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|11|
2011|05|
2012|01|

2007-02-16 [長年日記]

% [あなごる][OCaml] 各所で OCaml 用のノウハウが紹介されている模様

m.ukai さんや、shinichiro.h さんのとこ。 すでに気付いていることもあれば、目から鱗なこともあり。 ともあれ、ありがたく参考にさせていただきます。

% [あなごる] sh: ul: not found

キター…と思ったのに残念。 やっぱサーバと同じ環境が無いと、こういう方面はツラいなー。 でも今、手元に Linux 環境無いんだよな。 FreeBSD ならあるけど、Mac OS X と大して変わらんし。

% [OCaml] あなごる特別編、tennis を普通に書くの巻

あなごる、おもしろいんだけど、通常「読みやすく書く」というポリシー (実践できてるか否かは置いといて) のわしとしては、微妙にストレスが溜まるのも確か。 そんなわけで、息抜きのために (何か間違ってる気がするが) 短かくすることを全く考えないで素直にコードを書いてみることにした。 お題は tennis だが、昨日も書いたとおりこの問題は実はテニスじゃないので、テニスになるように改良を加えつつ。

% cat tennis.ml
type status = { games:int; player:string }

let is_tie a b = a.games = b.games

let is_finish a b sd =
   let fc = if sd then 7 else 6 in
   a.games = fc || b.games = fc

let winner a b = (max a b).player

let rec update_status a b =
   let input = read_line () in
   if input = a.player then
      { a with games = a.games + 1 }, b
   else
   if input = b.player then
      a, { b with games = b.games + 1 }
   else begin
      print_endline "bad name!! input again."; 
      update_status a b
   end

let rec play a b sudden_death =
   let x, y = update_status a b in
   let m, n = max x y, min x y in
   if is_finish x y sudden_death then begin
      Printf.printf "Player %s wins the set %d - %d\n"
         (winner x y) m.games n.games;
      exit 0
   end else
   if is_tie x y then
      Printf.printf "Set is tied at %d\n" m.games
   else
      Printf.printf "Player %s leads %d - %d\n"
         (winner x y) m.games n.games
   ;
   match x.games, y.games with
   | 5, 5 -> play x y true
   | _, _ -> play x y sudden_death

let main () =
   let a, b =
      if Array.length Sys.argv >= 3 then
         { games = 0; player = Sys.argv.(1) },
         { games = 0; player = Sys.argv.(2) }
      else
         { games = 0; player = "1" },
         { games = 0; player = "2" }
   in
   play a b false

let () = if not !Sys.interactive then main ()

特段、何か変わったこととかやってるわけじゃないので、まあ解説とかは不要だろう。 強いて言えば、OCaml の比較演算子はコレクション的構造に対しては再帰的に比較していくので、max や min が普通に使えるように、status の要素は games を先にしてるとか、そういう話はある。 比較のプライオリティが高いものほど、先頭側に置くようにするのがポイント。

5-5 になるまでは 6 ゲーム取った時点で終了するとか、起動時に名前を二つコマンドラインに渡しておけば、それを使った表示にしてくれるとか、間違った名前を入力したときは聞き直してくれるとか、そういう細かい機能が追加してある。

ところで、play 関数の最後のところや、main 関数の最初のところみたいなシチュエーションって結構悩むんだけど、こういうのってどうするのが良いのかな。 例えば play 関数の例で行くと、

match x.games, y.games with
| 5, 5 -> play x y true
| _, _ -> play x y sudden_death

というところ。 共通部分まとめ病患者としてみると、ついつい、ここは…

play x y (if x.games = 5 && y.games = 5 then true else sudden_death)

とか、

play x y begin
   match x.games y.games with
   | 5, 5 -> true
   | _, _ -> sudden_death
end

みたいに書きたくなっちゃうんだけど、これってやっぱ読みづらいよね。 そんな風に思って、読みやすいように…というつもりで書いてるんだけど、微妙に趣味と実益の狭間みたいなのを感じちゃうというか……

% [あなごる][Python] even lines

ちょっぴり息抜きで (だから何か違うって) Python に浮気してみた。 なんか OCaml はわし一人だけアプローチが違うみたいだなー。 それでも 1B 差に付けてるってのは、ある意味わしとしては奇跡的だ(苦笑

最初、知らずに input 使ってハマって、sys モジュールに逃げて 51B くらいだったんだけど、リファレンスをよくよく読んだら input は eval(raw_input(prompt)) と同じだって書いてやんの。 eval しちゃダメだよな(笑

ってことで raw_input 使ったらすんなり一位と同じスコアを獲得できた。 なんつーか、あまりよく知らない言語で挑むと、それなりに勉強になったりするね。

% [あなごる] そういや Statistics を公開するのがハヤりっぽいけど…

クッキーが名前しか憶えててくれないので、ついつい公開のチェックを入れ忘れたまま最短コードを通しちゃうと、もう公開できなくなっちゃうのが微妙に不便かも。

お名前:
E-mail:
コメント:

トップ «前の日記(2007-02-15) 最新 次の日記(2007-02-17)» 編集

日記ってのは本来、自分で読み返すためにあるもんだよなあ……
もしくは有名人になったら死後に本になったりとかか?

RSS はこちら

jijixi at azito.com