删除Prolog中第一次出现的元素

时间:2013-11-05 05:43:52

标签: list prolog

我正在尝试从Prolog中的列表中删除第一个元素。

我的代码:

remove_first_X(X,[X|Xs],Xs). %remove X
remove_first_X(X,[Y|Xs],[Y|Xs]) :-
   remove_first_X(X,Xs,Xs).

不起作用:

?- remove_first_X(1,[1,2,3],[2,3]).
true.

?- remove_first_X(1,[2,1,3],[2,3]).
false.

请帮忙! : - )

另一种尝试更接近:

remove_first_X(X,[X|Xs],Xs).
remove_first_X(X,[Y|Xs],[Y|Ys]) :-
   remove_first_X(X,Xs,Ys).

但是在第一次出现后删除了X:

?- remove_first_X(1,X,[2,1,0]).
X = [1, 2, 1, 0] ;
X = [2, 1, 1, 0] ;
X = [2, 1, 1, 0] ;
X = [2, 1, 0, 1] ;
false.

2 个答案:

答案 0 :(得分:4)

@ chamini2给出的实现是 impure ,并且在使用非基础术语时可能会变得在逻辑上不合理。请考虑以下两个查询:

?- E=1, remove_first_X(E,Xs,[2,1,0]).
E = 1, Xs = [1,2,1,0] ;
E = 1, Xs = [2,1,1,0] ;
false.

?- remove_first_X(E,Xs,[2,1,0]), E=1.
E = 1, Xs = [1,2,1,0] ;
false.                                    % one solution is missing!

救援!(\=)/2替换为dif/2,代码逻辑纯

remove_1st_x(X,[X|Xs],Xs).
remove_1st_x(X,[Y|Xs],[Y|Ys]) :- 
    dif(X,Y),
    remove_1st_x(X,Xs,Ys).

让我们再次运行查询,这次是改进的实现:

?- E=1, remove_1st_x(E,Xs,[2,1,0]).
E = 1, Xs = [1,2,1,0] ;
E = 1, Xs = [2,1,1,0] ;
false.

?- remove_1st_x(E,Xs,[2,1,0]), E=1.
E = 1, Xs = [1,2,1,0] ;
E = 1, Xs = [2,1,1,0] ;
false.

那更好! OP提供的其他查询也可以像他们一样工作:

?- remove_1st_x(1,[1,2,3],[2,3]).
true ;
false.

?- remove_1st_x(1,[2,1,3],[2,3]).
true ;
false.

?- remove_1st_x(1,X,[2,1,0]).
X = [1,2,1,0] ;
X = [2,1,1,0] ;
false.

编辑2015-05-07

remove_1st_x/3的上述实施在确定性地成功时留下了无用的选择点。 在保留的同时,让我们摆脱这种低效率!

使用if_/3(=)/3equal_truth/3)定义remove_1st_x/3@false an answer来定义问题" {{3} }",我们可以像这样定义remove_1st_x(E,[X|Xs],Ys) :- if_(X=E, Xs=Ys, (Ys=[X|Ys0],remove_1st_x(E,Xs,Ys0))).

?- remove_1st_x(1,[2,1,3],Ys).
Ys = [2,3].

?- remove_1st_x(1,[2,1,3],[2,3]).
true.

?- remove_1st_x(1,[1,2,3],[2,3]).
true.

让我们再次运行查询!请注意,所有这些都是确定性的。

1_a.jpg
1_b.jpg
1_c.jpg
2_a.jpg
3_a.jpg
3_b.jpg

答案 1 :(得分:2)

尝试在第二次尝试中添加一件事

remove_first_X(X,[X|Xs],Xs).
remove_first_X(X,[Y|Xs],[Y|Ys]) :- 
    X \= Y,
    remove_first_X(X,Xs,Ys).

您运行的示例中发生的是

  • 对于X = [1, 2, 1, 0],它只是尝试了remove_first_X
  • 的第一个条款
  • 下一个元素是通过第二个子句再次进入第一个子句,你可以看到没有任何东西禁止X = Y,这是你应该确定的。