Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 大于X的第一个元素的索引(序言)_List_Prolog_Clpfd - Fatal编程技术网

List 大于X的第一个元素的索引(序言)

List 大于X的第一个元素的索引(序言),list,prolog,clpfd,List,Prolog,Clpfd,我知道如何在Prolog中找到特定元素的索引,但是有没有办法找到大于sayX的数字的第一个实例的索引。例如,假设我有一个所有数字的列表,但是列表中的某个地方有一个大于1的随机数。如何查找大于1的数字的第一个实例的索引?我对Prolog非常陌生,不太擅长谓词的子目标。您想在列表、索引和值之间建立关系。让我们称之为列表\u 1索引\u gt/3。有第四个参数来跟踪当前的指数是很合适的。但是,最好不要用这个累加器来打扰用户,这样您就可以使用和辅助谓词以及当前索引的附加参数,我们称之为list_1sti

我知道如何在Prolog中找到特定元素的索引,但是有没有办法找到大于say
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相同的角色,提供更多的通用性。这里有一个解决方案,正如其他人指出的,它不是通用的,它仅在整数列表和阈值是基础项时才起作用

    与大多数列表处理谓词一样,我们需要递归地考虑它:

  • 检查列表的标题(其第一个元素)。如果它大于提供的阈值,那么我们就完成了
  • 否则,应用步骤1。到列表的尾部(删除标题后保留的列表)
  • 由于您需要元素的索引(与其实际值相反),我们还需要跟踪索引并在步骤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).
    
    注:

  • 如果传递空列表或未找到大于阈值的元素,则谓词将失败。在我看来,这是一种良好的行为
  • 该解是尾部递归的,因此可以通过Prolog自动进行优化
  • 样本输出:

    ?- 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