我遇到了以下问题,我坚持使用。
我有一个这样的方格式嵌套列表(这只是一个例子,我事先并不知道输入的维度 - 它可以是4 * 4或9 * 9或27 * 27甚至更多,唯一可靠的信息是列表中有k ^ 4个成员,其中k = 1,2,3 ......):
[[[2],[1,3],[4],[1,3]],
[[1,3],[4],[2,3],[1,3]],
[[3,4],[2,3],[1],[2,3,4]],
[[1,3,4],[1,2,3],[2,3],[2,3,4]]]
我可以生成子列表的笛卡尔积,然后生成列表的笛卡尔积,得到这个:
[[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,1,2,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,1,2,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,1,2,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,1,3,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,1,3,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,1,3,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,2,2,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,2,2,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,2,2,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,2,3,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,2,3,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,2,3,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,3,2,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,3,2,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,3,2,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,3,3,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,3,3,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[1,3,3,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[3,1,2,2]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[3,1,2,3]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[3,1,2,4]],
[[2,1,4,1],[1,4,2,1],[3,2,1,2],[3,1,3|...]],
[[2,1,4,1],[1,4,2,1],[3,2,1|...],[3,1|...]],
[[2,1,4,1],[1,4,2|...],[3,2|...],[3|...]],
[[2,1,4|...],[1,4|...],[3|...],[...]],
[[2,1|...],[1|...],[...]|...],
[[2|...],[...]|...],
[[...]|...],
[...]|...]
所以我可能生成并遍历此矩阵,但由于内存限制,我无法做到这一点。即使在9 * 9矩阵中,问题也有太多组合。
所以我想顺序生成这些组合以进行遍历,而不存储所有组合。 红利问题:生成的子列表不能包含重复值。但即使没有红利问题,如果您提供解决方案我很高兴。
感谢您的帮助。
答案 0 :(得分:0)
答案有点迟,但我遇到了一些麻烦来找到解决方案。
我建议你使用一些代码,我对你可以用中间结果做了什么假设,这个例子对所有最终结果和中间结果进行排序并将它们累积在#{Key = sorted_intermediate_list, Value = occurrence}
形式的地图中,它可以改变通过修改函数accumulate / 3。
-module (combi).
-export ([traverse/1,traverse_with_trace/1,get_all_solutions/1]).
% test exports
-export ([t1/0,t1/3,l/0,l2/0,l_ori/0]).
t1() ->
F = fun(X,Acc,_) ->
io:format("----> ~p~n",[X]),
[X|Acc]
end,
lists:reverse(cross_prod_1(l1(),[],F,[],1)).
t1(L,F,Acc) ->
cross_prod_1(L,[],F,Acc,1).
traverse(L) -> traverse(L,{no,0}).
traverse_with_trace(L) -> traverse(L,{yes,0}).
traverse([H|T],I) ->
print(I,"enter traverse ",[[H|T]]),
F = fun(P1,P2,N) -> accumulate(P1,P2,N) end,
print(I,"leave traverse ",cross_prod_1(H,[],F,{T,[],#{}},next(I))).
cross_prod_1([],L_acc,F,Acc,I) ->
print(I,"enter cross_prod_1 1",[[],L_acc,Acc]),
Res = lists:sort(L_acc),
print(I,"leave cross_prod_1 1",F(Res,Acc,next(I)));
cross_prod_1([[X1]|T],L_acc,F,Acc,I) ->
print(I,"enter cross_prod_1 2",[[[X1]|T],L_acc,Acc]),
print(I,"leave cross_prod_1 2",cross_prod_1(T,[X1|L_acc],F,Acc,next(I)));
cross_prod_1([[X1|T1]|T],L_acc,F,Acc = {E1,E2,_},I) ->
print(I,"enter cross_prod_1 3",[[[X1|T1]|T],L_acc,Acc]),
Res = cross_prod_1(T,[X1|L_acc],F,Acc,next(I)),
print(I,"leave cross_prod_1 3",cross_prod_1([T1|T],L_acc,F,{E1,E2,Res},next(I))).
accumulate(X,{[],SoFar,BigAcc},I) ->
print(I,"enter accumulate 1",[X,{[],SoFar,BigAcc}]),
print(I,"leave accumulate 1",insert(lists:sort([X|SoFar]),BigAcc));
accumulate(X,{[H1|T1],SoFar,BigAcc},I) ->
print(I,"enter accumulate 2",[X,{[H1|T1],SoFar,BigAcc}]),
F = fun(P1,P2,N) -> accumulate(P1,P2,N) end,
print(I,"leave accumulate 2",cross_prod_1(H1,[],F,{T1,[X|SoFar],BigAcc},next(I)));
accumulate(X,Y,N) -> % should not occur, for debug purpose
io:format("### ~p, ~p, ~p ###~n",[X,Y,N]),
Y.
insert(Elem,Map) ->
maps:update_with(Elem,fun (V) -> V+1 end ,1,Map).
next({Print,I}) -> {Print,I+1}.
% debug function, it returns Par and, if needed prints indented messages
print({no,_},_,Par) -> Par;
print({yes,N},From,Par) ->
H = lists:duplicate(2*N,$.),
io:format("~s~s : ~p~n",[H,From,Par]),
Par.
% list generator
l() ->
[[[a1],[a2,a3],[a4],[a5,a6]],
[[b1,b2],[b3],[b4,b5],[b6,b7]],
[[c1,c2],[c3,c4],[c5],[c6,c7,c8]],
[[d1,d2,d3],[d4,d5,d6],[d7,d8],[d9,d10,d11]]].
l1() -> [[a1],[a2,a3],[a4],[a5,a6]].
l2() -> [[[1,2],[3,4]],[[5,6],[7,8]]].
l_ori() ->
[[[2],[1,3],[4],[1,3]],
[[1,3],[4],[2,3],[1,3]],
[[3,4],[2,3],[1],[2,3,4]],
[[1,3,4],[1,2,3],[2,3],[2,3,4]]].
% reference functions
get_all_solutions(PossibleSolution) ->
Solutions = lists:map(fun(Solution) -> crossproduct(Solution) end, PossibleSolution),
crossproduct(Solutions).
crossproduct([H|T]) ->
[[A|B] || A <- H, B <- crossproduct(T)];
crossproduct([]) ->
[[]].
这里有一些结果:
1> c(combi).
{ok,combi}
2> length(combi:get_all_solutions(combi:l_ori())). % length of result using your solution and the list given as example
20736
3> maps:size(combi:traverse(combi:l_ori())). % size of the resulting map with my code and your list
2189
4> maps:fold(fun(_,V,A) -> V+A end,0,combi:traverse(combi:l_ori())). % check I have got all the elements
20736
5> combi:traverse_with_trace([[[1,2],[3]],[[4],[5]]]). % show the program progress with a tiny input list
enter traverse : [[[[1,2],[3]],[[4],[5]]]]
..enter cross_prod_1 3 : [[[1,2],[3]],[],{[[[4],[5]]],[],#{}}]
....enter cross_prod_1 2 : [[[3]],[1],{[[[4],[5]]],[],#{}}]
......enter cross_prod_1 1 : [[],[3,1],{[[[4],[5]]],[],#{}}]
........enter accumulate 2 : [[1,3],{[[[4],[5]]],[],#{}}]
..........enter cross_prod_1 2 : [[[4],[5]],[],{[],[[1,3]],#{}}]
............enter cross_prod_1 2 : [[[5]],[4],{[],[[1,3]],#{}}]
..............enter cross_prod_1 1 : [[],[5,4],{[],[[1,3]],#{}}]
................enter accumulate 1 : [[4,5],{[],[[1,3]],#{}}]
................leave accumulate 1 : #{[[1,3],[4,5]] => 1}
..............leave cross_prod_1 1 : #{[[1,3],[4,5]] => 1}
............leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1}
..........leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1}
........leave accumulate 2 : #{[[1,3],[4,5]] => 1}
......leave cross_prod_1 1 : #{[[1,3],[4,5]] => 1}
....leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1}
....enter cross_prod_1 2 : [[[2],[3]],[],{[[[4],[5]]],[],#{[[1,3],[4,5]] => 1}}]
......enter cross_prod_1 2 : [[[3]],[2],{[[[4],[5]]],[],#{[[1,3],[4,5]] => 1}}]
........enter cross_prod_1 1 : [[],[3,2],{[[[4],[5]]],[],#{[[1,3],[4,5]] => 1}}]
..........enter accumulate 2 : [[2,3],{[[[4],[5]]],[],#{[[1,3],[4,5]] => 1}}]
............enter cross_prod_1 2 : [[[4],[5]],
[],
{[],[[2,3]],#{[[1,3],[4,5]] => 1}}]
..............enter cross_prod_1 2 : [[[5]],
[4],
{[],[[2,3]],#{[[1,3],[4,5]] => 1}}]
................enter cross_prod_1 1 : [[],
[5,4],
{[],[[2,3]],#{[[1,3],[4,5]] => 1}}]
..................enter accumulate 1 : [[4,5],
{[],[[2,3]],#{[[1,3],[4,5]] => 1}}]
..................leave accumulate 1 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
................leave cross_prod_1 1 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
..............leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
............leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
..........leave accumulate 2 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
........leave cross_prod_1 1 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
......leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
....leave cross_prod_1 2 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
..leave cross_prod_1 3 : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
leave traverse : #{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
#{[[1,3],[4,5]] => 1,[[2,3],[4,5]] => 1}
6>