Prolog将数字列表分成两个相等的部分

时间:2014-03-20 06:41:21

标签: list prolog sum partition

您好我想编写一个名为perfect_part的函数,它将整数列表作为输入,如果可能,返回两个子列表,其总和恰好是原始列表中所有整数的总值的一半。 例如,

?- perfect_part([6, 3, 2, 1], L, R).
L = [6],
R = [3, 2, 1] ;
false.

?- perfect_part([1, 2, 3, 4, 0], L, R).
L = [1, 4],
R = [2, 3, 0] ;
L = [2, 3],
R = [1, 4, 0] ; 

这是我的尝试:

listsum([], 0).
listsum([H|T], Total):-
    listsum(T, Sum1),
    Total is H + Sum1.

    subset([],L).
    subset([X|T],L):- member(X,L),subset(T,L).

perfect_part([], 0, 0).
perfect_part(Nums, Left, Right):-
    listsum(Nums, S),
    H is S / 2,
    subset(Left, Nums),
    subset(Right, Nums),
    listsum(Left, H),
    listsum(Right, H).

但如果我运行它,我收到错误消息:

错误:是/ 2:参数没有充分实例化

我该如何解决?我是否正确地解决了这个问题?

1 个答案:

答案 0 :(得分:1)

缺少谓词子集/ 2,它是回答问题的重要部分。具体来说,如果子列表是连续的,您可以像

一样轻松解决
perfect_part(X,L,R) :- append(L,R,X), listsum(L,S), listsum(R,S).

然后我会寻找更适合append / 3的替代品,比如

partition([],[],[]).
partition([H|T],[H|L],R) :- partition(T,L,R).
partition([H|T],L,[H|R]) :- partition(T,L,R).

导致

perfect_part(X,L,R) :- partition(X,L,R), listsum(L,S), listsum(R,S).

编辑现在,从子集/ 2中可以看出错误原因:在基本情况下,L是未绑定的。

应为subset([],[]).,但不会终止。我想知道你是怎么得到错误的......

more edit 为避免重复解决方案,我建议用

打破对称性
perfect_part(X,L,R) :- partition(X,L,R), L @=< R, listsum(L,S), listsum(R,S).