我正在Project Euler做question 266,经过一番搜索后,发现this method很快就找到了一个数字的因子。你所做的是找到一个数字的素因子的所有排列:这些是它的因素。
我已经有一个模块可以找到数字的主要功率因数,例如:
Main> primePowerFactors 196
[(2,2),(7,2)]
这基本上表明:2^2 * 7^2 == 196
。从这里我想找到这些权力的所有排列,从而给出196的因子:
我想出了以下内容:
factors n = [a|a<-map facs (primePowerFactors n), y <- [0..(snd $ last $ primePowerFactors n)]]
where
facs (x,y) = (x,y)
rSq n = toInteger $ round $ sqrt (fromInteger n)
psr n = last $ dropWhile (<= rSq n) $ factors n
p = foldl' (*) 1 $ takeWhile (< 190) primes
answer = (psr p) `mod` (10^16)
但我的问题是factors
无效。我希望它通过每个素数因子的指数的所有可能值进行置换,然后找到产品来给出因子。如何修改它才能返回 n 的因素?
答案 0 :(得分:2)
对于某些代码高尔夫我写了一个很简单的功能集功能。
powerSet [] = []
powerSet (x:xs) = xs : map (x:) (powerSet xs) ++ (powerSet xs)
此算法的一个缺点是它不包含原始集合,但这对您来说是完美的,因为它看起来不像您想要的那样。
将此与将primePowerFactors n
转换为整体列表的方式相结合,比如说
ppfToList = concatMap (\(x,y)->replicate y x)
使用这些助手,使用
生成数字n的因子列表factors n = nub . map product . powerSet . ppfToList . primePowerFactors $ n
-- will be out of order, you can add a call to `sort` to fix that
根据列表理解,这种算法可能有点难以表达。
答案 1 :(得分:1)
首先,facs
是身份功能:
facs (x,y) = (x,y)
y
绑定在左侧的模式匹配中,而您可能希望它是列表推导中的y
。列表推导中绑定的变量名称是该理解的本地名称,不能在where
子句的不同范围内使用。
此外,列表推导中的y
仅根据最后的因子指数计算:
y <- [0..(snd $ last $ primePowerFactors n)]
对于每个因素,应该考虑它自己的指数,而不仅仅是最后一个因子的指数。
更基本的问题是,factors
函数的返回类型似乎与其意图不符:
*Euler> :t factors
factors :: Integer -> [(Integer, Int)]
这将返回素数因子的幂列表,同时它应该生成这些构造的列表,如下所示:
[
[(2,0), (7,0)],
[(2,1), (7,0)],
[(2,2), (7,0)],
[(2,0), (7,1)],
[(2,1), (7,1)],
...
]
需要对所有可能因素进行素数分解,但函数似乎只返回一个素因子分解。