gpt4 book ai didi

list - 在列表列表中查找形状

转载 作者:行者123 更新时间:2023-12-04 12:39:10 25 4
gpt4 key购买 nike

节目说明

  • 项目目标

  • 我的程序旨在计算 20X15 大小的平面中形状的位置。我有一个形状列表,其中包含形状类型、它的 id、它的半径或高度,以及它在平面上的预期 [X,Y] 位置。我有一个不同的二进制操作列表,只携带形状类型、它的 id 以及它与另一个形状的位置关系。有了操作列表中的这些信息,我应该计算形状的 [X,Y] 位置: 下面是两个列表的描述:

    形状列表

    我有一个形状列表:每个形状都是表单列表:
    [[shape, id],height/radius, [X,Y]]
    当 Prolog 打印出这些形状的列表时,它看起来如下所示:
    [[[diamond,1],4,[_7948,_7954]],[[circle,3],6,[_7894,_7900]],[[square,1],4,[_7840,_7846]],[[circle,1],5,[_7786,_7792]]|_7800]

    操作列表

    应在形状上执行的操作列表,每个操作的形式如下:
    [[[circle,1],below,[square,1]]]

    这意味着圆 1 应该出现在 X,Y 平面上的正方形 1 下方

    当 prolog 打印出这样的列表时,它看起来像下面这样:
    [[[circle,1],below,[square,1]]|_8016]
  • 程序

  • 所以我有 computeShapeLocations/2 .它的第一个参数是操作列表,第二个参数是形状列表。它递归地遍历操作列表,获取操作两侧的形状 ID。例如 circle 1 - below - sqaure 1并将这两个形状发送到正确的函数以使用 CLPFD 计算位置。对于相对定位为“下方”的两个形状,我使用 computeShapesBelow/2它采用两种形状,每种形状为 [[shape, id],height/radius, [X,Y]] .

    ComputeShapeLocations/2 中的步骤:
    1. 从操作列表中获取 [[[circle,1],below,[square,1]]] 形式的操作
    2. 获取第一个 id(圆圈 1),然后是关系类型(下方),然后是第二个 id(正方形 1)。
    3. 从形状列表中获取形状 (ShapesOut)
    4. 将形状发送至 computeShapesBelow/2 .这只是使用 clpfd 来比较半径或高度以及我的 X、Y 平面的尺寸。
    :- use_module(library(clpfd)).
    computeShapeLocations([],_ShapesOut).
    computeShapeLocations([Operation|Rest],ShapesOut) :- writeln(ShapesOut),
    writeln([Operation|Rest]),
    nth0(0,Operation,Subject1),
    nth0(1,Operation,below),
    nth0(2,Operation,Subject2),
    Shape1 = [Subject1,H,Loc],
    Shape2 = [Subject2,H2,Loc2],
    member(Shape1,ShapesOut),
    member(Shape2,ShapesOut),
    writeln(Shape1),
    writeln(Shape2),
    writeln(Subject1),
    writeln(Subject2),
    computeShapeBelow(Shape1,Shape2),
    computeShapeLocations(Rest,ShapesOut).
    computeShapeBelow(Shape1,Shape2) :- nth0(2,Shape1,Location1),
    nth0(2,Shape2,Location2),
    writeln(Shape1),
    writeln(Shape2),
    nth0(1,Shape1,Dim1),
    nth0(1,Shape2,Dim2),
    nth0(0,Location1,Xcord1),
    nth0(0,Location2,Xcord2),
    nth0(1,Location1,Ycord1),
    nth0(1,Location2,Ycord2),
    Ycord1 #> Dim1, Ycord1 #< 15-Dim1,
    Xcord1 #> Dim1, Xcord1 #< 20-Dim1,
    Ycord2 #> Dim2, Ycord2 #< 15-Dim2,
    Xcord2 #> Dim2, Xcord2 #< 20-Dim2,
    Ycord2 #> Ycord1+Dim2+Dim1.

    问题:
    computeShapeLocations/2我的查找很奇怪(参见上述步骤 computeShapeLocations/2 中的第三步)。我使用 member(ShapeId, ListOFshapesList) 从给定 id [shape,id] 的形状列表中获取形状。然后我打印出结果( writeln(Shape1), writeln(Shape2)),下图显示了行为是如何错误的。对于第一个形状 (circle,1),结果很好, computeShapesBelow/2甚至提出了其 X、Y 位置的适当限制(6..14 和 6..9)。对于第二个形状(Shape2 或正方形 1)。它的行为不像预期的那样,并且 clpfd 限制会导致更低的无穷大。

    原因是因为 [square,1] 的第二次搜索忽略了 [[square, 1], 4, [_2166, _2172]] 的条目。它在列表中,而是以某种方式添加了一个额外的 [[square, 1], _2250, [_2262|...]]然后它用来弄乱我的结果。
    enter image description here

    最佳答案

    在我看来,您的问题的根源被两个简单的问题所掩盖。我没有你所有的代码,我真的不知道你想要做什么,所以我只会谈谈我看到的内容以及我将如何进行。

    第一个问题是你没有有效地利用统一。例如,您可以替换它:

    nth0(0,Operation,Subject1),
    nth0(1,Operation,below),
    nth0(2,Operation,Subject2),

    有了这个:
    [Subject1,below,Subject2] = Operation,

    但是,此外,您实际上并不需要 Operation就其本身而言,因此您可以将其移至子句的头部:
    computeShapeLocations([[Subject1,below,Subject2]|Rest],ShapesOut) :-

    当您开始进行这些更改时,您的代码会收缩很多,并且应该更容易看到发生了什么。更容易理解的是使用更少的列表表示。例如,我更容易理解这个命令列表中发生了什么:
    [below(circle(1), square(1)), below(circle(2), square(1)), ...]

    甚至这个,你可以通过添加 :- op宣言:
    [circle(1) below square(1), circle(2) below square(1), ...]

    然后你的模式匹配会看起来更简单,比如:
    compute(Shape1 below Shape2) :- ...

    同样,对于您的形状,如果您有更多的结构,就会更容易理解发生了什么:
    shape(circle(1), 4, X@Y)

    对我来说比
    [[circle,1], 4, [X,Y]]

    我觉得输入列表中有未绑定(bind)的变量有点奇怪。我猜你希望他们稍后会获得值(value)。我想这种方法没有任何问题,我只是惊讶地看到地面和非地面的混合作为输入。

    您的第二个麻烦来源是您将几种程序混合在一起。我很确定您在某处进行了 DCG 解析步骤。通过解析其中的这种弱的、列表的表示,你强制自己在这些方法中做更多的工作来解构你的列表并获得它们的含义。考虑:
    command([Shape1,below,Shape2]) --> shape(Shape1), "below", shape(Shape2).

    相对
    command(Shape1 below Shape2) --> shape(Shape1), "below", shape(2).

    或者,
    shape_type(circle) --> "circle".  shape_type(square) --> "square".
    shape_name(shape(Name, Size, X@Y)) -->
    shape_type(T), integer(ID),
    integer(Size),
    integer(X), integer(Y),
    { Name =.. [T, ID] }.

    与你现在拥有的任何东西相比。

    IOW,您可以在解析过程中创建结构,这将简化您在处理过程中的生活。同样,做很多在我看来像调试 I/O 的事情会使您的处理更加复杂。
    find_shape(ShapeId, Shapes, Shape) :-
    Shape = shape(ShapeId, _, _),
    member(Shape, Shapes).

    computeShapeLocations([], _).
    computeShapeLocations([ShapeId1 below ShapeId2|Rest], Shapes) :-
    find_shape(ShapeId1, Shapes, Shape1),
    find_shape(ShapeId2, Shapes, Shape2),
    computeShapeBelow(Shape1, Shape2),
    computeShapeLocations(Rest, Shapes).

    computeShapeBelow(shape(_, D1, X1@Y1), shape(_, D2, X2@Y2)) :-
    Y1 #> D1, Y1 #< 15 - D1,
    X1 #> D1, X1 #< 20 - D1,
    Y2 #> D2, Y2 #< 15 - D2,
    X2 #> D2, X2 #< 20 - D2,
    Y2 #> Y1 + D2 + D1.

    我想如果我盯着这个我会发现它更容易调试。

    关于list - 在列表列表中查找形状,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51846556/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com