| Lazy Cjow Rhrr ( @ 2006-05-15 11:40:00 |
| Current mood: | |
| Entry tags: | erlang |
Рекурсивный перебор k-подмножеств
(Уфф, эти срочные проекты вышибли из колеи больше чем на месяц).
Хочу наконец закончить эстетствовать с перебором k-элементных подмножеств. Задачу сформулирую в наиболее общем виде: дан список (чего угодно), сформировать список всех его k-элементных подсписков.
start() ->
comb([], [a,b,c,d,e,f], 3).
% comb([], [a,b,c,d,e,f], 3) ->
% comb([a], [b,c,d,e,f], 2) ++
% comb([b], [c,d,e,f], 2) ++
% comb([c], [d,e,f], 2) ++
% comb([d], [e,f], 2).
comb(B, E, 1) ->
Cons = fun (X) -> B ++ [X] end,
map(Cons, E);
comb(B, E, K) when K == length(E) ->
[B ++ E];
comb(B, E, K) ->
combr(B, E, K-1).
combr(_B, E, K) when K == length(E) ->
[];
combr(B, [EH|ET], K) ->
%io:format("~w; ~w; ~w~n", [B ++ [hd(E)], tl(E), K]),
comb(B ++ [EH], ET, K) ++ combr(B, ET, K).
|
Здесь текущее множество формируется из начала B и некоторого куска длины K из списка-конца E. В граничных условиях (когда нужно перебрать все 1-элементные подмножества, или E-элементные подмножества из E) задача решается непосредственным перебором, а в общем случае - рекурсивно. Красивое, компактное, хоть и не самое эффективное решение.
2> comb:start(). [[a,b,c], [a,b,d], [a,b,e], [a,b,f], [a,c,d], [a,c,e], [a,c,f], [a,d,e], [a,d,f], [a,e,f], [b,c,d], [b,c,e], [b,c,f], [b,d,e], [b,d,f], [b,e,f], [c,d,e], [c,d,f], [c,e,f], [d,e,f]] |
Пока всё на этом.