[英]Index of first element greater than X (Prolog)
我知道如何在Prolog中找到特定元素的索引,但有沒有辦法找到大於X
的數字的第一個實例的索引。 例如,假設我有一個列表,但是列表中的某個地方有一個大於1的隨機數。 我怎樣才能找到大於1
的第一個實例的索引? 我是Prolog的新手,並且不太善於謂詞的子目標。
您希望在列表 , 索引和值之間編寫關系。 我們稱之為list_1stindex_gt / 3。 有第四個參數來跟蹤當前指數是恰當的。 但是,不用這個累加器來打擾用戶會很好,所以你可以使用輔助謂詞和當前索引的附加參數,我們稱之為list_1stindex_gt_ / 4。 假設您想要將索引計數為1
(否則將第四個參數更改為0
),您可以像這樣定義list_1stindex_gt / 3:
:-use_module(library(clpfd)).
list_1stindex_gt(L,I,GT) :-
list_1stindex_gt_(L,I,GT,1).
對於list_1stindex_gt_ / 4,你有2個案例:
列表的頭部大於第三個參數:然后您知道所需的索引。
列表的頭部小於或等於第三個參數:然后將累加器遞增1
並繼續在列表尾部搜索。
你可以在Prolog中寫這樣的:
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([1,1,1,1,5,1,1,2],I,1).
I = 5 ? ;
no
在哪個索引處,大於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
在哪個索引處,第一個元素大於變量X
可以在三個變量的列表中?
?- 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
此外,你可以考慮@ mat建議從你對前一個問題的回答改進:遵循背后的想法(#<)/ 3你可以定義(#>)/ 3然后使用if_ / 3定義list_1stindex_gt_ / 4 :
:-use_module(library(clpfd)).
#>(X, Y, T) :-
zcompare(C, X, Y),
greater_true(C, T).
greater_true(<, false).
greater_true(>, true).
greater_true(=, false).
list_1stindex_gt(L,I,GT) :-
list_1stindex_gt_(L,I,GT,1).
list_1stindex_gt_([X|Xs],I,GT,Acc0) :-
if_(X #> GT,
(I #= Acc0),
(Acc1 #= Acc0+1, list_1stindex_gt_(Xs,I,GT,Acc1))).
這樣,第一個查詢成功,而不會留下不必要的選擇點:
?- list_1stindex_gt([1,1,1,1,5,1,1,2],I,1).
I = 5.
這是一個略有不同的看法:
:- 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
使用SICStus Prolog 4.3.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
感謝clpfd,我們也可以提出非常一般的查詢:
| ?- 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
要獲得L中的任何索引,保持元素V大於N,您可以寫:
?- 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相同的角色,從而提供更多的通用性
這是一個解決方案,正如其他人指出的那樣,它不是通用的,它只有在整數列表和閾值是基礎術語時才有效。
與大多數列表處理謂詞一樣,我們需要遞歸地考慮它:
如果你想要元素的索引(而不是它的實際值),我們還需要跟蹤索引並在步驟2中增加它。為此,我們需要一個輔助謂詞。
%
% 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.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.