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
*)
答案 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)
您可以通过两种方式简化代码:
您可以反转计算权力总和的顺序。这可以让你在最后消除(昂贵的)排列。
然后你可以使用第一个中间值一次做两个总和。
您还可以在每个步骤中展平结果以避免更高维数组。这也可以让你避免在最后重塑A。
您可以使用内联函数来简化表示法。
这导致:
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)