Prolog中的迭代列表

时间:2017-01-09 09:00:21

标签: prolog

我想在Prolog中迭代一个列表,将生成的结果写入新列表。 使用谓词next_level_segments(List of Start-, Endcoordinates) 我想计算每对Start-和Endcoordinates之间的四个坐标列表,并将这四个列表存储在Ls中。 这意味着当我打电话时,例如

next_level_segments([
                       [(10,0),(3.3,0)],
                       [(3.3,0),(0,-5.8)],
                       [(0,-5.8),(-3.3,0)],
                       [(-3.3,0),(-10,0)]
                     ])

谓词segments()应计算其间的四个下一个坐标 这对开始和结束坐标例如[(10,0),(3.3,0)]。 所以next_level_segments应该迭代起点和终点列表,段应该进行计算和四个列表的结果,每四对坐标应该存储在一个结果列表中。

当我用四个坐标列表调用next_level_segments()时,计算完成并且当我查看迹线时生成坐标,但是没有正确存储。 据我在轨迹中看到的那样,缺少四个坐标的最后一个列表。 也许有人可能会看一看我的错误。

谢谢

segments([(Sx,Sy),(Ex,Ey)],Ls):-
    X2 is Sx+(Ex-Sx)/3,
    Y2 is Sy+(Ey-Sy)/3,
    R1 is sqrt((X2-Sx)*(X2-Sx)+(Y2-Ey)*(Y2-Ey)),
    Phi1 is atan((Y2-Sy)/(X2-Sx)),
    X3 is X2 +R1*cos((Phi1-240)*pi/180),
    Y3 is Y2 +R1*sin((Phi1+240)*pi/180),
    X4 is X2+(X2-Sx),
    Y4 is Y2+(Y2-Sy),
         Ls=[
             [(Sx,Sy),(X2,Y2)],
             [(X2,Y2),(X3,Y3)],
             [(X3,Y3),(X4,Y4)],
             [(X4,Y4),(Ex,Ey)]].    

next_level_segments([[(Sx,Sy),(Ex,Ey)]|E],[X|RLs]):-
    segments([(Sx,Sy),(Ex,Ey)],X),
    next_level_segments(E,RLs). 

next_level_segments([],[]).

1 个答案:

答案 0 :(得分:4)

您的next_level_segments/2只需要两个条款(而不是您正在使用的三个条款)。第一个应该是:

next_level_segments([], []).

你现在的第一和第三条都应该去,因为他们没有做任何有用的事情。

递归条款似乎很正常。

像这样纠正,我得到:

?- next_level_segments(
       [[(10,0),(3.3,0)],
        [(3.3,0),(0,-5.8)],
        [(0,-5.8),(-3.3,0)],
        [(-3.3,0),(-10,0)]
       ],
       X).
X = [[[(10, 0),  (7.766666666666667, 0)], [(7.766666666666667, 0),  (6.649999999999999, -1.9341234017852458)], [(6.649999999999999, -1.9341234017852458),  (5.533333333333333, 0)], [(5.533333333333333, 0),  (3.3, 0)]],
     [[(3.3, 0),  (2.2, -1.9333333333333333)], [(2.2, -1.9333333333333333),  (0.1262841490828066, -5.451200543142186)], [(0.1262841490828066, -5.451200543142186),  (1.1000000000000005, -3.8666666666666667)], [(1.1000000000000005, -3.8666666666666667),  (0, -5.8)]],
     [[(0, -5.8),  (-1.0999999999999999, -3.8666666666666663)], [(-1.0999999999999999, -3.8666666666666663),  (-3.0456930398351094, -7.310619872034865)], [(-3.0456930398351094, -7.310619872034865),  (-2.1999999999999997, -1.9333333333333327)], [(-2.1999999999999997, -1.9333333333333327),  (-3.3, 0)]],
     [[(-3.3, 0),  (-5.533333333333333, 0)], [(-5.533333333333333, 0),  (-6.65, -1.9341234017852458)], [(-6.65, -1.9341234017852458),  (-7.766666666666667, 0)], [(-7.766666666666667, 0),  (-10, 0)]]
    ].

请记住,像这样的琐碎的列表迭代也可以简单地写成:

maplist(segments, Input, Output)

换句话说,将segments/2应用于两个列表中的每个对应元素。你必须重新定义你的segments/3,但要有两个参数而不是三个,例如重写头部:

segments([(Sx,Sy),(Ex,Ey)], Ls)

(将两个第一个参数放在列表中,因为它们在输入列表中)

小评论:Prolog中的一对通常写为X-Y,而不是(X, Y)。许多标准库谓词代表"对"作为X-Y,例如keysort/2,库(对)等。如果您愿意,还可以为您的对提供一个描述性名称,例如pair(X,Y)coordinates(X,Y)。它并不仅仅是两个元素的关键,而是一个"元组"有三个这样的元素:(X,Y,Z)实际上是一个嵌套的术语:

?- write_canonical((X,Y,Z)).
','(_,','(_,_))
true.

X-Y-Z会遇到同样的问题:

?- write_canonical(X-Y-Z).
-(-(_,_),_)
true.

此时您可以再次使用带有描述性名称的字词,例如triple(X, Y, Z)coordinates(X, Y, Z)