2

阿姆斯特朗数是一个数字,它是它自己的数字的总和,每个数字都提高到数字的数量。

我的代码如下所示,用于查找 7 位阿姆斯壮数,之所以使用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
*)
4

3 回答 3

3

您可以使用shiftdim代替reshape并放入bsxfunfor 循环

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)
于 2013-10-08T15:27:24.533 回答
2

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

  1. 您可以颠倒计算幂和的顺序。这使您可以在最后消除(昂贵的)排列。

  2. 然后,您可以使用第一个中间值一次进行两次求和。

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

  4. 您可以使用内联函数来简化符号。

这导致:

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并且超出了我机器的内存能力。

于 2013-10-08T15:52:15.310 回答
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)
于 2013-10-08T16:08:22.083 回答