(+)
Mogは、連想的で可換であり、逆であるという事実を利用する答えを出しました。ただし、どの操作でも機能する答えを出すことも建設的だと思います。つまり、合計する実際のリストを作成してから、それらを合計します。したがって、計画は次のようになります。
- 可能な位置ごとにリストを分割する関数を記述します。
- 分割時に要素をドロップすることにより、分割をリストに戻す関数を記述します。
- リストを合計する関数を記述します(すでに
Prelude
:sum
関数を使用して実行されています)。
- それらを組み合わせ、リスト全体の特殊なケースを含む関数を記述します。
パート1を行うにはいくつかの方法があります。最初の選択肢は明示的な再帰です。
splits :: [a] -> [([a], [a])]
splits [] = [([],[])]
splits (x:xs) = ([],x:xs) : map (\(b,e) -> (x:b,e)) (splits xs)
ghciでチェックして、正しく設定されていることを確認できます。
*Main> splits "abcde"
[("","abcde"),("a","bcde"),("ab","cde"),("abc","de"),("abcd","e"),("abcde","")]
ただし、もっと良い方法があります。このData.List
モジュールには、特定の方法でリストを変更するための一連の関数が含まれています。tails
それらの2つはとですinits
:
*Main> tails "abcde"
["abcde","bcde","cde","de","e",""]
*Main> inits "abcde"
["","a","ab","abc","abcd","abcde"]
したがって、この定義は見栄えがはるかに良くなります。
splits xs = zip (inits xs) (tails xs)
ここで、各位置から1つの要素が削除されたリストのリストを生成する関数が必要です。
dropEach xs = [beginning ++ end | (beginning, ignored:end) <- splits xs]
したがって、最後のステップはすべてをまとめることです。
funnySums xs = map sum (xs : dropEach xs)
テストできます:
*Main> funnySums [1, 10, 100, 1000, 10000]
[11111,11110,11101,11011,10111,1111]