プログラミング in OCaml #8

http://d.hatena.ne.jp/kengpong/20091107/p1

(* 練習問題 5.2 次の関数を定義しなさい *)
(* 1. 正の整数 n から 1 までの整数の降順リストを生成する downto1 *)
let rec downto1 = function
    0 -> []
  | n -> n :: downto1 (n - 1);;

(* 2. 関数 roman *)
let rec roman dict n =
    match dict with
    [] -> ""
  | (n', s) :: rest when n >= n' -> s ^ roman dict (n - n')
  | (n', s) :: rest -> roman rest n;;

(* 3. 与えられたリストのリストに対し、(内側の)要素数を返す nested_length *)
let rec nested_length = function
    [] -> 0
  | x :: rest -> (List.length x) + nested_length rest;;

(* 4. 与えられたリストのリストに対し、内側のリストの要素を並べ変えたリストを返す concat *)
let rec concat l = List.fold_left (@) [] l;;

(* 5. zip *)
let rec zip l1 l2 =
    match (l1, l2) with
    | (x :: xrest, y :: yrest) -> (x, y) :: zip xrest yrest
    | (_, _) -> [];;

(* 6. unzip *)
let rec unzip = function
    [] -> ([], [])
  | (x, y) :: rest -> let (xrest, yares) = unzip rest in (x :: xrest, y :: yrest);;

(* 7. リストとリストの要素上の述語 p を満すすべての要素のリストを返す filter *)
let rec filter f = function
    [] -> []
  | x :: rest when f x -> x :: filter f rest
  | x :: rest -> filter f rest;;

(* 8-1. 先頭から n 番目までの要素からなる部分リストを取りだす take *)
let rec take n = function
    x :: rest when n > 0 x :: take (n - 1) rest
  | _ -> [];;

(* 8-2. 先頭から n 番目までの要素を抜かした部分リストを取りだす drop *)
let rec drop n = function
    x :: rest when n > 0 -> drop (n - 1) rest
  | l -> l;;

(* 9. (空でない) リストのなかから最大値を返す max_list *)
let max_list = function
    x :: [] -> x
  | x :: rest -> let y = max_list rest in if x > y then x else y;;

日が空いた上に、 半分寝てるような状態でやったので、いろいろと駄目っぽいなー。
気がついた点として

  • concat の効率が悪い
  • さらっと List モジュール使ってるけど、いいの?
  • ガードと if 式の使いわけが気分で分けてる感じになっちゃってるけど、どうしよう。

とかがあるかなー。


とりあえずは動けばあんまり気にしない方向で!*1

*1:もちろんツッコミ等は大歓迎です