获取列表的gcd

时间:2016-03-30 19:01:17

标签: haskell

我是Haskell的新手,实际上我刚刚开始,我想对我即将提出的问题有一个小小的暗示。

我目前正在尝试获取给定列表的GCD。例如,拥有列表[3,6,9]它将返回3.

目前,我采取了以下方法,我是朝着一个好方向前进的吗?

let getGCD l = map (\x y -> gcd x y) l

4 个答案:

答案 0 :(得分:4)

不完全是,你不想要map而是需要折叠。 map将允许您统一转换列表中的每个元素,因此您可以为其提供局部转换a -> b,并为您提供全局转换([a] -> [b])。这不是你想要的。

作为折叠的快速入门,其中包含了它们的全部内容,它们都让我们通过重复将函数应用于初始值,下一个元素和列表,然后重复使用来表达我们构建的计算。该应用程序的结果作为新的初始值。所以foldl' (+) 0 [1, 2, 3, 4]会像

那样
 foldl' (+) 0 [1, 2, 3, 4] ==>
 foldl' (+) 1 [2, 3, 4] ==>
 foldl' (+) 3 [3, 4] ==>
 foldl' (+) 6 [4] ==>
 foldl' (+) 10 [] ==> -- For empty lists we just return the seed given
 10

您能看到如何将问题插入此框架吗?

更多提示

您想获取一个列表并计算一个取决于列表中每个元素的结果,例如

gcdAll :: [Int] -> Int
gcdAll l = foldl' step initial l

更接近你想要的地方step获取到目前为止已处理的列表的当前gcd以及列表的下一个元素并返回下一个值而initial是要开始的值(如果l为空,则返回什么。由于没有真正理智的价值,我将其拆分为

gcdAll :: [Int] -> Maybe Int
gcdAll [] = Nothing
gcdAll (h : rest) = Just $ foldl' step h rest

这样你就能正确地指出失败的可能性,毕竟,什么是没有什么的gcd?

请注意,foldl'是从Data.List导入的。

答案 1 :(得分:1)

您可以在列表上递归使用gcd(本质上是折叠实现)

gcd' :: (Integral a) => [a] -> a
gcd' [] = 1
gcd' [x] = x
gcd' (x:xs) = gcd x (gcd' xs)

答案 2 :(得分:0)

GCD是一对数字的属性。所以,实际上,您想要查看从列表中提取的数字的。最终,您希望在整个列表中使用单个GCD,但作为第一步,您需要配对。

有一个广为人知的处理连续对的技巧:

f1 list = zipWith f2 list (tail list)

zipWith功能有点像map,但适用于列表的。在这种情况下,原始列表和原始列表的尾部。 (请注意,如果列表为空,则会失败。)如果用f2函数替换gcd,则现在有一个新列表,它是每对连续数字的GCD。这个列表比原始列表短一个元素:

f1 [x, y, z, w] ==> [gcd x y, gcd y z, gcd z w]

因此,每次将f1应用于列表时,都会得到一个新的,更短的GCD列表。应用足够的时间,你应该只有一个元素......

答案 3 :(得分:0)

我刚刚解决了这个问题,这将是最快、最简单的

myGCDMultiple = foldr1 gcd

> myGCDMultiple [3,6,9]
3