使用附加条款拼合Prolog中的列表

时间:2018-10-04 20:13:55

标签: recursion prolog

我目前正在开始学习Prolog,并努力解决基本问题。

我当前的任务是创建一个使嵌套列表平坦的谓词。我不应该为此使用cut运算符,累加器或->

我当前的谓词如下:

my_flatten(X,[X]) :- \+ is_list(X).
my_flatten([],[]).
my_flatten([X|Rest],Flattened) :- 
      my_flatten(X,Xflat), 
      my_flatten(Rest,Restflat), 
      append(Xflat,Restflat,Flattened).

这对于大多数输入而言都可以正常工作。但是,查询my_flatten(abc, [abc])返回true而不是false。 因此,元素1必须是一个列表,但是会干扰规则1,该规则标记了嵌套列表递归的底部。

编辑:

flattenx([],[]).
flattenx([H|T], R) :- flattenx(H, FH), append(FH, FT, R) , flattenx(T, FT).
flattenx([H|T], R) :- \+ flattenx(H, FH), R = [H|FT], flattenx(T, FT).

3 个答案:

答案 0 :(得分:2)

我只想证明您的先决条件不能(严格)满足您在 Edit:段落之后发布的解决方案的要求,因为\+(和{{1 }},即if-then-else)只是语法糖,可以使cut'的使用较少出错。您可以改为在头部使用显式模式来指导子句选择。例如

->

答案 1 :(得分:2)

Carlo和Willem发布的解决方案在要扁平化的列表中存在变量时是不正确的。例如

?- flatten([A,B,C], Flatted).
A = B, B = C, C = Flatted, Flatted = [].

或:

?- flatten_no_cut([A,B,C], Flatted).
ERROR: Out of global-stack.

在存在变量的情况下可以正常工作的解决方案是:

flatten(List, Flatted) :-
    flatten(List, [], Flatted).

flatten(Var, Tail, [Var| Tail]) :-
    var(Var),
    !.
flatten([], Flatted, Flatted) :-
    !.
flatten([Head| Tail], List, Flatted) :-
    !,
    flatten(Tail, List, Aux),
    flatten(Head, Aux, Flatted).
flatten(Head, Tail, [Head| Tail]).

通话示例:

?- flatten([A,B,C], Flatted).
Flatted = [A, B, C].

?- flatten([A,[B,1,[a,foo(X)]],C], Flatted).
Flatted = [A, B, 1, a, foo(X), C].

答案 2 :(得分:1)

第一个子句并不是真正必要的:它在列表构造函数中包装不是列表的所有内容。您可能想要。

本质上,可能发生件事:

  1. 我们有一个空列表,然后将其展平,将返回一个空列表;
  2. 我们有一个非空列表,并且第一项也是一个列表,然后我们首先展平该子列表,然后继续该列表;和
  3. 我们有一个非空列表,并且第一项不是 列表,然后我们继续进行平化。

这将导致以下谓词:

php_admin_value

但是,上面的方法不是很优雅,也不是很有效,并且只能在一个方向上工作。我将其保留为练习。