Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.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
Prolog编程中的问题_Prolog - Fatal编程技术网

Prolog编程中的问题

Prolog编程中的问题,prolog,Prolog,您好,我是Prolog新手,正在尝试用Prolog编写小程序以学习它 我已经写了一个程序来删除位置元素,意思是删除(List,2,Ans)将删除位置2,4,6,8的所有元素。。。。从列表中。。。下面是我的逻辑 remove(L,N,Ans):- length(L,LEN), T1 is 1 mod N, add(L,N,[],LEN,T1,Res). add(L,N,Ans,0,T,Ans). add([H|T],N,Ans,LEN,0,Res):- LEN1 is L

您好,我是Prolog新手,正在尝试用Prolog编写小程序以学习它

我已经写了一个程序来删除位置元素,意思是删除(List,2,Ans)将删除位置2,4,6,8的所有元素。。。。从列表中。。。下面是我的逻辑

remove(L,N,Ans):-
   length(L,LEN),
   T1 is 1 mod N,
   add(L,N,[],LEN,T1,Res).

add(L,N,Ans,0,T,Ans).
add([H|T],N,Ans,LEN,0,Res):-
   LEN1 is LEN-1,
   T1 is 1 mod N,
   add(T,N,Ans,LEN1,T1,Res).
add([H|T],N,Ans,LEN,T,Res):-
   T =\= 0, LEN =\= 0,
   LEN1 is LEN-1,
   T1 is T1+1,
   T2 is T1 mod N,
   append([H],Ans,Result),
   add(T,N,Result,LEN1,T2,Res).
但每次我运行它时,在查找add时都会失败。下面是针对特定实例的程序跟踪

[trace]  ?- remove([1,2,3,4,5,6,7,8],2,X).
   Call: (6) remove([1, 2, 3, 4, 5, 6, 7, 8], 2, _G2941) ? creep
   Call: (7) length([1, 2, 3, 4, 5, 6, 7, 8], _G3039) ? creep
   Exit: (7) length([1, 2, 3, 4, 5, 6, 7, 8], 8) ? creep
   Call: (7) _G3041 is 1 mod 2 ? creep
   Exit: (7) 1 is 1 mod 2 ? creep
   Call: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep
   Fail: (7) add([1, 2, 3, 4, 5, 6, 7, 8], 2, [], 8, 1, _G3046) ? creep
   Fail: (6) remove([1, 2, 3, 4, 5, 6, 7, 8], 2, _G2941) ? creep
false.

有人知道问题出在哪里吗?

希望您能在代码中找到解决方法。我认为学习一门语言更好的方法实际上是调试它。。。潜伏者的评论已经让你走上了正确的轨道。但我想展示使用内置程序如何改变您的视角(当然,这对于任何语言都是正确的,不仅仅是Prolog)

当你

没有规则可以匹配,特别是T不能是列表和数字1

add([H|T],N,Ans,LEN,T,Res):-

也就是说,我不确定应该如何更正代码…

一个常见的prolog习惯用法是使用“helper”谓词,它实际执行工作并携带 维护状态的一个或多个附加参数。在这种情况下,我们需要一个计数器来跟踪 我们在来源列表中的位置

remove( Xs , N , Ys ) :-
  remove( Xs , 1 , N , Ys ). % Note the additional argument (our counter) initialized to 1

remove( []     , _ , _ , []     ) .  % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , [X|Ys] ) :- % otherwise,
  P mod N =\= 0 ,                    % - if the current position is NOT a multiple of N,
  P1 is P+1 ,                        % - we increment the position,
  remove(Xs,P1,N,Ys)                 % - and recurse down, adding the head of the list
  .                                  %   to the result.
remove( [_|Xs] , P , N ,    Ys  ) :- % otherwise,
  P mod N =:= 0 ,                    % - if the current position is a multiple of N,
  P1 is P1+1 ,                       % - increment the position,
  remove(Xs,P1,N1,Ys)                % - and recurse down, discarding the head of the list
  .                                  % Easy!
您可能会注意到一些重复的代码。本着保持干燥的精神,我们可以对其进行重构:

remove( [] , _ , _ , [] ) .       % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , Ys ) :-  % otherwise,
  keep_or_discard(X,P,N,Ys,Y1) ,  % - decided whether to keep or discard the current list head
  P1 is P+1 ,                     % - increment the counter
  remove( Xs , P1 , N , Y1 )      % - and recurse down.
  .

keep_or_discard( _ , P , N , Ys , Ys ) :-    % if P is a multiple of N
  P mod N =:= 0 ,                            % - discard X,
  ! .                                        % - and eliminate the choice point.
keep_or_discard( X , _ , _ , Ys , [X|Ys] ) . % otherwise, we keep it.
有些人不喜欢使用切割来明确消除选择点,因此,我们也可以通过使用prolog的运算符来进行重构:

remove( [] , _ , _ , [] ) .       % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , Ys ) :-  % otherwise,
  ( P mod N =:= 0                 % - if P is a multiple of N,
  ->    Y1  = Ys                  %   - then we discard the list head
  ;  [X|Y1] = Ys                  %   - otherwise, we add it to the result list
  ) ,                             % - and then ...
  P1 is P+1 ,                     % - increment the counter
  remove( Xs , P1 , N , Y1 )      % - and recurse down.
  .

当然,这两种重构是否比原始重构更清晰或更容易理解是个人的选择。

但是在这种情况下,最后一个add将通过1与T的统一来选择。
1 mod N
总是
1
如果
N>1
不是吗?@潜伏者我不清楚它在调用Call时:(7)add([1,2,3,4,5,6,7,8],2,[],8,1,_G3046)?爬行…为什么它不能通过最后一次添加来细化这个目标或统一这个目标…是的…这很好,但我正在学习porlog的逻辑…并尝试从以下链接解决问题
bagof/3
更适合这种解决方案,因为它也按预期处理变量。@JatinKhurana:当然,哟你是对的。请注意,我在我的代码片段中建议了一个表达式,它可以帮助你更正代码……你能告诉我为什么不能将7点的通话与最后一次添加统一起来……我已经厌倦了从最后1-2小时开始想象它。@JatinKhurana它不能将7点的通话统一起来,因为Carlo在他的回答中告诉你:你在尝试选择在第一个参数中使用
T
作为列表,在第五个参数中使用数字。调用不匹配前两个
add
子句,因为第四个或第五个参数都不是
0
。它不匹配最后一个子句,因为第一个参数将
T
实例化为
[2,3,4,5,6,7,8]
第五个参数试图将
T
实例化为
1
。不能两者都是。您需要为第五个参数选择一个不同的变量名。您还需要修复
T1是T1+1
。这很好……但我的问题是为什么它不统一add([1,2,3,4,5,6,7,8],2,[],8,1,_G3046)最后加上…为什么它是给假。。。。
remove( [] , _ , _ , [] ) .       % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , Ys ) :-  % otherwise,
  keep_or_discard(X,P,N,Ys,Y1) ,  % - decided whether to keep or discard the current list head
  P1 is P+1 ,                     % - increment the counter
  remove( Xs , P1 , N , Y1 )      % - and recurse down.
  .

keep_or_discard( _ , P , N , Ys , Ys ) :-    % if P is a multiple of N
  P mod N =:= 0 ,                            % - discard X,
  ! .                                        % - and eliminate the choice point.
keep_or_discard( X , _ , _ , Ys , [X|Ys] ) . % otherwise, we keep it.
remove( [] , _ , _ , [] ) .       % when we exhaust the source list, we're done.
remove( [X|Xs] , P , N , Ys ) :-  % otherwise,
  ( P mod N =:= 0                 % - if P is a multiple of N,
  ->    Y1  = Ys                  %   - then we discard the list head
  ;  [X|Y1] = Ys                  %   - otherwise, we add it to the result list
  ) ,                             % - and then ...
  P1 is P+1 ,                     % - increment the counter
  remove( Xs , P1 , N , Y1 )      % - and recurse down.
  .