如何在SWI-PROLOG中删除两个相等的相邻数字

如何在SWI-PROLOG中删除两个相等的相邻数字,prolog,Prolog,我不熟悉PROLOG,很难完成几项任务。如果有人能在这方面帮助我,那就太好了。这就是我们的想法: 我有一个包含[3413242341]的数字列表,目标是简化这个列表,直到我有一个空列表[]。(数字简化技术)。我将目标细分如下: 谓词初始化 (R1)如果两个相邻的数字相等,程序应删除这两个数字 (R2)如果两个相邻数字差值的绝对值大于1,则程序应能够在两个相邻数字之间切换 (R3)(n,n-1,n)序列必须能够被(n-1,n,n-1)序列替换 这两天我一直在努力学习这个程序,任何帮助都会得到高度重

我不熟悉PROLOG,很难完成几项任务。如果有人能在这方面帮助我,那就太好了。这就是我们的想法:

我有一个包含
[3413242341]
的数字列表,目标是简化这个列表,直到我有一个空列表
[]
。(数字简化技术)。我将目标细分如下:

  • 谓词初始化
  • (R1)如果两个相邻的数字相等,程序应删除这两个数字
  • (R2)如果两个相邻数字差值的绝对值大于1,则程序应能够在两个相邻数字之间切换
  • (R3)(n,n-1,n)序列必须能够被(n-1,n,n-1)序列替换

  • 这两天我一直在努力学习这个程序,任何帮助都会得到高度重视。

    prolog的重要之处在于它是一种声明性语言:你用谓词演算描述解决方案,让prolog推理引擎找出解决方案。prolog程序通常看起来非常像问题陈述。我们开始吧,好吗

    您的问题陈述描述了2条特定规则,并包含(IMHO)第三条隐含规则:

    • 两个相邻的相同数字被完全删除(
      [1,2,2,3]
      → <代码>[1,3])
    • 序列N,N-1,N被交换(
      [8,5,4,5,9]
      → <代码>[8,4,5,4,9])
    • (暗示)其他任何事物都是不变的
    这将提出一个类似这样的解决方案:

    reduce( []         , []         ).                               % When the source list is exhausted, we're done.
    reduce( [N,N|Ns]   , Rs         ) :-             reduce(Ns,Rs) . % Apply Rule #1
    reduce( [N,Q,N|Ns] , [Q,N,Q|Rs] ) :- Q =:= N-1 , reduce(Ns,Rs) . % Apply Rule #2
    reduce( [N|Ns]     , [N|Rs]     ) :-             reduce(Ns,Rs) . % Apply Rule #3: (implied)
    
    reduce( []     ) .       % The empty list is the desired state
    reduce( [N|Ns] ) :-      % otherwise ...
      remove_pairs(Ns,T1) ,  % - apply rule #1 to the entire list  
      do_swaps(T2,T3) ,      % - apply rule #2 to the entire list
      T3 \= [N|Ns] ,         % - if something changed
      reduce( T3 )           % - repeat the exercise with the changed list
      .                      % Easy!
    
    %
    % apply Rule #1 to the entire list:
    % Remove adjacent pairs such that [1,2,2,3] -> [1,3]
    %
    remove_pairs( []       , []     ) .
    remove_pairs( [X]      , [X]    ) .
    remove_pairs( [X,X|Xs] ,    Rs  ) :-          remove_pairs(Ns,Rs) .
    remove_pairs( [X,Y|Xs] , [X|Rs] ) :- X \= Y , remove_pairs(Xs,Rs) .
    
    %
    % Apply Rule #2 to the entire list:
    % Swap N,Q,N where Q is N-1 such that [8,5,4,5,9] -> [8,4,5,4,9]
    %
    do_swaps( []         , []         ) .
    do_swaps( [N]        , [N]        ) .
    do_swaps( [N,Q]      , [N,Q]      ) .
    do_swaps( [N,Q,N|Ns] , [Q,N,Q|Rs] ) :- Q =:= N-1 , do_swaps(Ns,Rs) .
    do_swaps( [N,Q,N|Ns] , [N,Q,N|Rs] ) :- Q =\= N-1 , do_swaps(Ns,Rs) .
    
    当然,我不知道这是否符合你的要求。另一种方法可能是这样的:

    reduce( []         , []         ).                               % When the source list is exhausted, we're done.
    reduce( [N,N|Ns]   , Rs         ) :-             reduce(Ns,Rs) . % Apply Rule #1
    reduce( [N,Q,N|Ns] , [Q,N,Q|Rs] ) :- Q =:= N-1 , reduce(Ns,Rs) . % Apply Rule #2
    reduce( [N|Ns]     , [N|Rs]     ) :-             reduce(Ns,Rs) . % Apply Rule #3: (implied)
    
    reduce( []     ) .       % The empty list is the desired state
    reduce( [N|Ns] ) :-      % otherwise ...
      remove_pairs(Ns,T1) ,  % - apply rule #1 to the entire list  
      do_swaps(T2,T3) ,      % - apply rule #2 to the entire list
      T3 \= [N|Ns] ,         % - if something changed
      reduce( T3 )           % - repeat the exercise with the changed list
      .                      % Easy!
    
    %
    % apply Rule #1 to the entire list:
    % Remove adjacent pairs such that [1,2,2,3] -> [1,3]
    %
    remove_pairs( []       , []     ) .
    remove_pairs( [X]      , [X]    ) .
    remove_pairs( [X,X|Xs] ,    Rs  ) :-          remove_pairs(Ns,Rs) .
    remove_pairs( [X,Y|Xs] , [X|Rs] ) :- X \= Y , remove_pairs(Xs,Rs) .
    
    %
    % Apply Rule #2 to the entire list:
    % Swap N,Q,N where Q is N-1 such that [8,5,4,5,9] -> [8,4,5,4,9]
    %
    do_swaps( []         , []         ) .
    do_swaps( [N]        , [N]        ) .
    do_swaps( [N,Q]      , [N,Q]      ) .
    do_swaps( [N,Q,N|Ns] , [Q,N,Q|Rs] ) :- Q =:= N-1 , do_swaps(Ns,Rs) .
    do_swaps( [N,Q,N|Ns] , [N,Q,N|Rs] ) :- Q =\= N-1 , do_swaps(Ns,Rs) .
    
    这会将每个变换应用于整个列表。如果列表发生更改,我们将递归应用
    reduce/1
    操作,如果列表最终转换为空列表
    []
    ,则该操作将成功,如果转换失败,则最终将失败


    当然,在回溯过程中,它会尝试找到另一种解决方案。

    另一种解决方法是:

    simplify(In, Lst) :-
        simplify(In, [], [], Lst).
    
    
    simplify([], _Deja_vu, RL, L) :- !, reverse(RL, L).
    simplify(In,  Deja_vu, Cur, Lst) :-
        (   r1(In, Out), L =r1; r2(In, Out), L = r2; r3(In, Out), L=r3),
        % we must avoid cycles
        \+member(Out, Deja_vu),
        simplify(Out, [Out| Deja_vu],[L|Cur], Lst).
    
    % If two adjacent numbers are equal, program should remove both of them.
    r1(In, Out) :-
        append(L, [X,X|T], In),
        append(L, T, Out).
    
    % switch between two adjacent digits if the absolute value of
    % their difference is greater than 1.
    r2(In, Out) :-
        append(L, [X,Y|T], In),
        abs(X-Y) > 1,
        append(L, [Y,X|T], Out).
    
    % (n, n-1, n) sequence must be able to be replaced by the (n-1, n, n-1) sequence.
    r3(In, Out) :-
        append(L, [X,Y, X|T], In),
        X =:= Y+1,
        append(L, [Y,X,Y|T], Out).
    

    [3413242341]
    是一个只包含一个元素的列表,编号3413242341什么是“谓词初始化”,您从何处获得它?测试用例在何处?在两天内,你肯定已经制作了一些。这些规则是如何相互作用的?如果两个规则发生冲突,例如规则
    R3
    可以与
    R1
    冲突。@EugeneSh.:当然可以,但是假设您有一个带有
    [4,3,4]
    的列表,您首先要做什么
    (R1)
    删除邻接词从而
    [4]
    (R3)
    [3,4,3]
    ?亲爱的尼古拉斯·凯里,首先我要对你的支持以及你真正有用的提示和评论表示衷心的感谢。你让我更容易理解。但是你能更详细地告诉我第一种解决方案和第二种解决方案的确切区别吗?提前谢谢。非常感谢JOEL76,你能指导我用SWI-PROLOG进行案例测试吗?提前感谢我使用SWi Prolog,您只需尝试简化([3,4,1,3,2,4,2,3,4,1],L)感谢您的回复,但在SWi Prolog上尝试之后。程序陷入了无限循环。结果如下L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2,r2,r2 |……];L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2 |……];L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2 |……];L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2 |……];L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2 |……];L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2 |……];L=[r2,r2,r2,r1,r2,r2,r2,r2,r2,r2,r2 |……]。。。。。。。。。。等等有什么建议吗?是的,有很多解决方案。我有一个小问题要问你,目的是简化数字列表上的搜索方法,以便在最后有一个空列表(理想状态)。正如我们所看到的,它不太清楚什么时候会发生。如果你能更详细地解释给我听,我真的很感激。提前谢谢。