Matlab 简化查找阿姆斯特朗数的代码

Matlab 简化查找阿姆斯特朗数的代码,matlab,Matlab,A是一个数字,它是它自身数字的总和 每一个都提升到位数的幂次方 我的代码如下所示,用于查找7位Armstrong数字,这是使用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, res

A是一个数字,它是它自身数字的总和 每一个都提升到位数的幂次方

我的代码如下所示,用于查找7位Armstrong数字,这是使用
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
*)

您可以使用
shiftim
而不是
重塑
,并将
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)

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

  • 可以颠倒计算幂和的顺序。这样,您就可以在最后消除(昂贵的)排列

  • 然后可以使用第一个中间值一次进行两次求和

  • 您还可以在每个步骤中展平结果,以避免更高维度的数组。这还可以避免在末端重新塑造形状

  • 您可以使用内联函数简化表示法

  • 这导致:

    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位Anderson数需要
    uint64
    ,超出了我的机器的内存容量。

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

    [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)
    

    为什么
    ^7
    ?是不是应该是
    ^3
    ?@LuisMendo不,幂等于整数长度。你不能用
    m(:)替换所有你
    重塑(m,1,1,[])
    的东西吗
    然后只需调用
    r1'
    r2'
    等?@math然后你应该在开始时为那些考虑它的人更改定义:使用基于
    num2str
    的方法会慢得多。