如何在X之后创建所有元素的数组?

时间:2015-03-10 12:26:37

标签: prolog predicate

我需要编写一个谓词next(X, List1, List2),它返回List2,这是一个直接跟在X之后的元素数组。

例如,

next(v1,[v1,v2,v3,v1,v2,v1,v5],L) returns L=[v2,v2,v5]
next(b,[b,k,m,b,j],L) returns L=[k,j]
next(s,[s,b,c,d,e,f,s,c,s,g],L) returns L=[b,c,g]
....

我知道必须使用递归和尾部。

我想我知道逻辑以及谓词应该如何工作,但我无法让它工作。以下是如果用户输入next(a,[a,b,c,a,b,c],L).

,我希望谓词有效
[a,b,c,a,b,c]
%if first letter is a, put the letter after it in array L, if not - remove first letter.
%first letter is a, put b in array L, remove a from initial array.

[b,c,a,b,c]
%if first letter is a, put the letter after it in array L, if not - remove first letter.
% first letter is b, it is not a, so remove it from initial array

[c,a,b,c]
%if first letter is a, put the letter after it in array L, if not - remove first letter.
% first letter is c, it is not a, so remove it from initial array

[a,b,c]
%if first letter is a, put the letter after it in array L, if not - remove first letter.
% first letter is a, put b in array L, remove a from initial array.

[b,c]
%if first letter is a, put the letter after it in array L, if not - remove first letter.
% first letter is b, it is not a, so remove it from initial array

[c]
%if first letter is a, put the letter after it in array L, if not - remove first letter.
% first letter is c, it is not a, so remove it from initial array

这就是我所拥有的:

next(X, List1, List2):-
    next(X,[X,X2|List1],X2).

我知道方括号中的部分是错误的。

更新#1:

/* X is the head of the list */
next(X, [X,Y|T1], [Y|T2]) :-
    next(X, [Y|T1], T2).

/* X is not the head of the list*/
next(X, [_|T1], [T2]) :-
    next(X, T1, T2).

/* T1 contains only one element */
    next(X, _, [T2]):-
        true.

/* T1 is empty */
    next(X,[T2]):-
        true.

更新#1的跟踪日志:

1? - 追踪。 真。

[trace] 1 ?- next(a,[a,c,d,e,f,a,g],S).
   Call: (6) next(a, [a, c, d, e, f, a, g], _G4792) ? creep
   Call: (7) next(a, [c, d, e, f, a, g], _G4880) ? creep
   Call: (8) next(a, [d, e, f, a, g], _G4885) ? creep
   Call: (9) next(a, [e, f, a, g], _G4888) ? creep
   Call: (10) next(a, [f, a, g], _G4891) ? creep
   Call: (11) next(a, [a, g], _G4894) ? creep
   Call: (12) next(a, [g], _G4898) ? creep
   Call: (13) next(a, [], _G4903) ? creep
   Exit: (13) next(a, [], [_G4906]) ? creep
   Exit: (12) next(a, [g], [[_G4906]]) ? creep
   Exit: (11) next(a, [a, g], [g, [_G4906]]) ? creep
   Exit: (10) next(a, [f, a, g], [[g, [_G4906]]]) ? creep
   Exit: (9) next(a, [e, f, a, g], [[[g, [_G4906]]]]) ? creep
   Exit: (8) next(a, [d, e, f, a, g], [[[[g, [_G4906]]]]]) ? creep
   Exit: (7) next(a, [c, d, e, f, a, g], [[[[[g, [_G4906]]]]]]) ? creep
   Exit: (6) next(a, [a, c, d, e, f, a, g], [c, [[[[g, [_G4906]]]]]]) ? creep
S = [c, [[[[g, [_G4906]]]]]] 

我已经从这些资源中查看了基本级别的prolog练习列表: http://www.ic.unicamp.br/~meidanis/courses/problemas-prolog/ http://www.anselm.edu/homepage/mmalita/culpro/index.html

1 个答案:

答案 0 :(得分:0)

我认为您已经定义了解决问题所需的规则,但定义这些规则的谓词子句并不完全正确。让我们来看看你定义的规则:

/* X is the head of the list */
next(X, [X,Y|T1], [Y|T2]) :-
    next(X, [Y|T1], T2).

这是我在评论中给出的一个,其中列表的头部与元素匹配,并且它是正确的。

/* X is not the head of the list*/
next(X, [_|T1], [T2]) :-
    next(X, T1, T2).

此条款有问题。它说, X不是列表的头部,但查询next(a, [a,b,c], T)将匹配它,因为X = _是可能的。此外,这里有所有额外括号,T2已经是一个列表,所以你不想把它放在像[T2]这样的括号中。更正的条款是:

next(X, [Y|T1], T2) :-
    dif(X, Y),      % Or X \== Y if you don't have dif/2
    next(X, T1, T2).

第三条规则和条款:

/* T1 contains only one element */
    next(X, _, [T2]):-
        true.

这有一个问题,因为_匹配任何,而不仅仅是单个元素列表。规则说, T1只包含一个元素。但T1甚至没有出现在该条款中。更正后的版本为:

/* A list with one element has no elements "next" */
next(_, [_], []).

所以在上面,第一个参数不再重要,第二个参数是一个元素的任何列表,无论它是什么。结果必须为空。

你的最后一条规则&子句:

/* T1 is empty */
    next(X,[T2]):-
        true.

一个明显的问题是你现在只有2个参数。你的谓词必须有3.如果T1为空,我希望中间参数为[]

/* An empty list has no "next" values */
next(_, [], []).

您还可以将最后两个子句合并为:

next(_, T, []) :- T = [] ; T = [_].