haskell:自然数的因数

cit*_*toz 3 haskell

我正在尝试在 Haskell 中编写一个函数来计算给定数字的所有因子,除了它本身。

结果应该是这样的:

factorlist 15 => [1,3,5]
Run Code Online (Sandbox Code Playgroud)

我是 Haskell 和整个递归主题的新手,我很确定我应该在这个例子中应用它,但我不知道在哪里或如何应用。

我的想法是将给定的数字与从 1 到 n div2的列表的第一个元素与mod函数进行比较,但以某种方式递归地进行比较,如果结果是,0则将数字添加到新列表中。(我希望这是有道理的)

我将不胜感激在这件事上的任何帮助

到目前为止,这是我的代码:(它不起作用..但以某种方式说明了我的想法)

 factorList :: Int -> [Int]
 factorList n  |n `mod` head [1..n`div`2] == 0 = x:[]
Run Code Online (Sandbox Code Playgroud)

Zet*_*eta 6

有几种方法可以处理这个问题。但首先,让我们写一个小帮手:

isFactorOf :: Integral a => a -> a -> Bool
isFactorOf x n = n `mod` x == 0
Run Code Online (Sandbox Code Playgroud)

这样我们就可以编写12 `isFactorOf` 24并获得TrueFalse。对于递归部分,假设我们使用一个带有两个参数的函数:一个是我们想要分解的数字,第二个是我们当前正在测试的因子。我们只测试小于或等于 的因子n `div` 2,这导致:

createList n f | f <= n `div` 2 = if f `isFactorOf` n
                                     then f : next
                                     else next
               | otherwise      = []
    where next = createList n (f + 1)
Run Code Online (Sandbox Code Playgroud)

因此,如果第二个参数是 的因子n,我们将其添加到列表中并继续,否则我们就继续。我们只在f <= n `div` 2. 现在为了 create factorList,我们可以简单地使用createList足够的第二个参数:

factorList n = createList n 1
Run Code Online (Sandbox Code Playgroud)

递归隐藏在createList. 因此,createList是一个工人,你可以把它隐藏在where里面factorList

请注意,可以factorList使用过滤器或列表推导式轻松定义:

factorList'  n = filter (`isFactorOf` n) [1 .. n `div` 2]
factorList'' n = [ x | x <- [1 .. n`div` 2], x `isFactorOf` n]
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,您不会自己编写递归。

进一步练习:

  • 尝试自己实现该filter功能。
  • 创建另一个函数,它只返回因数。您可以使用之前的结果并编写一个素数过滤器,或者编写一个直接生成它们的递归函数(后者更快)。