Prolog 如何改进在列表中查找特定数字的代码?
我正在编写prolog代码,查找某个数字;如果数字介于0和9之间且不在给定列表中,则该数字是正确的数字。为此,我编写了一个谓词Prolog 如何改进在列表中查找特定数字的代码?,prolog,clpfd,logical-purity,Prolog,Clpfd,Logical Purity,我正在编写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],
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]).
所以这段代码基本上是说,如果可能的数字列表的头已经是第二个列表的一个成员,那么就从头上切下,然后用尾递归继续。
如果元素不在第二个列表中,则第二个子句将触发并告诉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
首先,代码不起作用。考虑: ?- number(Xs, Ys, N). nontermination 在最普遍的情况下: ?- 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 . ?-良好的_数(N,Ls)。 Ls=[], N在0..9; Ls=[[u 2540], N在0..9中, N\=\u 2540; Ls=[[u 2750,[u 2756], N在0..9中, N\=\u 2756, N\=\u 2750。 这只需要两行代码,我们就实现了一个非常一般的关系
有关更多信息,请参见。首先,谓词不起作用,也不检查所有必需的约束(例如,介于0和9之间) 有几件事:
- 您解包了第二个列表
,但在调用[H|T]
时重新打包了它;相反,您可以使用list成员(XH[H|T])
(不过这稍微改变了谓词的语义,但对描述更为准确)李>L
- 您检查两次
ship李>member/2
- 您不检查该值是否是介于
和0
之间的数字(而且还是整数)9
number(Ns, L, Number) :-
member(Number, Ns),
integer(Number),
0 =< Number,
Number =< 9,
\+ member(Number, L).
我们还可以使用ConstraintLogicp在FiniteD域库上编程,并使用in/2
谓词:
number(Ns, L, Number) :-
member(Number, Ns),
between(0, 9, Number),
\+ member(Number, L).
:- use_module(library(clpfd)).
number(Ns, L, Number) :-
member(Number, Ns),
Number in 0..9,
\+ member(Number, L).
还有其他一些事情可能出错。例如,我们用\+member(Number,L)检查非成员身份。
但是如果L
不固定,这将失败,我们可以使用元谓词maplist
构造列表,然后对每个元素调用谓词,而不是建议元素都不等于Number
的列表。我们希望调用每个元素的谓词是该元素不等于Number
,因此我们可以使用:
:- use_module(library(clpfd)).
number(Ns, L, Number) :-
member(Number, Ns),
Number in 0..9,
maplist(#\=(Number), L).
:- use_module(library(clpfd)).
number(Ns, L, Number) :-
member(Number, Ns),
Number in 0..9,
\+ member(Number, L).
:- use_module(library(clpfd)).
number(Ns, L, Number) :-
member(Number, Ns),
Number in 0..9,
maplist(#\=(Number), L).