見出し画像

関数型プログラミングの初級問題-19問目- (約5分)

 関数型プログラミングによるリスト操作の練習問題の19問目です。問題は、OCaml公式ページのものを使いました。
 内容は、問題と答案です。答案の作成時間は、約5分でした。

問題19.

 リストを左巡回シフトさせる関数rotateを書け。

※ 例えば、rotate ["1"; "2"; "3"; "4"; "5"] 3は(["4"; "5"; "1"; "2"; "3"])になります。

答案

基本的な考え方

 関数型プログラミングによるリスト操作の基本的な流れは、以下の1から3になります。
  1. 引数のリストをheadとtailに分離する
  2. tailを引数として再帰呼び出すると共に、その返り値とheadを適当に組み合わせる
  3. 以上を引数のリストが停止条件に達するまで繰り返す

本問の解き方

 問題17.の答案の分割関数splitを用います。
 関数spliteは、先頭からn番目でリストを前後に分割してタプルとして返します。
 このタプルの第1要素は、元のリストを左シフトさせたときに消える部分に相当し、第2要素は、左シフトの結果(空き部分を除く)に相当します。
 そこで、第2要素の後段に第1要素を結合することで、左巡回シフトとなります。

コード

let rotate lisuto n =
 let rec split i = function
  | [] -> ([], [])
  | head::tail ->
   if i < 1 then ([], head::tail)
   else let (zenhan, kouhan) = split (i-1) tail in
  (head::zenhan, kouhan) in
 let (zenhan, kouhan) = split n lisuto in kouhan@zenhan


感想

 今回は簡単でした。分割関数splitを使うか、一つずつの左シフトを繰り返すかで迷いましたが、どちらも汚いコードになるのは目に見えているので、楽なほうを選びました。

 ここのところ出題されている数字を指定してのリスト操作は、関数型プログラミングには向いていない気がします。
 これらの操作は、再帰的なものではなく逐次的なものです。
 例えば、今回の問題は、左巡回シフトを繰り返す単純なループ処理のはずです。
 これならば、命令型プログラミングでfor文などを使うほうが、処理の流れが分かり易くすっきりします。

 こんな単純な問題ですら読み難く複雑なコードになるようではOCamlを実用で使用するのは厳しいですね。
 関数splitは、二日前に書いたコードなのに何をしているのか全く理解できませんでした。まあ、実用にないのは私のオツムかもしれませんが…

 次回は、第20問です。どうも仕事明けに記事を書くと陰鬱としていけません。もっとnoteらしくお花畑なホワホワした記事にしないと!

古往今来得ざれば即ち書き得れば即ち飽くは筆の常也。と云うわけで御座います、この浅ましき乞食めに何卒皆々様のご慈悲をお願い致します。