我必须编写一个谓词的深度版本,它向列表中的每个数字元素添加一个数字,而我已经完成了非深度版本:
addnum(N,T,Y)
这给出了类似于:
e.g. ?-addnum(7,[n,3,1,g,2],X).
X=[n,10,8,g,9]
但我现在想创建一个深度版本的addnum,它应该这样做:
e.g. ?-addnumdeep(7,[n,[[3]],q,4,c(5),66],C).
X=[n,[[10]],q,11,c(5),73]
有人能给我一些建议吗?我从这个开始:
islist([]).
islist([A|B]) :- islist(B).
addnumdeep(C,[],[]).
addnumdeep(C,[Y|Z],[G|M]):-islist(Z),addnum(C,Y,[G,M]),addnumdeep(C,Z,M).
但我认为我的逻辑不对。我想的是检查尾部是否是列表,然后在头部运行addnum,然后在尾部的其余部分运行addnumdeep,这是列表吗?
也许您可以在第一位"捕获"列表,添加第一个子句作为
addnum(N,[T|Ts],[Y|Ys]) :- addnum(N,T,Y),addnum(N,Ts,Ys).
这是一个解决方案。切割是必要的,否则它会回溯并在以后给出错误的解决方案。我曾尝试使用旧的addnum
谓词,但你不知道之后是否必须深入,所以只有当你有addnum_3levels_deep
谓词时才可行,即使这样,使用这个解决方案并计算深度也会更清楚。
addnumdeep(N,[X|Y],[G|H]):-
!, % cut if it is a nonempty list
(number(X)->
G is N + X;
addnumdeep(N,X,G)), % recurse into head
addnumdeep(N,Y,H). % recurse into tail
addnumdeep(_,A,A).
注意,这也允许addnumdeep(7,3,3)
。如果您希望它是addnumdeep(7.3.10)
,则必须提取括号中的条件:
addnumdeep(N,[X|Y],[G|H]):-
!, % cut if it is a nonempty list
addnumdeep(N,X,G),
addnumdeep(N,Y,H).
addnumdeep(N,X,Y):-
number(X),!, % cut if it is a number.
Y is N+X.
addnumdeep(_,A,A).
这个解决方案更好,因为它突出了您可能遇到的三种基本情况:它要么是列表,然后是追索权,要么是数字,对于其他一切,只需将其放入结果列表的尾部(这也处理空列表的情况)。另一方面,这个解决方案需要红色切口,所以它可能会受到一些纯粹主义者的反对。
如果你不想要红色削减,你可以用替换最后一条
addnumdeep(_,A,A):- !, + number(A), + A = [_|_].
如果不希望允许使用非列表,可以先用is_list
检查它是否是列表,然后调用建议的谓词。
我会从告诉我一个术语是否为列表的东西开始,大致如下:
is_list_like( X ) :- var(X) , ! , fail .
is_list_like( [] ) .
is_list_like( [_|_] ) .
然后,它只是在现有谓词中添加另一个case,类似于以下内容:
add_num( _ , [] , [] ) . % empty list? all done!
add_num( N , [X|Xs] , [Y|Ys] ) :- % otherwise...
number(X) , % - X is numeric?
Y is X + N , % - increment X and add to result list
add_num( N , Xs , Ys ) % - recurse down
. %
add_num( N , [X|Xs] , [Y|Ys] ) :- % otherwise...
is_list_like( X ) , % - X seems to be a list?
! ,
add_num( N , X , Y ) , % - recurse down on the sublist
add_num( N , Xs , Ys ) % - then recurse down on the remainder
. %
add_num( N , [X|XS] , [Y|Ys] ) :- % otherwise (X is unbound, non-numeric and non-listlike
X = Y , % - add to result list
add_num( N , Xs , Ys ) % - recurse down
. %