Reputation: 71248
I'm trying to get the max product of 4 adjacent numbers in an array this is what I got now:
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
I get a compilation error on the max(,)
saying:
error FS0001: Type mismatch. Expecting a 'a but given a 'a * 'b -> 'a * 'b The resulting type would be infinite when unifying ''a' and ''a * 'b -> 'a * 'b'
Anybody knows what's wrong in this code ? (or another solution)
Upvotes: 0
Views: 292
Reputation: 47914
Both of the other answers sum sliding windows but in your question they're contiguous. If you want the latter you can define such a function:
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
then use code similar to Tomas':
let max4 line =
line |> groupsOf 4
|> Seq.map (Seq.reduce (*))
|> Seq.max
groupsOf
ignores any partial group at the end (as does your code).
Upvotes: 1
Reputation: 243106
As an alternative to using explicit recursion, you could also solve this using existing F# library functions. This is how most F# data processing is written, but it is always good to learn how to write recursive functions by hand (because you sometimes need them).
So, just for completeness, here is a way to solve the probelm more declaratively using existing functions:
let max4 line =
line |> Seq.windowed 4
|> Seq.map (Seq.reduce (*))
|> Seq.max
The first line turns the list into a sequence of 4-element arrays (windows). This is then passed to Seq.map
that turns the window into a product of the elements. To do that, I'm using Seq.reduce
which reduces sequence (window, in this case) using the specified function, here the (*)
operator. Finally, to find the maximal element of the products, you can use Seq.max
function.
Upvotes: 5
Reputation: 41290
Suppose the input is a list of integers:
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
You made some mistakes:
max
function is in the curry form max: 'a -> 'a -> 'a
.b::c::d::tl
, not tl
only.0
is not a good starting point. Beware that integer overflow could happen (which I still haven't addressed in my function).Upvotes: 2