List prolog-检查给定列表是否与模式匹配并替换某些元素

List prolog-检查给定列表是否与模式匹配并替换某些元素,list,prolog,List,Prolog,我遇到以下prolog代码的问题: valid(X, Y) :- append([E1 | T2], [E1 | T3], X1), append([E1|T1], X1, X), append([E2 | T2], [E2 | T3], Y1), append([E2|T1], Y1, Y), E2 is E1 + 1. 我想做的是:对于给定的列表X,检查它是否匹配模式[E1,…,E1,…,E1,…];如果是,则将所有E1替换为E1+1。 ..部分中可以有任意数量的元

我遇到以下prolog代码的问题:

valid(X, Y) :-
    append([E1 | T2], [E1 | T3], X1), append([E1|T1], X1, X),
    append([E2 | T2], [E2 | T3], Y1), append([E2|T1], Y1, Y),
    E2 is E1 + 1.
我想做的是:对于给定的列表X,检查它是否匹配模式
[E1,…,E1,…,E1,…]
;如果是,则将所有
E1
替换为
E1+1
..
部分中可以有任意数量的元素,即
T1
T2
T3
可以是任意长度

例如,我的预期输出是:

?- valid([1,5,1,6,7,1,8], Y).
Y = [2, 5, 2, 6, 7, 2, 8] ;
false.

?- valid([1,5,6,1,7,1], Y).
Y = [2, 5, 6, 2, 7, 2] ;
false.

?- valid([1,5,6,7,8], Y).
false.
但现在我得到的实际输出是:

?- valid([1,5,1,6,7,1,8], Y).
Y = [2, 5, 2, 6, 7, 2, 8] ;
ERROR: Out of global stack

?- valid([1,5,6,7,8], Y).
ERROR: Out of global stack
问题是,prolog将尝试尝试无限长的
T1
T2
T3
,因此从不停止。因此,当我的输入列表
X
与模式不匹配时,它会一直运行,直到内存空间不足

有没有办法修复我的代码,使其在找到所有可能的答案(可能不止一个)或X与模式不匹配时停止


谢谢

Append/3
谓词不是稳定的,因此它在开始时会计算其参数。因此,您需要在前面移动计算X的规则,如下所示:

valid(X, Y) :-
    append([E1|T1], X1, X),append([E1 | T2], [E1 | T3], X1),
    append([E2|T1], Y1, Y),append([E2 | T2], [E2 | T3], Y1),
    E2 is E1 + 1.
由于对X求值,第一次追加不会导致尝试无限长的长度,第二次追加也是如此

一些例子:

?- valid([1,5,1,6,7,1,8], Y).
Y = [2, 5, 2, 6, 7, 2, 8] ;
false.

?- valid([1,5,6,1,7,1], Y).
Y = [2, 5, 6, 2, 7, 2] ;
false.

?- valid([1,5,6,7,8], Y).
false. 
?- valid([1,5,1,6,7,1,8], Y).
Y = [2, 5, 2, 6, 7, 2, 8] ;
false.

?- valid([1,5,6,1,7,1], Y).
Y = [2, 5, 6, 2, 7, 2] ;
false.

?- valid([1,5,6,7,8], Y).
false.

?- valid(X, [2, 5, 2, 6, 7, 2, 8]).
X = [1, 5, 1, 6, 7, 1, 8] ;
false.
我更喜欢用一些简单的递归和E1的计数(并在输出列表中替换为E2)来解决这个问题,因为追加可能有点棘手

例如:

:- use_module(library(clpfd)).

valid([H|T], [H2|T2]):-  H2 #= H+1 ,valid(H,T,T2,1).

valid(_,[],[],3).
valid(H,[H|T1],[H2|T2],Count):- H2 #= H+1, Count1 #= Count+1,valid(H,T1,T2,Count1).  
valid(H,[H1|T1],[H1|T2],Count):- dif(H1,H), valid(H,T1,T2,Count).  
还有一些例子:

?- valid([1,5,1,6,7,1,8], Y).
Y = [2, 5, 2, 6, 7, 2, 8] ;
false.

?- valid([1,5,6,1,7,1], Y).
Y = [2, 5, 6, 2, 7, 2] ;
false.

?- valid([1,5,6,7,8], Y).
false. 
?- valid([1,5,1,6,7,1,8], Y).
Y = [2, 5, 2, 6, 7, 2, 8] ;
false.

?- valid([1,5,6,1,7,1], Y).
Y = [2, 5, 6, 2, 7, 2] ;
false.

?- valid([1,5,6,7,8], Y).
false.

?- valid(X, [2, 5, 2, 6, 7, 2, 8]).
X = [1, 5, 1, 6, 7, 1, 8] ;
false.
使用CLPFD库可以使谓词更具关系性,因此正如您在上面的最后一个示例中所看到的那样,您可以进行如下查询:
有效(X、[2,5,2,6,7,2,8])。
而之前不能(使用以前的解决方案)

以下是另一种替代方法:

new(H,H,R):- R is H+1.
new(H,N,N):- dif(N,H). 

valid([H|T], Y):- findall(X1, (member(X1,[H|T]),X1 = H) , L), 
                  length(L,3), maplist(new(H),[H|T],Y).

很乐意帮忙!!!,我已经尝试过用递归求解,并编辑了我的答案,希望能有所帮助!!。