List 大于X的第一个元素的索引(序言)
我知道如何在Prolog中找到特定元素的索引,但是有没有办法找到大于sayList 大于X的第一个元素的索引(序言),list,prolog,clpfd,List,Prolog,Clpfd,我知道如何在Prolog中找到特定元素的索引,但是有没有办法找到大于sayX的数字的第一个实例的索引。例如,假设我有一个所有数字的列表,但是列表中的某个地方有一个大于1的随机数。如何查找大于1的数字的第一个实例的索引?我对Prolog非常陌生,不太擅长谓词的子目标。您想在列表、索引和值之间建立关系。让我们称之为列表\u 1索引\u gt/3。有第四个参数来跟踪当前的指数是很合适的。但是,最好不要用这个累加器来打扰用户,这样您就可以使用和辅助谓词以及当前索引的附加参数,我们称之为list_1sti
X
的数字的第一个实例的索引。例如,假设我有一个所有数字的列表,但是列表中的某个地方有一个大于1的随机数。如何查找大于1
的数字的第一个实例的索引?我对Prolog非常陌生,不太擅长谓词的子目标。您想在列表、索引和值之间建立关系。让我们称之为列表\u 1索引\u gt/3。有第四个参数来跟踪当前的指数是很合适的。但是,最好不要用这个累加器来打扰用户,这样您就可以使用和辅助谓词以及当前索引的附加参数,我们称之为list_1stindex_gt_4。假设您希望在1
处开始计算索引(否则将第四个参数更改为0
),您可以这样定义列表索引:
:-use_module(library(clpfd)).
list_1stindex_gt(L,I,GT) :-
list_1stindex_gt_(L,I,GT,1).
对于列表索引,您有两种情况:
1
,并继续在列表的尾部进行搜索list_1stindex_gt_([X|Xs],I,GT,I) :- % case 1
X #> GT.
list_1stindex_gt_([X|Xs],I,GT,Acc0) :- % case 2
X #=< GT,
Acc1 #= Acc0+1,
list_1stindex_gt_(Xs,I,GT,Acc1).
在三个变量的列表中,大于1的第一个元素可以位于哪个索引处
?- list_1stindex_gt([A,B,C],I,1).
I = 1,
A in 2..sup ? ;
I = 2,
A in inf..1,
B in 2..sup ? ;
I = 3,
A in inf..1,
B in inf..1,
C in 2..sup ? ;
no
?- list_1stindex_gt([A,B,C],I,X).
I = 1,
X#=<A+ -1 ? ;
I = 2,
X#>=A,
X#=<B+ -1 ? ;
I = 3,
X#>=A,
X#=<C+ -1,
X#>=B ? ;
no
在三个变量的列表中,大于变量X
的第一个元素可以位于哪个索引处
?- list_1stindex_gt([A,B,C],I,1).
I = 1,
A in 2..sup ? ;
I = 2,
A in inf..1,
B in 2..sup ? ;
I = 3,
A in inf..1,
B in inf..1,
C in 2..sup ? ;
no
?- list_1stindex_gt([A,B,C],I,X).
I = 1,
X#=<A+ -1 ? ;
I = 2,
X#>=A,
X#=<B+ -1 ? ;
I = 3,
X#>=A,
X#=<C+ -1,
X#>=B ? ;
no
要获取L中的任何索引(包含大于N的元素V),可以编写:
?- L=[1,2,3,1,2,3],N=2, nth1(I,L,V),V>N.
并仅限于一审:
?- L=[1,2,3,1,2,3],N=2, once((nth1(I,L,V),V>N)).
如果您有可用的库(clpfd),并且您的列表的域限制为整数,那么元素/3可以扮演与nth1/3相同的角色,提供更多的通用性。这里有一个解决方案,正如其他人指出的,它不是通用的,它仅在整数列表和阈值是基础项时才起作用 与大多数列表处理谓词一样,我们需要递归地考虑它:
%
% Predicate called by the user:
%
% The element of List at Index is the first one greater than Threshold.
%
idx_first_greater(List, Threshold, Index) :-
% here we use our helper predicate, initializing the index at 1.
idx_first_greater_rec(List, Threshold, 1, Index).
%
% Helper predicate:
%
% idx_first_greater_rec(List, Threshold, CurIdx, FoundIdx) :
% The element of List at FoundIndex is the first one greater
% than Threshold. FoundIdx is relative to CurIdx.
%
% Base case. If the header is greater than the Threshold then we are done.
% FoundIdx will be unified with CurIdx and returned back to the recursion stack.
idx_first_greater_rec([H|_], Threshold, Index, Index) :- H > Threshold, !.
% Recursion. Otherwise increment CurIdx and search in the tail of the list
idx_first_greater_rec([_|T], Threshold, CurIdx, FoundIdx) :-
NewIdx is CurIdx+1,
idx_first_greater_rec(T, Threshold, NewIdx, FoundIdx).
注:
?- idx_first_greater([1,1,1,2,1,1], 1, Idx).
Idx = 4 ;
false.
?- idx_first_greater([1,1,1,2,1,1], 3, Idx).
false.
?- idx_first_greater([], 3, Idx).
false.
这里有一个稍微不同的观点: :- use_module(library(clpfd)). :- use_module(library(lists)). :- asserta(clpfd:full_answer). zs_first_greater(Zs, Index, Pivot) :- append(Prefix, [E|_], Zs), maplist(#>=(Pivot), Prefix), E #> Pivot, length([_|Prefix], Index). % 1-based index 感谢您的帮助,我们还可以询问非常一般的问题:
| ?- zs_first_greater([A,B,C,D], I, X).
I = 1,
A#>=X+1,
A in inf..sup,
X in inf..sup ? ;
I = 2,
A#=<X,
B#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup ? ;
I = 3,
A#=<X,
B#=<X,
C#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup,
C in inf..sup ? ;
I = 4,
A#=<X,
B#=<X,
C#=<X,
D#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup,
C in inf..sup,
D in inf..sup ? ;
no
|?-zs_first_更大([A,B,C,D],I,X)。
I=1,
A#>=X+1,
A在inf..sup中,
在inf..sup?中的X;
I=2,
A#==X+1,
A在inf..sup中,
X在inf..sup中,
B在inf.sup?中;
I=3,
A#=元素/3
和其他clpfd约束不能与一次/1
很好地结合。这不是很普遍。请尝试最一般的查询:?-idx\u first\u more(X,Y,Z)。
或比您的存款更一般的查询。使用Prolog系统的CLP(FD)约束,而不是低级算法,使其更为通用,类似于@tas在另一个答案中所做的。我支持@mat的观点。使用!但是你的代码还有另一个问题:目标idx\u first\u greater(idx\u first\u greater([2,2,2],1,3)
成功了,但应该失败!谢谢@mat,我对clpfd一无所知,我们来看看。目标idx\u first\u greater([1,1,1,2,1,2],1,idx)
给出了两个答案,Idx=4
和Idx=7
。第一个答案正确,第二个答案不正确。Idx\u first\u更大([2,2,2],1,3])。
仍然成功!切割非常棘手。
| ?- zs_first_greater([1,1,1,2,1,1], I, 1).
I = 4 ? ;
no
| ?- zs_first_greater([1,1,1,2,1,1], I, 3).
no
| ?- zs_first_greater([], I, 3).
no
| ?- zs_first_greater([1,1,1,1,5,1,1,2], I, 1).
I = 5 ? ;
no
| ?- zs_first_greater([A,B,C,D], I, X).
I = 1,
A#>=X+1,
A in inf..sup,
X in inf..sup ? ;
I = 2,
A#=<X,
B#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup ? ;
I = 3,
A#=<X,
B#=<X,
C#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup,
C in inf..sup ? ;
I = 4,
A#=<X,
B#=<X,
C#=<X,
D#>=X+1,
A in inf..sup,
X in inf..sup,
B in inf..sup,
C in inf..sup,
D in inf..sup ? ;
no