如何将列表转换为Prolog中的循环列表?

时间:2016-06-04 07:57:43

标签: list prolog circular-list

我有一个列表backend "inmem" { address = "127.0.0.1:8500" path = "vault" } listener "tcp" { address = "127.0.0.1:9000" tls_disable = 1 } listener "tcp" { address = "127.0.0.1:8200" tls_disable = 0 tls_cert_file = "C:/my/server.pem" tls_key_file = "C:/my/serverkey.pkcs8" } ,我需要将每个数字与数字旁边的数字进行比较,同时比较第一个数字和最后一个数字。想想这个列表是在圆桌旁。任何帮助将不胜感激。谢谢你......

3 个答案:

答案 0 :(得分:3)

您可能不需要循环列表 - 非圆形列表也可以...

:- 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).

使用SICStus Prolog 4.3.2进行样本查询 1

?- 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.

修改

如果您使用上述“包裹的相邻”访问模式与不同的约束,请考虑提升常用功能!您可以将它们转换为可重复使用的,如下所示:

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_difNU/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 答案是为了简洁和可读性而手动后处理的。
脚注2 :无需担心! Prolog给我们的答案没有改变 - 根本没有改变。 功能

答案 1 :(得分:1)

创建新列表以进行比较:

comp_list([X|Rest],L) :-
    append([X|Rest],[X],L).

示例:

?- comp_list([1,2,3],L).
L = [1, 2, 3, 1].

答案 2 :(得分:0)

在递归访问期间继续执行第一个元素,最后停止:

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))).