如何改进查找列表中特定数字的代码?

Ros*_*ose 3 prolog

我正在写一些找到一定数量的prolog代码; 如果数字在0到9之间且在给定列表中不存在,则数字是正确的数字.为此,我编写了一个谓词number/3,其中可能的数字作为第一个参数,Rightnumber不能出现的列表和神秘的RightNumber作为第三个参数:

number([XH|XT], [H|T], RightNumber):-
    member(XH, [H|T]), !,
    number(XT, [H|T], RightNumber).
number([XH|_], [H|T], XH):-
    \+ member(XH, [H|T]).
Run Code Online (Sandbox Code Playgroud)

所以这段代码基本上说如果可能的数字列表的头部已经是第二个列表的成员,则剪掉头部并继续用尾部递归.如果元素不在第二个列表中,则第二个子句触发并告诉prolog该数字是RightNumber.它可以只提供可能的第一个数字,这就是我想要使用它的方式.

这段代码在理论上有效,但我想知道是否有更好的方法来记下它?我在我的代码中稍后在另一个谓词中使用此谓词,但它不能作为其中的一部分.我认为它只是阅读第一个条款,而不是第二个条款,因此失败了.

有没有人有想法可以改善我的代码?

示例查询:

?- number([0,1,2,3,4,5,6,7,8,9], [1,2], X).
       X = 3
?- number([0,1,2,3,4,5,6,7,8,9], [1,2,3,4,5,6,7,8,0], X).
       X = 9
Run Code Online (Sandbox Code Playgroud)

mat*_*mat 5

首先,代码也无法正常工作.考虑:

?- number(Xs, Ys, N).
nontermination

这显然很糟糕:对于这个所谓的最一般的查询,我们期望得到答案,但Prolog并没有给我们任何答案这个程序!

所以,我首先建议你从你的程序中消除所有杂质,并专注于你想要的干净的声明性描述.

我给你一个开始:

good_number(N, Ls) :-
        N in 0..9,
        maplist(#\=(N), Ls).

这表明如果 N介于0和9之间,则该关系为真,并且 N与该中的任何整数不同  Ls.有关CLP(FD)约束的更多信息,请参阅.

重要的是,这适用于所有方向.例如:

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

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

?- good_number(N, [1,2,3]).
N in 0\/4..9.

而且以最常见的情况:

?- good_number(N, Ls).
Ls = [],
N in 0..9 ;
Ls = [_2540],
N in 0..9,
N#\=_2540 ;
Ls = [_2750, _2756],
N in 0..9,
N#\=_2756,
N#\=_2750 .

这只有两行代码,我们实现了非常一般的关系.

另请参阅以获取更多信息.