首页 > 解决方案 > 将列表列表中的每个不同数字作为解决方案

问题描述

我需要做一个谓词,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 的工作原理。我很感激任何帮助,谢谢!

标签: listprolog

解决方案


你可以从:

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

如果您想要独特的解决方案,您可以将其包含在 a 中setof/3,然后member/2再次调用。


推荐阅读