在列表列表中提供每个不同数字的解决方案

时间:2018-05-24 19:57:04

标签: list prolog

我需要做一个谓词,select(ListOfLists, X)作为解决方案返回列表列表中每个不同数字的解决方案,从列表中单独的数字开始,例如:

select([[1,2,3],[1,2],[4],[3]],X).

会回来:

X = 4 ; 
X = 3 ;
X = 2 ;
X = 1

只要首先显示列表中单独的数字,订单就无关紧要。

为此,首先我编写了2个其他谓词,即:

%OrderedList is Lists ordered by size.  
orderListsBySize(Lists, OrderedLists).

示例:orderListsBySize([[1,2],[6],[3,4,5]], L). - > L = [[6], [1,2], [3,4,5]]

%ListsWithoutX is Lists without the X elements  
removeFromLists(X, Lists, ListsWithoutX).

示例:removeFromLists(1,[[1,2],[3],[4,1,5]],L). - > L = [[2],[3],[4,5]]

这两个谓词都有效。

然后,为了执行select(ListOfLists, X)谓词,我尝试了以下内容:

select([[X|[]]|_], X). select(L1,S) :-
    orderListsBySize(L1, [[X|XS]|LS]),
    length(XS, A),
    A == 0,
    select([[X|[]]|M], S),
    removeFromLists(X, [XS|LS], M).  
select([[X|_]|_], X).

但它不起作用。
用其他语言做这不是一项艰苦的练习,问题是我仍然很难理解prolog是如何工作的。我得到了任何帮助,谢谢!

1 个答案:

答案 0 :(得分:1)

你可以从:

开始
select2(ListOfLists,Element):-
    length(List,_Len),
    member(List,ListOfLists),
    member(Element,List). 

这将返回所有答案,但随后陷入寻找更大列表的循环中。 这可以使用:-use_module(library(clpfd)).来避免,并且定义fd_length/2不会继续寻找更大的列表然后存在于列表列表中。

fd_length(L, N) :-
   N #>= 0,
   fd_length(L, N, 0).

fd_length([], N, N0) :-
   N #= N0.
fd_length([_|L], N, N0) :-
   N1 is N0+1,
   N #>= N1,
   fd_length(L, N, N1).

select(ListOfLists,Element):-
    maplist(length,ListOfLists,Lengths),
    sort(Lengths,SortedLength),
    last(SortedLength,Biggest),
    Biggest #>= Len,
    fd_length(List,Len),
    member(List,ListOfLists),
    member(Element,List).

示例查询:

?-select([[1,2,3],[1,2],[4],[3]],X).
X = 4
X = 3
X = 1
X = 2
X = 1
X = 2
X = 3
false

如果您需要独特的解决方案,可以将其放在setof/3中,然后再次致电member/2