我正在尝试在阵列中获得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 *'b - > 'a *'b在统一''a'和''a *'b - >时,结果类型将是无限的。 'a *'b'
有人知道这段代码有什么问题吗? (或其他解决方案)
答案 0 :(得分:5)
作为使用显式递归的替代方法,您还可以使用现有的F#库函数来解决此问题。这就是大多数F#数据处理的编写方式,但学习如何手动编写递归函数总是很好(因为有时候需要它们)。
所以,为了完整起见,这里有一种方法可以使用现有函数更加声明地解决问题:
let max4 line =
line |> Seq.windowed 4
|> Seq.map (Seq.reduce (*))
|> Seq.max
第一行将列表转换为4元素数组(窗口)的序列。然后将其传递给Seq.map
,将窗口转换为元素的乘积。为此,我使用Seq.reduce
使用指定的函数减少序列(在本例中为窗口),这里是(*)
运算符。最后,要查找产品的最大元素,可以使用Seq.max
函数。
答案 1 :(得分: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
不是一个好的起点。请注意整数溢出可能发生(我仍然没有在我的函数中解决)。答案 2 :(得分: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
会忽略最后的任何部分组(代码也是如此)。