5

z はリスト内の場所、y はリスト xs に挿入される番号である insertAt というプログラムを作成したいと考えています。Haskellは初めてで、これが私がこれまでに持っているものです。

insertAt :: Int-> Int-> [Int]-> [Int]
insertAt z y xs
  | z==1 = y:xs

しかし、そこからどこへ行くべきかわかりません。

私は elementAt 関数を持っています。

elementAt v xs
  | v==1 = head xs
  | otherwise = elementAt (v-1) (tail xs)

しかし、どうすれば収まるか、または必要があるかどうかはわかりません。できれば追加は避けたいです。

4

3 に答える 3

7

これが宿題でない場合:let (ys,zs) = splitAt n xs in ys ++ [new_element] ++ zs

この投稿の残りの部分では、この問題を宿題として、またはこの種のことを行う方法を独学していると仮定します。

この種の問題の鍵は、それを自然なケースに分解することです。2 つのデータを処理しています。挿入先のリストと、そのリスト内の位置です。この場合、データの各部分には 2 つの自然なケースがあります。処理しているリストが空であるかそうでないか、および処理している数がゼロであるかそうでないかです。したがって、最初のステップは、4 つのケースすべてを書き出すことです。

insertAt 0 val []     = ...
insertAt 0 val (x:xs) = ...
insertAt n val []     = ...
insertAt n val (x:xs) = ...

ここで、これら 4 つのケースのそれぞれについて、自分がそのケースにいるという答えが与えられるべきかを考える必要があります。

最初の 2 つのケースについては、答えは簡単です。リストの先頭に挿入したい場合は、リストが空かどうかに関係なく、目的の値を最初に貼り付けます。

3 番目のケースは、質問に実際にはあいまいさがあることを示しています。たとえば、空のリストの 3 番目の位置に挿入するように求められたらどうなるでしょうか? 私にはエラーのように聞こえますが、その場合に何をしたいのかを自分で答える必要があります。

4 番目のケースは最も興味深いものです。空でないリストの最初ではない位置に値を挿入したいとします。この場合、再帰を使用して問題の小さなインスタンスを解決できることを覚えておいてください。この場合、たとえば、再帰を使用して解決できます。insertAt (n-1) val xsつまり、入力リストの末尾のn-1th の位置に同じ値を挿入した結果です。たとえば、 list の位置 3 (4 番目の位置) に 5 を挿入しようとしていた場合、[100,200,300]再帰を使用して list の位置 2 (3 番目の位置) に 5 を挿入できます。[200,300]これは、再帰呼び出しによって が生成されることを意味し[200,300,5]ます。

再帰呼び出しが機能すると想定できます。私たちの唯一の仕事は、その小さな問題の答えを、与えられた元の問題の答えに変換することです。この例で求めている答えは[100,200,300,5]( list の位置 4 に 5 を挿入した結果であり、 list[100,200,300][200,300,5]得られます。では、どうすれば目的の結果を得ることができるでしょうか? 最初の要素を元に戻すだけです! (次のように考えてください)なぜこれが真実なのか。)

そのケースが終了したので、リストと位置の組み合わせを更新する可能性のあるすべてのケースをカバーしました。関数はすべての可能性に対して正しく機能し、可能性はすべての可能な入力をカバーするため、関数は常に正しく機能することを意味します。これで完了です。

これらのアイデアを Haskell に変換するのはあなたに任せます。演習の目的はあなたがそれを学ぶことだからですが、うまくいけば問題を解決する方法を知ることができます。

于 2013-10-04T00:14:48.177 に答える