2016-12-30 5 views
2

私は関数型プログラミングと言語haskellを初めて使いました。私は、述語関数に応じて、リスト内の最も長い連続した一連の要素の長さを決定しようとしています。それは解決策6として私を与える必要がありリスト内のHaskellの最も長い連続した一連の要素

longestSequence (\x -> x >= 10) [1,44,33,22,2,3,55,66,66,77,88,99] 

:私はこのようにそれを呼び出すと

longestSequence :: (a -> Bool) -> [Int] -> Int 

:関数は次のようになりますです。まだまで

私のソリューションです:私はこの問題を解決する方法の

longestSequence :: (a -> Bool) -> [a] -> Int 
longestSequence p [] = 0 
longestSequence p (x:xs) 
    | (p x) = 1 + (longestSequence p xs) 
    | otherwise = longestSequence p xs 

任意のヒントやアイデア?

+1

なぜあなたに6を与えなければならないのでしょうか、代わりにあなたに与えるのは何ですか? –

+1

私は仕様を得ると思います。それは、すべてが述語を満たしている最も長い連続した一連の要素の長さです。 – luqui

+0

私の解決策では、述語が真であれば私はすべての項目を数えているので、9を得る。 – Oni1

答えて

5

小さな問題を除外してください。

  1. 対応するエントリが述語を満たす場合、エントリはTrueある[Bool]リストに指定されたリストを変換する:この例では一般的な戦略は次のようであるかもしれません。それは関数を書くことです(Int -> Bool) -> [Int] -> [Bool]
  2. グループの連続TrueFalseの値です。それは関数[Bool] -> [[Bool]]を書くことです。 Data.List.groupをご覧ください。
  3. [[Bool]] -> [[Bool]]
  4. 各内部リストの長さをカウントします。
  5. [[Bool]] -> [Int]は、それらの長さの最大値を探す:[Int] -> Int

は、次に、あなただけのこれらの機能を構成する必要があり、あなたが行われています。 1.と4.の場合は、関数map :: (a -> b) -> [a] -> [b]を使用します。 mapを既に知っている場合は、それを使用してください。もしあなたがしなければ、自分自身もそれを書くことを提案するでしょう。

私が与えた関数の型シグネチャのいくつかは、あまりにも明確です。可能であれば、少し一般化しようとします。

+1

は、 'False'グループをフィルタリングする必要があります。そのうちの1つがうまくいけば、 – pigworker

+1

これは私の問題を解決するための非常に良い説明でした:)非常に@jpathありがとう! – Oni1

+0

@ Oni1ありがとうございました。 – jpath

3

警備員では、p xotherwiseの両方に問題があります。

(p x) = 1 + (longestSequence p xs)は、xの次の要素がpを予測保持していない場合、現在の最長シーケンスが長く残っ1

を超える場合1

​​は真実ではありません追加することはできません、常に真ではありません

可能な修正は、最大の長さと再帰よりも簡単です

longestSequence :: (a -> Bool) -> [a] -> Int 
longestSequence p x = ls x 0 0 
    where 
    ls [] mx cur = max mx cur 
    ls (x:xs) mx cur 
     | p x = ls xs mx (cur+1) 
     | otherwise = ls xs (max mx cur) 0 
+0

これは動作しません:(。コンパイルが失敗します... – Oni1

+0

@ Oni1本当に申し訳ありませんが、コピー&ペーストのエラー、 – delta

1

あなたはしばしばfoldを使用することができ、現在の長さを維持することであり、このCでase、scanlを使用します。これは、リスト全体を保持する以外は、foldlのようになります。

以下は、述語に一致するすべての項目のカウントをインクリメントするリストを反復します。一致しないものが見つかった場合は、カウントをゼロに戻します。最後に、結果リストの最大値を見つけます。あなたの例の[1,44,33,22,2,3,55,66,66,77,88,99]の入力と(\x -> x >= 10)の述語のために

longestSequence p = maximum . scanl (\count x -> if (p x) then count + 1 else 0) 0 

scanlはの出力を生成します。このリストの最大値をとると、6となり、入力の最後に最大値が現れ、述部が一致しなかったリストの値がゼロであることが分かります。

ちなみに、私はこの問題を小さな部分に分解するjpathに全面的に同意します。私は人々がfoldで同様の問題を解決するのを見てきましたが、\countパラメータの中のmaxの計算をタプルで詰め込むことによって人々は同じ問題を解決しましたが、それは読みにくくなります。これはまた、あなたのような単機能の再帰的なソリューションを、あなたの頭を包み込むのが難しいものにしています。一度に追跡することが多すぎるので、ゼロにリセットする部分にどこにどのようにフィットするのかを確認するのは難しいです。

関連する問題