我如何将列表转换为 Prolog 中的循环列表?
How can i convert a list into a circular list in Prolog?
我有一个列表 [5, 4, 8, 9, 7, 6]
,我需要将每个数字与下一个数字进行比较,还要将第一个数字和最后一个数字相互比较。想像这个列表是围绕一个循环 table。任何帮助将不胜感激。现在谢谢...
在递归访问期间只进行第一个元素,最后停止:
compare_adj([First|Rest]) :- compare_adj([First|Rest], First).
compare_adj([A,B|T], F) :-
writeln(compare(A,B)),
compare_adj([B|T], F).
compare_adj([Last], First) :-
writeln(compare(Last, First)).
?- compare_adj([5, 4, 8, 9, 7, 6]).
compare(5,4)
compare(4,8)
compare(8,9)
compare(9,7)
compare(7,6)
compare(6,5)
true ;
false.
编辑
尽管效率很低,但我们可以结合一些内置函数来节省一些代码:
compare_adj([First|Rest]) :-
append([First|Rest],[First],Temp),
forall(append(_, [A,B|_], Temp), writeln(compare(A,B))).
您可能不需要循环列表 — 非循环列表就可以...
:- use_module(library(lists), [last/2]).
怎么会这样?非常直截了当:在最后一项前面加上 "lagging" 在所有相邻列表项之间强制执行您的选择约束。
wrapped_adj_dif([E|Es]) :-
last(Es, E0),
adj_dif_prev([E|Es], E0).
adj_dif_prev([], _).
adj_dif_prev([E|Es], E0) :-
dif(E, E0),
adj_dif_prev(Es, E).
示例查询1 使用 SICStus Prolog 4.3.2:
?- wrapped_adj_dif(Xs).
Xs = [_A,_B] , dif(_B,_A), dif(_A,_B)
; Xs = [_A,_B,_C] , dif(_C,_A), dif(_A,_B), dif(_B,_C)
; Xs = [_A,_B,_C,_D], dif(_D,_A), dif(_A,_B), dif(_B,_C), dif(_C,_D)
...
请注意,当第一个参数是非循环基础列表时,上面的代码是确定性的:
?- wrapped_adj_dif([a,b,c,d]).
true.
?- wrapped_adj_dif([a,b,c,a]).
false.
编辑
如果您使用上述 "wrapped adjacent" 具有 不同 约束的访问模式,请考虑提升共同特征!您可以像这样将它们转换为可重复使用的 meta-predicate:
for_all_wrapped_adjacent(P_2, Es) :-
last(Es, E0),
i_mapadj_prev(Es, P_2, E0).
i_mapadj_prev([], _, _).
i_mapadj_prev([E|Es], P_2, E0) :-
call(P_2, E0, E),
i_mapadj_prev(Es, P_2, E).
使用上面的元谓词
wrapped_adj_dif<b>NU</b>/1
的新定义
归结为:
wrapped_adj_difNU(Es) :-
for_all_wrapped_adjacent(dif, Es).
这里又是上面的查询2—这次使用wrapped_adj_difNU/1
:
?- wrapped_adj_difNU([a,b,c,d]).
true. % (unchanged)
?- wrapped_adj_difNU([a,b,c,a]).
false. % (unchanged)
?- wrapped_adj_difNU(Xs).
Xs = [_A,_B] , dif(_B,_A), dif(_A,_B)
; Xs = [_A,_B,_C] , dif(_C,_A), dif(_A,_B), dif(_B,_C)
; Xs = [_A,_B,_C,_D], dif(_D,_A), dif(_A,_B), dif(_B,_C), dif(_C,_D)
... % (unchanged)
脚注 1:
为了简洁和可读性,prolog-toplevel 个答案是 post 手动处理的。
脚注 2:不用担心! Prolog 给我们的答案没有改变——一点也没有。
创建一个新列表以便比较:
comp_list([X|Rest],L) :-
append([X|Rest],[X],L).
示例:
?- comp_list([1,2,3],L).
L = [1, 2, 3, 1].
我有一个列表 [5, 4, 8, 9, 7, 6]
,我需要将每个数字与下一个数字进行比较,还要将第一个数字和最后一个数字相互比较。想像这个列表是围绕一个循环 table。任何帮助将不胜感激。现在谢谢...
在递归访问期间只进行第一个元素,最后停止:
compare_adj([First|Rest]) :- compare_adj([First|Rest], First).
compare_adj([A,B|T], F) :-
writeln(compare(A,B)),
compare_adj([B|T], F).
compare_adj([Last], First) :-
writeln(compare(Last, First)).
?- compare_adj([5, 4, 8, 9, 7, 6]).
compare(5,4)
compare(4,8)
compare(8,9)
compare(9,7)
compare(7,6)
compare(6,5)
true ;
false.
编辑
尽管效率很低,但我们可以结合一些内置函数来节省一些代码:
compare_adj([First|Rest]) :-
append([First|Rest],[First],Temp),
forall(append(_, [A,B|_], Temp), writeln(compare(A,B))).
您可能不需要循环列表 — 非循环列表就可以...
:- use_module(library(lists), [last/2]).
怎么会这样?非常直截了当:在最后一项前面加上 "lagging" 在所有相邻列表项之间强制执行您的选择约束。
wrapped_adj_dif([E|Es]) :- last(Es, E0), adj_dif_prev([E|Es], E0). adj_dif_prev([], _). adj_dif_prev([E|Es], E0) :- dif(E, E0), adj_dif_prev(Es, E).
示例查询1 使用 SICStus Prolog 4.3.2:
?- wrapped_adj_dif(Xs).
Xs = [_A,_B] , dif(_B,_A), dif(_A,_B)
; Xs = [_A,_B,_C] , dif(_C,_A), dif(_A,_B), dif(_B,_C)
; Xs = [_A,_B,_C,_D], dif(_D,_A), dif(_A,_B), dif(_B,_C), dif(_C,_D)
...
请注意,当第一个参数是非循环基础列表时,上面的代码是确定性的:
?- wrapped_adj_dif([a,b,c,d]). true. ?- wrapped_adj_dif([a,b,c,a]). false.
编辑
如果您使用上述 "wrapped adjacent" 具有 不同 约束的访问模式,请考虑提升共同特征!您可以像这样将它们转换为可重复使用的 meta-predicate:
for_all_wrapped_adjacent(P_2, Es) :- last(Es, E0), i_mapadj_prev(Es, P_2, E0). i_mapadj_prev([], _, _). i_mapadj_prev([E|Es], P_2, E0) :- call(P_2, E0, E), i_mapadj_prev(Es, P_2, E).
使用上面的元谓词
wrapped_adj_dif<b>NU</b>/1
的新定义
归结为:
wrapped_adj_difNU(Es) :- for_all_wrapped_adjacent(dif, Es).
这里又是上面的查询2—这次使用wrapped_adj_difNU/1
:
?- wrapped_adj_difNU([a,b,c,d]).
true. % (unchanged)
?- wrapped_adj_difNU([a,b,c,a]).
false. % (unchanged)
?- wrapped_adj_difNU(Xs).
Xs = [_A,_B] , dif(_B,_A), dif(_A,_B)
; Xs = [_A,_B,_C] , dif(_C,_A), dif(_A,_B), dif(_B,_C)
; Xs = [_A,_B,_C,_D], dif(_D,_A), dif(_A,_B), dif(_B,_C), dif(_C,_D)
... % (unchanged)
脚注 1:
为了简洁和可读性,prolog-toplevel 个答案是 post 手动处理的。
脚注 2:不用担心! Prolog 给我们的答案没有改变——一点也没有。
创建一个新列表以便比较:
comp_list([X|Rest],L) :-
append([X|Rest],[X],L).
示例:
?- comp_list([1,2,3],L).
L = [1, 2, 3, 1].