获取一些数字的所有因素(迭代器摊牌:)

时间:2009-07-07 09:55:19

标签: algorithm iterator programming-languages

您将获得一个数字的所有主要因子及其多重性(最高权力) 要求是产生该数字的所有因素。

让我举个例子:

素数因素:

  • 2(电力:3)
  • 3(权力:1)

(意思是数字为2^3 * 3^1 = 24

预期结果是:
1,2,3,4,6,8,12,24

我正在考虑使用一些链式自定义迭代器(在C#中),每个素数因子一个,从0到该素数的幂。

你会如何实现这个?使用您的首选语言。

这与problem #23

中的Project Euler有关

5 个答案:

答案 0 :(得分:6)

Haskell

cartesianWith f xs = concatMap $ \y -> map (`f` y) xs
factorsOfPrimeFactorization =
    foldl (cartesianWith (*)) [1] . map (\(p, e) -> map (p^) [0..e])
> factorsOfPrimeFactorization [(2, 3), (3, 1)]
[1,2,4,8,3,6,12,24]

要对结果进行排序,

import Data.List
cartesianWith f xs = concatMap $ \y -> map (`f` y) xs
factorsOfPrimeFactorization =
    sort . foldl (cartesianWith (*)) [1] . map (\(p, e) -> map (p^) [0..e])

Perl

sub factors {
    my %factorization = @_;
    my @results = (1);
    while (my ($p, $e) = each %factorization) {
        @results = map {my $i = $_; map $i*$_, @results} map $p**$_, 0..$e;
    }
    sort {$a <=> $b} @results;
}

print join($,, factors(2, 3, 3, 1)), $/;  # => 1 2 3 4 6 8 12 24

J

   /:~~.,*/"1/{:@({.^i.@{:@>:)"1 ] 2 3 ,: 3 1
1 2 3 4 6 8 12 24

这些都实现了相同的算法,即生成列表 p 0 p 1 ,分解中的每一对( p e )中的..., p e ,并将笛卡尔积中每一组的乘积放在所有这些列表中。

答案 1 :(得分:3)

考虑所有可能的权力组合。对于每个组合,将素数提升到相应的幂,然后乘以结果。

>>> from functools import reduce
>>> from itertools import product, starmap
>>> from operator import mul 
>>> 
>>> def factors(prime_factors):
...     primes, powers = zip(*prime_factors)
...     power_combos = product(*(range(p + 1) for p in powers))
...     prime_combos = (zip(primes, c) for c in power_combos)
...     return (reduce(mul, starmap(pow, c)) for c in prime_combos)
... 
>>> sorted(factors([(2, 3), (3, 1)]))
[1, 2, 3, 4, 6, 8, 12, 24]

此代码使用Python 3.0。除了调用sorted之外,它只使用迭代器。

侧面评论:太糟糕了这个问题似乎不太受欢迎。我想看看,例如发布一些功能性解决方案。 (我稍后可能会尝试编写Haskell解决方案。)

答案 2 :(得分:3)

如果你不关心单个除数,但关于n的所有除数的总和,你可能想看看Divisor Function

因此

的除数之和

n=p_1^{a_1}\cdot p_2^{a_2}\cdots p_k^{a_k}

\frac{p_1^{a_1+1}-1}{p_1-1}\cdot\cdot\cdot\frac{p_k^{a_k+1}-1}{p_k-1}

答案 3 :(得分:0)

我首先在没有IDE的情况下拍摄,因此可能存在一些错误。

struct PrimePower
{
    public PrimePower(Int32 prime, Int32 power) : this()
    {
        this.Prime = prime;
        this.Power = power;
    }

    public Int32 Prime { get; private set; }
    public Int32 Power { get; private set; }
}

然后就是这个递归函数。

public IEnumerable<Int32> GetFactors(IList<PrimePowers> primePowers, Int32 index)
{
    if (index < primePowers.Length() - 1)
    {
        Int32 factor = 1;
        for (Int32 p = 0; p <= primePowers[index].Power; p++)
        {
            yield return factor * GetFactors(primePowers, index + 1);
            factor *= primePowers[index].Prime;
        }
    }
    else if (index = primePowers.Length() - 1)
    {
        Int32 factor = 1;
        for (Int32 p = 0; p <= primePowers[index].Power; p++)
        {
            yield return factor * GetFactors(primePowers, index + 1);
            factor *= primePowers[index].Prime;
        }
    }
    else
    {
        throw new ArgumentOutOfRangeException("index");
    }
}

它也可能是一种扩展方法,IList<PrimerPower>可能会在IEnumerable<PrimePower>Skip()次调用时被削弱为Take()。我也不喜欢传递索引,但替代方案是复制每次调用的主要功率列表。因此,我认为迭代解决方案更可取 - 如果我再次使用IDE,则添加一个。

答案 4 :(得分:-1)

很容易做到。事实上,我在博客上写了一篇关于这件事的文章。看看这段代码。

#Application lists all factors/divisors for a number.
targetNumber=input('What number do you want the factors for?\n> ')
factors=[]
for i in range(1,targetNumber):
    if targetNumber%i==0:
        factors.append(i)
    elif targetNumber/i==1:
        factors.append(targetNumber)
        break
print factors

Read more