简化查找阿姆斯壮号码的代码

时间:2013-10-08 14:44:58

标签: matlab

  

armstrong number是一个数字,它是自己数字的总和   每个都提升到数字位数。

我的代码如下所示,用于查找7位数字Armstrong Number,使用bsxfun的原因因为它非常快,但它只接受三个参数(Mathematica的类似函数Outer可以接受多个参数)。如何让我的代码更紧凑?

tic
m1=(1:9).^7;
m=(0:9).^7;
r1=bsxfun(@plus, m1', m);
r2=bsxfun(@plus, r1, reshape(m,1,1,[]));
r3=bsxfun(@plus, r2, reshape(m,1,1,1,[]));
r4=bsxfun(@plus, r3, reshape(m,1,1,1,1,[]));
r5=bsxfun(@plus, r4, reshape(m,1,1,1,1,1,[]));
r6=bsxfun(@plus, r5, reshape(m,1,1,1,1,1,1,[]));
r7= permute(r6, 7:-1:1);
A=reshape((1e6:1e7-1), size(r7));
A(A==r7)
toc

(*
ans =

     1741725
     4210818
     9800817
     9926315
*)

3 个答案:

答案 0 :(得分:3)

您可以使用shiftdim代替reshape并将bsxfun放入for循环中

m=(0:9).^7.';
r=(1:9).^7.';
for k=1:6,
    m = shiftdim(m,-1);
    r = bsxfun(@plus, r, m);
end
r= permute(r, 7:-1:1);
A=reshape((1e6:1e7-1), size(r7));
A(A==r7)

答案 1 :(得分:2)

您可以通过两种方式简化代码:

  1. 您可以反转计算权力总和的顺序。这可以让你在最后消除(昂贵的)排列。

  2. 然后你可以使用第一个中间值一次做两个总和。

  3. 您还可以在每个步骤中展平结果以避免更高维数组。这也可以让你避免在最后重塑A。

  4. 您可以使用内联函数来简化表示法。

  5. 这导致:

    tic
    m1=(1:9).^7;
    m=(0:9).^7;
    combine = @(x,y) reshape(bsxfun(@plus, x, y'),[],1);
    r2=combine(m, m);
    r4=combine(r2, r2);
    r6=combine(r4, r2);
    r7=combine(r6, m1')';
    r7(r7 == (1e6:1e7-1))'
    toc
    

    你会发现这也快得多。

    通过使用计算整数幂时使用的相同技巧,可以在N上使用此泛型:

    function a = andy(N)
    m1=uint32((1:9).^N);
    m=uint32((0:9)'.^N);
    k = uint32(N) - 1;
    result = uint32(0);
    combine = @(x,y) reshape(bsxfun(@plus, x, y'),[],1);
    while (1),
        if (bitand(k, 1) ~= 0), result = combine(result,m); end
        k = bitshift(k,-1);
        if (k == 0), break, end
        m = combine(m,m);
    end
    result = combine(result,m1')';
    a = result(result == ((10^(N-1)):(10^N-1)))';
    

    我将所有值转换为uint32,这不仅快20%,而且还允许我计算9位数的安德森数字:

    >> tic,andy(9),toc
    
    ans =
    
       146511208
       472335975
       534494836
       912985153
    
    Elapsed time is 40.208217 seconds.
    

    计算10位数的安德森数字需要uint64,超出了我机器的记忆能力。

答案 2 :(得分:0)

这是一种不同的方法,非常紧凑,但仍需要对任意长度进行一些更新。但是,我猜你无论如何都无法计算许多不同长度的数字。

[X1, X2, X3, X4, X5, X6, X7] = ndgrid(0:9);

V = X1.^7+ X2.^7+ X3.^7+ X4.^7+ X5.^7+ X6.^7+ X7.^7;
W = X1*1e6+ X2*1e5+ X3*1e4+ X4*1e3+ X5*1e2+ X6*1e1+ X7;
W(W==V&X1>0)