我想解决的问题如下:
我给出了一个排序列表,我必须在列表中配对第一个和最后一个项目。然后我必须将列表中的第2个和(最后1个)项配对,直到列表为空或剩下1个元素。然后我必须返回对的列表。
我决定针对这个问题采取的步骤是首先检查列表的长度是否大于1.如果不是,则表示我们有一个0或1个元素的列表。
然后我获取给定列表中的第一个和最后一个项目,从列表中删除它们,配对它们,然后在新列表上递归调用相同的谓词。一旦我一直走到0/1项目,然后我会弹回并将它们附加到我的返回列表中。
我遇到的问题是,当我尝试将对L = [first,last]
附加到我的返回列表时,它会出错。我的代码列在下面。
T
是我的输入列表。
first/2
只获取列表中的第一项。 pair/3
从P1
和P2
删除了一些信息,然后创建L = [P1,P2]
。
getMatches(T,K,ReturnList) :-
( length(T,Val),
Val > 1,
first(T,P1),
last(T, P2),
delete(T,P1,G),
delete(G,P2,H),
pair(P1,P2,L),
getMatches(H,K,ReturnList),
append(L,K,ReturnList)
; first(T,_),
K = []
).
使用示例:
如果是T = [1, 2, 3, 4, 5]
那么
ReturnList = [[1,5], [2, 4]]
应该成立。
答案 0 :(得分:2)
我们根据常用的列表谓词append/3
定义list_pairs/2
。
list_pairs([] , []). list_pairs([_], []). list_pairs([A,B|Xs0], [A-Z|Yss]) :- append(Xs, [Z], [B|Xs0]), list_pairs(Xs, Yss).
请注意,我们不会将一对X
和Y
表示为列表[X,Y]
,而是将其作为复合X-Y
。这个惯例也是惯用的,广泛的,也是更有效的!
以下是list_pairs/2
的最常见查询:
?- list_pairs(Es, Pss). Es = [] , Pss = [] ; Es = [_] , Pss = [] ; Es = [A,B] , Pss = [A-B] ; Es = [A,_,B] , Pss = [A-B] ; Es = [A,B,C,D] , Pss = [A-D,B-C] ; Es = [A,B,_,C,D] , Pss = [A-D,B-C] ; Es = [A,B,C,D,E,F] , Pss = [A-F,B-E,C-D] ; Es = [A,B,C,_,D,E,F] , Pss = [A-F,B-E,C-D] ; Es = [A,B,C,D,E,F,G,H] , Pss = [A-H,B-G,C-F,D-E] ; Es = [A,B,C,D,_,E,F,G,H], Pss = [A-H,B-G,C-F,D-E] ...
答案 1 :(得分:2)
这是对this earlier answer的跟进,并对其进行了改进 避免创造无用的选择点和 将O(N 2 )的Big-O复杂度降低到O(N)。
list_pairs_lin([], []). list_pairs_lin([X|Xs], XYs) :- reverse(Xs, Ys), ahead_keys_values_pairs(Xs, [X|Xs], Ys, XYs). ahead_keys_values_pairs([], _, _, []). ahead_keys_values_pairs([_|Fs0], [X|Xs], [Y|Ys], [X-Y|XYs]) :- maybe_ahead(Fs0, Fs), ahead_keys_values_pairs(Fs, Xs, Ys, XYs). maybe_ahead([], []). maybe_ahead([_|Xs], Xs).
让我们用SWI-Prolog 7.3.15运行一些查询!
使用list_pairs_lin/2
时,我们仍然可以得到合理的答案吗?
?- length(Es, N), numlist(1, N, Es), list_pairs_lin(Es, Pss). N = 1, Es = [1] , Pss = [] ; N = 2, Es = [1,2] , Pss = [1-2] ; N = 3, Es = [1,2,3] , Pss = [1-3] ; N = 4, Es = [1,2,3,4] , Pss = [1-4,2-3] ; N = 5, Es = [1,2,3,4,5] , Pss = [1-5,2-4] ; N = 6, Es = [1,2,3,4,5,6] , Pss = [1-6,2-5,3-4] ; N = 7, Es = [1,2,3,4,5,6,7] , Pss = [1-7,2-6,3-5] ; N = 8, Es = [1,2,3,4,5,6,7,8] , Pss = [1-8,2-7,3-6,4-5] ; N = 9, Es = [1,2,3,4,5,6,7,8,9], Pss = [1-9,2-8,3-7,4-6] ...
是的!复杂性怎么样?
?- set_prolog_flag(toplevel_print_anon, false). true. ?- numlist(1, 5000, _Xs), time(list_pairs(_Xs,_)). % 6,252,500 inferences, 2.302 CPU in 2.301 seconds (100% CPU, 2716404 Lips) true ; % succeeds, but leaves behind useless choicepoint % 2,503 inferences, 0.001 CPU in 0.001 seconds (100% CPU, 1716259 Lips) false. % terminates universally ?- numlist(1, 5000, _Xs), time(list_pairs_lin(_Xs,_)). % 10,003 inferences, 0.003 CPU in 0.003 seconds (100% CPU, 3680523 Lips) true. % succeeds deterministically
答案 2 :(得分:1)
getMatches(List, ReturnList) :- % getMatches/2
getMatches(List, [], Answer),
reverse(Answer, ReturnList),
!.
getMatches(List, ListAns, ListAns) :- % getMatches/3
length(List, L),
L < 2.
getMatches([H | Tail], List, Ans) :-
last(Tail, Last),
delete(Tail, Last, NewTail),
append([[H, Last]], List, NewList),
getMatches(NewTail, NewList, Ans).
和
?- getMatches([1,2,3,4,5],X).
X = [[1, 5], [2, 4]].