2015-02-12 2 views
2

Учитывая число 'c' и список номеров чисел ', я пытаюсь сгенерировать все суммы, которые я могу иметь для c и любого подмножества в числах. например. (1, [2,4,8]), я должен генерировать (обратите внимание, что мы всегда должны иметь c в сумме) [1,3,5,9,7,11,13,15]Суммировать все подмножества в matlab

I написал следующий код, но не все суммы появляются. Что не так?

function result = allsums(c, numbers) 
    if isempty(numbers) 
     result = []; 
    else 
     [nr n_numbers] = size(numbers); 
     for i = 1:n_numbers 
      result = cat(2, c+numbers(i), allsums(c, cat(2,numbers(1:i-1),numbers(i+1:end)))); 
     end 
    end 

result = cat(2, result, c+sum(numbers,2)); 
end 

ответ

2

Неправильный в строке:

result = cat(2, sums, c+sum(numbers,2)); 

Поскольку вы напомнил функцию sums без входных аргументов, в то время как вы написали функцию с 2 входными аргументами.

UPDATE:

если length(numbers) менее 15 (http://www.mathworks.com/help/matlab/ref/nchoosek.html), вы можете попробовать nchoosek так:

function result = sums(c, numbers) 
    result = []; 
    if ~isempty(numbers) 
    [nr n_numbers] = size(numbers); 
    result = c; 
    for i = 1:n_numbers 
     combi = nchoosek(numbers, i); 
     for j = 1:size(combi, 1) 
     result(end+1) = c + sum(combi(j,:)); 
     end 
    end 
    end 
    result = unique(result); 
end 

р/с: просто очень быстрый пример, вы можете попытаться оптимизировать код , я не уверен, если с помощью рекурсии, как у вас лучше или с помощью встроенных функций MatLab является лучше ...

+0

нет, сумма - это функция matlab для суммирования элементов матрицы, 2 означает сумму по столбцам. Я отредактирую код ma – giulio

+0

да, но основная ошибка - это первые «суммы» в этой строке, так как вы напомнили свой функция без входных аргументов. – scmg

+0

Ваш код работает благодаря. Тем не менее, я до сих пор не понимаю, что не так с моей рекурсией ... – giulio

3

Это может быть один подход -

%// Input array and scalar 
numbers = [2,4,8] 
c = 1; 

%// Generate all sums for all combinations with nchoosek; then add up with c 
combsums = arrayfun(@(n) sum(nchoosek(numbers,n),2),1:numel(numbers),'Uni',0) 
result = [c ; c+vertcat(combsums{:})] 

код запуска -

result = 
    1 
    3 
    5 
    9 
    7 
    11 
    13 
    15 
+0

upvoted. Я до сих пор не привык к замене for-loop массивом ... довольно большой молот, когда логические шаги слишком ясны ... – scmg

+1

@scmg Ну, с 'arrayfun' это компактный способ делать вещи. Кроме того, при замене циклов, которые делают тяжелые сокращения, например 'sum-reduction' в этом случае с' arrayfun', это может быть действительно интересно с точки зрения производительности, я думаю. – Divakar

2

Как о решении одной строкой?

c = 1; %// number 
S = [2 4 8]; %// set 

result = unique(c+S*(dec2bin(0:2^numel(S)-1).'-'0')); 

Объяснение: Ключевым моментом здесь является dec2bin(0:2^numel(S)-1).'-'0', который производит 0 - образец 1, указывающий, какие элементы множества S добавляются. В примере это

0  0  0  0  1  1  1  1 
0  0  1  1  0  0  1  1 
0  1  0  1  0  1  0  1 

Каждый столбец соответствует другому подмножеству S. Затем умножение матрицы на S дает сумму для каждого подмножества.

+0

Хорошая новинка с комбинацией, использующей 'dec2bin'! – Divakar

Смежные вопросы