0

配列内の4つの隣接する数値の最大積を取得しようとしていますが、これは私が今得たものです:

let max4 line =
    let rec loop acc = function
        |a :: b :: c :: [] -> acc
        |a :: b :: c :: d :: tl -> loop (max(acc, a*b*c*d)) tl
        |_ -> 0
    loop 0 line

max(,)次のことわざでコンパイルエラーが発生します。

エラー FS0001: タイプが一致しません。'a が期待されているが、'a * 'b -> 'a * 'b が指定されている''a' と ''a * 'b -> 'a * 'b' を統合すると、結果の型は無限になります。


このコードのどこが間違っているか知っている人はいますか? (または別の解決策)

4

3 に答える 3

5

明示的な再帰を使用する代わりに、既存の F# ライブラリ関数を使用してこれを解決することもできます。ほとんどの F# データ処理はこのように記述されますが、再帰関数を手動で記述する方法を学ぶことは常に良いことです (必要になる場合があるため)。

したがって、完全を期すために、既存の関数を使用してより宣言的に問題を解決する方法を次に示します。

let max4 line = 
  line |> Seq.windowed 4 
       |> Seq.map (Seq.reduce (*))
       |> Seq.max

最初の行は、リストを一連の 4 要素配列 (ウィンドウ) に変換します。これは に渡されSeq.map、ウィンドウが要素の積に変わります。そのためにSeq.reduce、指定された関数、ここでは(*)演算子を使用して、シーケンス (この場合はウィンドウ) を削減する which を使用しています。最後に、製品の最大要素を見つけるために、Seq.max関数を使用できます。

于 2012-05-31T17:04:49.423 に答える
2

入力が整数のリストであるとします。

let max4 line =
    let rec loop acc = function
        | x1::(x2::x3::x4::_ as xs) -> loop (max acc (x1*x2*x3*x4)) xs
        |_ -> acc
    loop System.Int32.MinValue line

あなたはいくつかの間違いを犯しました:

  • 組み込みmax関数はカレー形式max: 'a -> 'a -> 'aです。
  • 関数で対処する次のケースはb::c::d::tl、だけではありませtlん。
  • この積はマイナスになる可能性があるため0、出発点としては適切ではありません。整数オーバーフローが発生する可能性があることに注意してください (関数ではまだ対処していません)。
于 2012-05-31T16:43:16.780 に答える
1

他の回答はどちらもスライディングウィンドウを合計していますが、あなたの質問ではそれらは連続しています。後者が必要な場合は、そのような関数を定義できます。

let groupsOf n items =
  if n <= 0 then invalidArg "n" "must be greater than zero"
  if List.isEmpty items then invalidArg "items" "empty list"
  let rec loop i acc items =
    seq {
      match i, items with
      | 0, [] -> yield List.rev acc
      | _, [] -> ()
      | 0, _ ->
        yield List.rev acc
        yield! loop n [] items
      | _, x::xs -> yield! loop (i - 1) (x::acc) xs
    }
  loop n [] items

次に、Tomas のようなコードを使用します。

let max4 line = 
  line |> groupsOf 4 
       |> Seq.map (Seq.reduce (*))
       |> Seq.max

groupsOf最後の部分グループを無視します(コードと同様)。

于 2012-05-31T18:36:10.043 に答える