遍历序言列表并返回一个包含所有正值索引的列表

时间:2021-02-13 17:16:26

标签: prolog

我需要获取列表中所有正元素的每个索引,并使用所有这些索引创建一个新列表

例如

[-1,2,-5] -> [1]
[1,2,-5] -> [0,1]

我已经有了一个获取索引的谓词,但我不明白如何遍历每个值并在最后返回一个列表。现在我的谓词看起来像

indexOf([Element|_], Element, 0) :- !.
indexOf([_|Tail], Element, Index) :-
  indexOf(Tail, Element, Index1),
  !,
  Index is Index1+1.

iterate([],Res) :- Res.
iterate([H|T],Res) :- 
    H>0,
    indexOf([H|T],H,Ind),
    append([],[Ind],Res),
    iterate(T,Res).

iterate([H|T],Res) :- 
    H=<0,
    iterate(T,Res).

但编译后,我收到此错误

**Input** 
iterate([-1,-2,3],X).

**Output**

Sandbox restriction!
Could not derive which predicate may be called from
      call(C)
      iterate([],A)
      iterate([3],A)
      iterate([-2,3],A)
      iterate([-1,-2,3],A)

请告诉我,我做错了什么?以及为什么会出现这个错误

2 个答案:

答案 0 :(得分:1)

您错误地使用了 Prolog:

iterate([],Res) :- Res.

调用绑定到 Res 的术语(希望是谓词的名称),但不会返回 Res

SWISH 不会让您执行无法确定它们是否安全的疯狂调用,因此会出现错误。

但是为什么这么复杂的代码呢?按规定做:

% ---
% gimme_positives(List,Positive)
% gimme_positives_2(Idx,List,Positive)
% ---

% We call this

gimme_positives(List,Indexes) :-
   gimme_positives_2(0,List,Indexes).

% This is the "helper" which additionally needs an index

gimme_positives_2(_,[],[]).                  % If List empty, we are done.

gimme_positives_2(Idx,[L|Ls],[Idx|More]) :-  % Case of L positive
   L >= 0,
   IdxPlus is Idx+1,
   gimme_positives_2(IdxPlus,Ls,More).       % recursive call

gimme_positives_2(Idx,[L|Ls],More) :-        % Case of L negative
   L < 0,
   IdxPlus is Idx+1,
   gimme_positives_2(IdxPlus,Ls,More).       % recursive call  

那么:

?- gimme_positives([],X).
X = [] ;
false.

?- gimme_positives([-1,2,-5],X).
X = [1] ;
false.

?- gimme_positives([1,2,-5],X).
X = [0,1] ;
false.

这实际上是 foldl/4 的情况……一旦您对高阶谓词和组合列表感到宾至如归:

gimme_positives_foldl(List,Indexes) :-
   foldl(
      selector,
      List,               % the list of integers        
      [0,Indexes],        % the initial value: index 0 as first, and the RESULT list as second element 
      [_FinalIndex,[]]).  % the final value: an index we don't care about and the termination of the result list: []

selector(L,[Idx,[Idx|More]],[IdxPlus,More]) :-
   L >= 0,
   IdxPlus is Idx+1.

selector(L,[Idx,More],[IdxPlus,More]) :-
   L < 0,
   IdxPlus is Idx+1.

我什至无法完全解释为什么我会这样写。

但它有效:

?- gimme_positives_foldl([],X).
X = [].

?- gimme_positives_foldl([-1,2,-5],X).
X = [1] ;
false.

?- gimme_positives_foldl([1,2,-5],X).
X = [0,1] ;
false

答案 1 :(得分:0)

在 SWI-Prolog 中,您可以使用谓词 nth0/3findall/3

positive_element_indexes(List, Indexes) :-
    findall(Index, 
            (nth0(Index, List, Element), Element > 0),
            Indexes).

一些例子:

?- positive_element_indexes([1,-2,3,-4,5], Indexes).
Indexes = [0, 2, 4].

?- positive_element_indexes([-1,-2,3], Indexes).
Indexes = [2].

?- positive_element_indexes([-1,2,3], Indexes).
Indexes = [1, 2].

?- positive_element_indexes([-1,-2,-3], Indexes).
Indexes = [].
相关问题