我是Prolog的新手并尝试实现一种深度方形谓词,它将列表中的所有数字以及子列表中的所有数字都对齐。我写了一些工作代码,但它没有给我预期的输出。
代码:
dsquare([],S).
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
dsquare([H|T],S):- isList(H), dsquare(H,S).
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
当前输出:
2?- dsquare([[2],4,a],X).
X = [4| _VDHV] ;
X = [[2], 16, a| _VDNM] ;
fail.
预期产出:
X = [[4],16,a]
我也想知道为什么我的输出中会出现'_VDHV'和'_VDNM'。 任何帮助将不胜感激。
编辑: 好的,所以我将我的代码更新为:
dsquare([],[]).
dsquare([H|T],[R|S]):- number(H), R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]):- isList(H), dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).
但我得到的输出是:
13?- dsquare([a,3,[[2]],b,4],X).
X = [a, 9, [[4]], b, 16] ;
X = [a, 9, [[4]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 9, [[2]], b, 16] ;
X = [a, 9, [[2]], b, 4] ;
X = [a, 3, [[4]], b, 16] ;
X = [a, 3, [[4]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
X = [a, 3, [[2]], b, 16] ;
X = [a, 3, [[2]], b, 4] ;
fail.
我不知道它是如何得到这么多结果的。
修改的 最后,工作解决方案是
dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[H|S]) :- dsquare(T,S).
答案 0 :(得分:0)
你的Prolog应该在第一和第三条规则中警告你“单身人士”。
尝试
dsquare([],[]).
...
dsquare([H|T],[S|R]):- isList(H), dsquare(H,S), dsquare(T,R).
OT不会在没有动机原因的情况下进行裁员。
编辑你会得到更多结果,因为最后一条规则被引发回溯。现在可以将剪切放置在需要的地方(即在代码进入由条件保护的分支之后):
dsquare([],[]).
dsquare([H|T],[R|S]) :- number(H), !, R is H*H, dsquare(T,S).
dsquare([H|T],[R|S]) :- isList(H), !, dsquare(H,R), dsquare(T,S).
dsquare([H|T],[R|S]) :- R=H, dsquare(T,S).
或考虑重复代码的重构:
dsquare([],[]).
dsquare([H|T],[R|S]) :-
( number(H)
-> R is H*H
; isList(H)
-> dsquare(H,R)
; R=H
),
dsquare(T,S).
编辑上面的定义(我用'if / then / else'测试过)似乎很好:
1 ?- dsquare([[2],4,a],X).
X = [[4], 16, a].
2 ?- dsquare([a,[3],[[[5]]],[2],a],X).
X = [a, [9], [[[25]]], [4], a].
答案 1 :(得分:0)
_Vxxx
位是prolog对结果中未绑定变量的表示。基本上,它是符号表中的键或地址。
在您的第一条规则中,
dsquare([],S).
你永远不会将任何东西绑定到第二个参数。这意味着如果您将其作为dsquare([],X)
调用,则X将保持未绑定状态。如果调用为dsquare([1,2,3],X)
(假设其他所有内容都正常工作,则结果列表结构将被破坏,X
将类似[1,2,3|_VD3DC]
,因为最后一项不是atome []
(空列表)或./2
,结构为非空列表。
在你的第二条规则中,
dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
!
)在您的第3条规则中,
dsquare([H|T],S):- isList(H), dsquare(H,S).
您正在递归到作为源列表头部的子列表,但根本不评估源列表的尾部而是简单地丢弃它。
在你的第4条规则中,
dsquare([H|T],[R|S]) :- dsquare(T,S), R = H, !.
再次,就像在你的第二条规则中一样,切割是不必要的,操作顺序也相反。
我写的是这样的:
deep_square( [] , [] ) % squaring an empty list produces an empty list
.
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
number(X) , % if the head is a number,
Y is X*X , % square it
deep_square(Xs,Ys) % and recurse down
. %
deep_square( [X|Xs] , [Y|Ys] ) :- % otherwise...
nonvar(X) , % if the head is bound,
X = [_|_] , % and is a non-empty list.
deep_square( X , Y ) , % deep square the head
deep_square( Xs , Ys ) % and then recurse down
.
deep_square( [X|Xs] , [X|Ys] ) :- % otherwise the head is unbound or something other than a number or a non-empty list...
deep_square( Xs , Ys ) % recurse down.
. % Easy!
你会注意到,在一个序言谓词的句子的头部发生了一个很多的统一魔法等。