我正在尝试创建一个谓词,它返回包含由我给出的某个数字的列表元素.
例:
?- where_is_it( [ [1,2,3] , [1,2,7] , [4,5] , [8] ] , 7 , X ).
X=[1,2,7].
Run Code Online (Sandbox Code Playgroud)
我是一个相对较新的prolog程序员,所以这是我的代码:
where_is_it([],_,[]).
where_is_it([H|T],Num,H):-
member([Num],H),!,
where_is_it(T,Num,[]).
Run Code Online (Sandbox Code Playgroud)
非常感谢你
where_is_it(Xss, X, Xs) :-
member(Xs, Xss),
member(X, Xs).
Run Code Online (Sandbox Code Playgroud)
您可以使用if_/3
和memberd_t/2
来自模块reif以便更具确定性:
where_is_it([H|T], X, L) :-
if_(memberd_t(X,H), L=H, where_is_it(T, X, L)).
Run Code Online (Sandbox Code Playgroud)
这是仅使用tmember/2和(=)/3且没有任何显式递归的版本:
where_is_it(Xss,X,Xs) :-
tmember(=(Xs),Xss),
tmember(=(X),Xs).
Run Code Online (Sandbox Code Playgroud)
OP 给出的查询按预期工作:
?- where_is_it([[1,2,3],[1,2,7],[4,5],[8]],7,X).
X = [1,2,7] ? ;
no
Run Code Online (Sandbox Code Playgroud)
该版本的一些功能: 如果该元素出现在多个列表中(与if_/3和memberd_t的版本不同):
?- where_is_it([[1,2,3],[1,2,7],[4,5],[8]],1,X).
X = [1,2,3] ? ;
X = [1,2,7] ? ;
no
Run Code Online (Sandbox Code Playgroud)
一个列表中多次出现的元素仅匹配一次(与 member/2 的版本不同):
?- where_is_it([[1,2,3,1],[4,5],[8]],1,X).
X = [1,2,3,1] ? ;
no
Run Code Online (Sandbox Code Playgroud)
同一列表的多次出现仅匹配一次(与 member/2 的版本不同):
?- where_is_it([[1,2,3],[1,2,3],[4,5],[8]],1,X).
X = [1,2,3] ? ;
no
Run Code Online (Sandbox Code Playgroud)
即使使用开放列表(与 member/2 的版本以及if_/3和memberd_t的版本不同):
?- where_is_it([[1,2,3],[1,2,7],[4,5],[8],[1|_]],1,X).
X = [1,2,3] ? ;
X = [1,2,7] ? ;
X = [1|_A],
dif([1|_A],[1,2,3]),
dif([1|_A],[1,2,7]) ? ;
no
Run Code Online (Sandbox Code Playgroud)
如果实际元素是可变的:
?- where_is_it([[1,2,3],[8]],Y,X).
X = [1,2,3],
Y = 1 ? ;
X = [1,2,3],
Y = 2 ? ;
X = [1,2,3],
Y = 3 ? ;
X = [8],
Y = 8 ? ;
no
Run Code Online (Sandbox Code Playgroud)
最通用的查询(与 member/2 的版本(仅略有不同)以及if_/3和memberd_t的版本):
?- where_is_it(Xss,X,Xs).
Xs = [X|_A],
Xss = [[X|_A]|_B] ? ;
Xs = [_A,X|_B],
Xss = [[_A,X|_B]|_C],
dif(X,_A) ? ;
Xs = [_A,_B,X|_C],
Xss = [[_A,_B,X|_C]|_D],
dif(X,_B),
dif(X,_A) ? ;
...
Run Code Online (Sandbox Code Playgroud)
有一些约束(与 member/2 的版本(仅略有不同)以及if_/3和memberd_t的版本):
?- Xss=[_,_],Xs=[_,_],where_is_it(Xss,X,Xs).
Xs = [X,_A],
Xss = [[X,_A],_B] ? ;
Xs = [_A,X],
Xss = [[_A,X],_B],
dif(X,_A) ? ;
Xs = [X,_A],
Xss = [_B,[X,_A]],
dif([X,_A],_B) ? ;
Xs = [_A,X],
Xss = [_B,[_A,X]],
dif(X,_A) ? ;
no
Run Code Online (Sandbox Code Playgroud)
这是一个实现使用tmember/2
:
where_is_it(InList, X, L):- tmember(check(X,L),InList).
check(X,L,L1,T):- if_( memberd_t(X,L1), (T = true, L = L1), T = false).
Run Code Online (Sandbox Code Playgroud)
小智 2
您也许应该阅读您的条款内容?您可能需要一个子句,其中表示“如果 X 是 H 的成员,则 H 是解决方案”:
where_is_it([H|_], X, H) :-
member(X, H).
Run Code Online (Sandbox Code Playgroud)
然后你还需要另一个子句来说明也许你在列表的其余部分有一个解决方案:
where_is_it([_|T], X, H) :-
where_is_it(T, X, H).
Run Code Online (Sandbox Code Playgroud)
也许这对于开始就足够了?