【问题标题】:square all members in the list including sublist Prolog without using maplist在不使用 maplist 的情况下将列表中的所有成员(包括子列表 Prolog)平方
【发布时间】:2018-10-11 17:26:27
【问题描述】:

我是 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).

【问题讨论】:

  • @CapelliC:只需重新启动我的程序即可运行。
  • @Nicholas Carey:你的解释很有帮助

标签: list prolog


【解决方案1】:

您的 Prolog 应该在您的第一条和第三条规则中警告您“单例”。

试试

dsquare([],[]).
...
dsquare([H|T],[S|R]):- isList(H), dsquare(H,S), dsquare(T,R).

OT 不会在没有动机原因的情况下进行裁减。

edit 你会得到更多结果,因为最后一条规则在回溯时被触发。现在是时候在需要的地方放置剪辑了(即在代码进入由条件保护的分支之后):

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].

【讨论】:

  • 我明白你在说什么,并将其纳入我的代码中。我在问题中发布了我的新更新代码以及我得到的输出。
  • 好吧,“剪辑”是我现在更好理解的东西。但现在我得到了一个非常有趣的输出。 dsquare([a,[3],[[[5]]],[2],a],X)。 X = [a, " ", [[[25]]], [4], a] ;对于一些“深”的情况,我得到一个空白区域,如图所示。除此之外,一切看起来都不错。
  • 它仍然给了我一个专门用于 [3] 的空白空间,但除此之外一切都很好。谢谢您的帮助。我会看看我能为空白做些什么,也许尝试在另一个 prolog 编译器上运行它。
【解决方案2】:

_Vxxx 位是 prolog 对结果中未绑定变量的表示。基本上就是符号表中的键或地址。

  • 在您的第一条规则中,

    dsquare([],S).
    

    你永远不会将任何东西绑定到第二个参数。这意味着如果您以dsquare([],X) 调用它,X 将保持未绑定状态。如果以dsquare([1,2,3],X) 调用(假设其他一切正常,则生成的列表结构将被破坏,X 将类似于[1,2,3|_VD3DC],因为最后一项既不是原子[](空list) 或./2,这是一个非空列表的结构。

  • 在你的第二条规则中,

    dsquare([H|T],[R|S]):- number(H), dsquare(T,S), R is H*H, !.
    
    • 剪辑 (!) 是不必要的
    • 您的运算符顺序不正确。先平方 H,然后向下递归。这完成了两件事:它 (A) 提前失败(如果结果是绑定的),并且 (B) 允许应用尾递归优化。
  • 在你的第三条规则中,

    dsquare([H|T],S):- isList(H), dsquare(H,S).
    

    您正在向下递归作为源列表头部的子列表,但根本不评估源列表的尾部,而是简单地丢弃它。

  • 在你的第四条规则中,

    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!

你会注意到有很多统一魔法和类似的事情发生在序言谓词的子句的头部。

【讨论】:

  • 很好的解释。我跟着你的 cmets 并相应地修改了我的代码。我也使用了你给定的 sn-p 但它没有给我预期的输出。这是我使用您的代码时的输出。21?- deep_square([a,2,[[3]],r],X)。 X = [a, 4, [" "], r] ; X = [a, 4, [[3]], r] ; X = [a, 4, [[3]], r] ; X = [a, 4, [[3]], r] ; X = [a, 2, [" "], r] ; X = [a, 2, [[3]], r] ; X = [a, 2, [[3]], r] ; X = [a, 2, [[3]], r] ;失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-31
  • 2011-12-29
  • 1970-01-01
相关资源
最近更新 更多