上下文:我正在使用Matlab开发Project Euler Problem 23,以便练习我几乎不存在的编程技巧。
我的问题:
现在我有一个大约有6500个数字(范围从12到28122)的向量作为元素,并且想要计算所有两个元素的总和。那就是我只需要每个和的一个实例,所以计算a1 + a就没有必要计算+ a1。
编辑以澄清:这包括总和a1 + a1,a2 + a2,...,an + an。
问题是这太慢了。
问题特定限制:
这是一个给定的28123或以上的数字不需要计算,因为那些不能用于进一步解决问题。
我的方法:
AbundentNumberSumsRaw=[];
for i=1:3490
AbundentNumberSumsRaw=[AbundentNumberSumRaw AbundentNumbers(i)+AbundentNumbers(i:end);
end
这非常有效:p
我的评论:
我很确定逐渐增加向量AbundentNumbersRaw是错误的编码,因为这意味着内存使用量会不必要地增加。我还没有这样做,因为a)我不知道预先分配的大小向量和b)我无法想出一种方法,以有序的方式将总和注入AbundentNumbersRaw而不使用一些丑陋的嵌套环路。
“for i = 1:3490”低于元素数量只是因为我检查并发现索引高于3490的数字的所有结果总和对我来说太大了无法使用。
我很确定我的主要问题是该程序需要对向量AbundentNumbersRaw进行大量增量增量。
非常感谢任何和所有帮助和建议:)
干杯
拉斯穆斯
答案 0 :(得分:3)
假设
a = 28110*rand(6500,1)+12;
然后
sums = [
a(1) + a(1:end)
a(2) + a(2:end)
...
];
是你想要的计算。
您还声明应丢弃其值超过28123的总和。
这可以概括为:
% Compute all 2-element sums without repetitions
C = arrayfun(@(x) a(x)+a(x:end), 1:numel(a), 'uniformoutput', false);
C = cat(1, C{:});
% discard sums exceeding threshold
C(C>28123) = [];
或使用循环
% Compute all 2-element sums without repetitions
E = cell(numel(a),1);
for ii = 1:numel(a)
E{ii} = a(ii)+a(ii:end); end
E = cat(1, E{:});
% discard sums exceeding threshold
E(E>28123) = [];
简单测试表明arrayfun
比循环快一些,所以我选择arrayfun
选项。
答案 1 :(得分:0)
由于你的主要问题是要找出,给定集合中的哪些整数可以写成不同集合中两个整数的总和,我会选择不同的方法:
AbundantNumbers = 1:6500; % replace with the list you generated somewhere else
maxInteger = 28122;
AbundantNumberSum(1:maxInteger) = true; % logical array
for i = 1:length(AbundantNumbers)
sumIndices = AbundantNumbers(i) + AbundantNumbers;
AbundantNumberSum(sumIndices(sumIndices <= maxInteger)) = false;
end
不幸的是,这不是你的问题的答案,而是你的问题;-)对于MatLab解决你原来问题的方法,请看Rody Oldenhuis的优雅答案。
答案 2 :(得分:0)
我的方法如下:
v = 1:3490; % your vector here
s = length(v);
result = zeros(s); % preallocate memory
for m = 1:s
result(m,m:end) = v(m)+v(m:end);
end
你将获得一个3490 x 3490元素的矩阵,其中一半以上是0。