2008年03月21日

OCamlのお勉強 その8 〜リストの練習問題〜

プログラミング in OCaml ~関数型プログラミングの基礎からGUI構築まで~」を読んでの勉強記録です。

今回は、本に記載されている練習問題を解いていきます。

練習問題 5.2 次の関数を定義しなさい。

5.5 練習問題,p106-107

以下に与えられた9つの関数を定義していきます。

正の整数nから1までの降順リストを生成する関数downto1

# let downto1 n =
    let rec downto1' i l =
      if i > n then l
      else downto1' (i + 1) (i :: l) in
    downto1' 0 [];;
val downto1 : int -> int list = <fun>
# downto1 5;;
- : int list = [5; 4; 3; 2; 1; 0]

このくらいならすぐに書けました。一応、末尾再帰にしてあります。今後も練習のため末尾再帰可能なものについてはなるべく末尾再帰で書いていきます。

与えられた正の整数のローマ数字表現(文字列)を求める関数roman(I = 1,V = 5,X = 10,L = 50,C = 100,D = 500,M = 1000です)。

# let roman dict n =
    let rec roman' dict n s =
      let rec find f l =
        match l with
        | (a', b) :: rest -> if f a' then (a', b) else find f rest in
      match n with
      | 0 -> s
      | _ -> let (i, r) = find (fun x -> n >= x) dict in roman' dict (n - i) (s ^ r) in
    roman' dict n "";;
(* 警告を省略 *)
val roman : (int * string) list -> int -> string = <fun>

find関数はfが真となる要素をリストlの中から見つける関数ですが、要素が見つからない場合については定義してありません。そのため、find関数のマッチ式が網羅的でないという警告が出ています。今は例外処理のやり方がわからないので無視しておきます。以下は実行結果です。

# let romans = [(1000, "M"); (500, "D"); (100, "C");
                     (50, "L"); (10, "X"); (5, "V"); (1, "I")];;
(* romansの表示を省略 *)
# roman romans 1984;;
- : string = "MDCCCCLXXXIIII"
# let romans = [(1000, "M"); (900, "CM"); (500, "D");
                (400, "CD"); (100, "C"); (90, "XC");
                (50, "L"); (40, "XL"); (10, "X");
                (9, "IX"); (5, "V"); (4, "IV"); (1, "I")];;
(* romansの表示を省略 *)
# roman romans 1984;;
- : string = "MCMLXXXIV"

辞書を入れ替えることでより正確な表記を行います。

与えられたリストのリストに対し、(内側のリストの)要素の総数を返す関数nested_length

予め、与えられたリストの長さを返す関数lengthを定義しておきます。

# let length l =
    let rec length' l n =
      match l with
      | [] -> n
      | _ :: rest -> length' rest (n + 1) in
    length' l 0;;
val length : 'a list -> int = <fun>

続いてnested_lengthを定義します。

# let nested_length ll =
    let rec nested_length' ll n =
      match ll with
      | [] -> n
      | l :: rest -> nested_length' rest (n + length l) in
    nested_length' ll 0;;
val nested_length : 'a list list -> int = <fun>
# nested_length [[1; 2; 3]; [4; 5]; [6]; [7; 8; 9; 10]];;
- : int = 10

確かに計算できています。

今回はここまで。次回もリストの練習問題をいくつか解いていきます。

posted by bakemoji at 01:20| Comment(0) | TrackBack(0) | OCaml | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。

この記事へのトラックバック

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。


×

この広告は90日以上新しい記事の投稿がないブログに表示されております。