Haskell中的素数因式分解,以返回一个元组列表,给出数字和幂

busg9geu  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(154)

我一直试图通过做一些简单的问题来学习 haskell 。
问题所在
目前,我正在尝试实现一个函数primeFactorization :: Integer -> [(Integer, Integer)],以便输出一个元组列表,其中包含素数因子和它在数字中的幂。

示例输出

> primeFactorization 120
[(2,3), (3,1), (5,1)]自120以来= 2^3 * 3^1 * 5^1

我的(部分)解决方案
primeFactorization :: Integer -> [Integer]
primeFactorization n = 
    let
        factors :: Integer -> [Integer]
        factors n = [x | x <- [2..n-1], n `mod` x == 0]

        isPrime :: Integer -> Bool
        isPrime n
            | n `elem` [0, 1] = False
            | n == 2 = True
            | n > 2 = null [ x | x <- [2..(ceiling . sqrt . fromIntegral) n], n `mod` x == 0]
            | otherwise = False
    in
        filter isPrime $ (factors n)

这是一个有效的实现,可以得到一个数的素因子。但是,正如所看到的,它只输出素因子。我不知道如何在haskell中存储次数。而且,考虑到在haskell中迭代是不习惯的,我不知道如何实现这个解决方案。在python中,我会这样做:

def pf(number):
    factors=[]
    d=2
    while(number>1):
        while(number%d==0):
            factors.append(d)
            number=number/d
        d+=1
    return factors

于是,问题来了:如何实现素因子的幂?
注意事项:
1.我已经看到了:Prime factorization of a factorial然而,这并没有回答我的问题。
1.这不是家庭作业问题,我正在独立学习。

mnemlml8

mnemlml81#

你总是可以用递归来替换命令式语言循环(只要它们不干涉任何全局状态)。这可能不是最优雅的方法,但在这种情况下,用递归函数来模仿Python内部循环似乎是非常合适的:

dividerPower :: Integer -> Integer -> Int
dividerPower n d
  | n`rem`d == 0  = 1 + dividerPower (n`quot`d) d
  | otherwise     = 0

(This你也可以用一个helper函数使它成为尾递归的,并在一个累加器变量上向前计数,但这会更尴尬,而且我认为在这种情况下没有内存/性能优势。)
你可以把它和你的Haskell代码一起使用(对于您已经找到的每一个因素,检查它发生的频率),或者扩展它,使整个过程像Python解决方案一样工作(这实际上更有效,因为它避免了对每一个数都检查它是否是素数)。为此,您只需要给予结果中的最终值n。让's使用where块来处理模式匹配,并且还使rem和:

dividePower :: Integer -> Integer -> (Integer, Int)
dividePower n d
  | r == 0     = (nfin, p'+1)
  | otherwise  = (n, 0)
 where (n', r) = n `quotRem` d
       (nfin, p') = dividePower n' d

那么Python代码的等价物是

pf :: Integer -> Integer -> [(Integer, Int)]
pf = go 2
 where go d n
         | n>1        = (d, p) : go (d+1) n'
         | otherwise  = []
        where (n', p) = dividePower n d

这实际上像在Python中一样,给出了一个也包括非分隔符(幂为0)的列表。

| n>1        = (if p>0 then ((d,p):) else id) $ go (d+1) n'

相关问题