使用 repeat 对序言中的事实集合进行排序
Using repeat to sort a collection of facts in prolog
我有一组事实 set/2,其中第一个变量是集合的标识符,第二个是与标识符关联的值。
例如:
set(a,2).
set(a,c).
set(a,1).
set(a,a).
set(a,3).
set(a,b).
我需要构造一个谓词 ordering/2(使用重复运算符),它将按字典顺序输出特定集合的值。
例如
?- ordering(a,Output).
会导致
[1,2,3,a,b,c].
到目前为止我所做的是这段代码:
ordering(Input,Output):-
findall(X,set(Input,X),List),
repeat,
doSort(List)
sort(List, OrderedList),
Output = OrderedList.
这里的想法是谓词将找到与特定输入关联的集合的所有值,并将列表变量与它们统一起来。现在我们有了未排序的列表。这是我不完全确定的部分。谓词应该继续在列表上使用某种特定的 doSort,然后使用 sort/2 检查列表,如果它是按字典顺序排列的,则将其与输出统一。
任何人都可以澄清我是否走在正确的道路上,如果是,那么应该如何实施 doSort?
好吧,我在@Daniel lyon 的帮助下尝试了一种答案:
ordering(Input,Output):-
findall(X,set(Input,X),List),
repeat,
permutation(List,PermutationList),
sort(PermutationList, SortedList),
Output= SortedList , !.
大体思路是一样的,对于repeat循环,predicate会统一List和PermutationList,尝试它的所有变体并用sort/2检查它们的正确性,直到达到正确的排列,统一它与SortedList,之后它将Output与SortedList统一。剪切就在那里,所以我只会得到一次输出。
?- % init test DB
| maplist([X]>>assert(set(a,X)), [c,b,a,1,2,3]).
true.
?- % find first
| set(a,X), \+ (set(a,Y), Y @< X).
X = 1 ;
false.
?- % find next, given - hardcoded here as 1 - previous
| set(a,X), X @> 1, \+ (set(a,Y), Y @> 1, Y @< X).
X = 2 ;
false.
现在我们可以尝试使这些查询可重用:
ordering(S,[H|T]) :- first(S,H), ordering(S,H,T).
first(S,X) :- set(S,X), \+ (set(S,Y), Y @< X).
next(S,P,X) :- set(S,X), X @> P, \+ (set(S,Y), Y @> P, Y @< X).
ordering(S,P,[X|T]) :- next(S,P,X), ordering(S,X,T).
ordering(_,_,[]).
正确地说,我们需要在某处进行切割。你能认出那个地方吗?
我有一组事实 set/2,其中第一个变量是集合的标识符,第二个是与标识符关联的值。
例如:
set(a,2).
set(a,c).
set(a,1).
set(a,a).
set(a,3).
set(a,b).
我需要构造一个谓词 ordering/2(使用重复运算符),它将按字典顺序输出特定集合的值。 例如
?- ordering(a,Output).
会导致
[1,2,3,a,b,c].
到目前为止我所做的是这段代码:
ordering(Input,Output):-
findall(X,set(Input,X),List),
repeat,
doSort(List)
sort(List, OrderedList),
Output = OrderedList.
这里的想法是谓词将找到与特定输入关联的集合的所有值,并将列表变量与它们统一起来。现在我们有了未排序的列表。这是我不完全确定的部分。谓词应该继续在列表上使用某种特定的 doSort,然后使用 sort/2 检查列表,如果它是按字典顺序排列的,则将其与输出统一。
任何人都可以澄清我是否走在正确的道路上,如果是,那么应该如何实施 doSort?
好吧,我在@Daniel lyon 的帮助下尝试了一种答案:
ordering(Input,Output):-
findall(X,set(Input,X),List),
repeat,
permutation(List,PermutationList),
sort(PermutationList, SortedList),
Output= SortedList , !.
大体思路是一样的,对于repeat循环,predicate会统一List和PermutationList,尝试它的所有变体并用sort/2检查它们的正确性,直到达到正确的排列,统一它与SortedList,之后它将Output与SortedList统一。剪切就在那里,所以我只会得到一次输出。
?- % init test DB
| maplist([X]>>assert(set(a,X)), [c,b,a,1,2,3]).
true.
?- % find first
| set(a,X), \+ (set(a,Y), Y @< X).
X = 1 ;
false.
?- % find next, given - hardcoded here as 1 - previous
| set(a,X), X @> 1, \+ (set(a,Y), Y @> 1, Y @< X).
X = 2 ;
false.
现在我们可以尝试使这些查询可重用:
ordering(S,[H|T]) :- first(S,H), ordering(S,H,T).
first(S,X) :- set(S,X), \+ (set(S,Y), Y @< X).
next(S,P,X) :- set(S,X), X @> P, \+ (set(S,Y), Y @> P, Y @< X).
ordering(S,P,[X|T]) :- next(S,P,X), ordering(S,X,T).
ordering(_,_,[]).
正确地说,我们需要在某处进行切割。你能认出那个地方吗?