在列表列表中查找形状 [英] Looking up shapes in a lists of lists

查看:322
本文介绍了在列表列表中查找形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

程序说明

  1. 该计划的目的

我的程序用于在20X15尺寸的平面中计算形状的位置.我有一个包含形状类型,其ID,其半径或高度以及其在平面上的预期[X,Y]位置的形状的列表.我有一个不同的二进制操作列表,其中仅包含形状类型,其id以及它与另一个形状的位置关系.在操作列表中获得此信息后,我应该计算形状的[X,Y]位置:以下是两个列表的说明:

My program is meant to calculate locations of shapes in a 20X15 sized plane. I have a list of shapes carrying the shape type, its id, its radius or height, and its prospective [X,Y] location on the plane. I have a different list of binary operations carrying only the shape type, its id, and its location relationship with another shape. With this information in the operations list, I should compute the [X,Y] locations of the shapes: Below is a description of the two lists:

形状列表

我有一个形状列表:每个形状都是以下形式的列表:

I have a list of shapes: each shape is a list of the form:

[[shape, id],height/radius, [X,Y]]

由Prolog打印出来的形状列表如下所示:

A list of such shapes would look something like the below when it is printed out by Prolog:

[[[diamond,1],4,[_7948,_7954]],[[circle,3],6,[_7894,_7900]],[[square,1],4,[_7840,_7846]],[[circle,1],5,[_7786,_7792]]|_7800]

操作列表

应该对每个操作采用以下形式的形状进行操作的列表:

A list of operations that should be carried out on the shapes each operation is of the form:

[[[circle,1],below,[square,1]]]

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

由序言打印出的此类列表如下所示:

Such a list when printed out by prolog would look something like the following:

[[[circle,1],below,[square,1]]|_8016]

  1. 程序

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

So I have computeShapeLocations/2. Its first argument is a list of operations and the second list is a list of shapes. It recursively goes over the list of operations getting the shape ids on both sides of the operation. eg circle 1 - below - sqaure 1 and sends the two shapes to the correct function to calculate the locations using CLPFD. For two shapes with a relative positioning of 'below' I use computeShapesBelow/2 which takes two shapes each of the form [[shape, id],height/radius, [X,Y]].

ComputeShapeLocations/2中的步骤: 1.从操作列表中获取形式为[[[circle,1],在下面,[square,1]]]的操作 2.先获取第一个ID(圆圈1),然后获取关系类型(如下),然后获取第二个ID(正方形1). 3.从形状列表中获取形状(ShapesOut) 4.将形状发送到computeShapesBelow/2.这只是使用clpfd比较半径或高度以及X,Y平面的尺寸.

Steps in ComputeShapeLocations/2: 1. Get an operation of the form [[[circle,1],below,[square,1]]] from the list of operations 2. Fetch first id (circle 1), then type of relationship (below) then second id (square 1). 3. Fetch the shapes from the shapes list (ShapesOut) 4. Send the shapes to computeShapesBelow/2. This just uses clpfd to compare radius or height and the dimensions of my X,Y plane.

:- 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]的listofshapes中提取形状.然后,我打印出结果(writeln(Shape1), writeln(Shape2)),下图显示了行为是如何错误的.对于第一个形状(圆形,1),结果很好,并且computeShapesBelow/2甚至为其X,Y位置设置了适当的限制(6..14和6..9).对于第二个形状(Shape2或正方形1).它的行为不符合预期,并且clpfd限制导致较低的无穷大.

The problem: In computeShapeLocations/2 my lookup is just bizarre( see step three above in steps of computeShapeLocations/2). I use member(ShapeId, ListOFshapesList) to fetch shapes from listofshapes given their ids [shape,id]. I then print out the results( writeln(Shape1), writeln(Shape2))and the image below shows just how the behavior is wrong. For the first shape (circle,1), the result is good and computeShapesBelow/2 even comes up with a proper limit of its X,Y location (6..14 and 6..9). For the second shape (Shape2 or square 1). It does not behave as expected and the clpfd limits result in lower infinities.

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

The reason is because this second search of [square,1] ignores an entry of [[square, 1], 4, [_2166, _2172]] which is in the list and instead somehow adds an extra [[square, 1], _2250, [_2262|...]] which it then uses to mess up my results.

推荐答案

在我看来,两个简单的问题掩盖了问题的根源.我没有您所有的代码,并且我真的不知道您要做什么,所以我只说说我所看到的以及我将如何进行.

In my opinion, the source of your problem is being obscured by two simple problems. I don't have all your code and I don't really know what you're trying to do, so I'll just talk about what I see and how I would proceed.

第一个问题是您没有有效利用统一.例如,您可以替换为:

The first problem is that you are not making effective use of unification. For instance, you can replace this:

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

与此:

[Subject1,below,Subject2] = Operation,

但是,此外,您实际上并不需要单独的Operation,因此可以将其移到子句的开头:

But, moreover, you don't really need Operation on its own, so you can move that into the head of your clause:

computeShapeLocations([[Subject1,below,Subject2]|Rest],ShapesOut) :-

当您开始进行这些更改时,您的代码将收缩很多,并且它会变得更容易看到正在发生的事情.使用更少的表述会更容易理解.例如,对于我来说,了解此命令列表中发生的事情要容易一些:

As you start to make these changes your code will contract quite a bit and it should become a lot easier to see what is going on. What would make it even easier to understand would be using less listy representations. For instance, it's a little easier for me to understand what is going on in this command list:

[below(circle(1), square(1)), below(circle(2), square(1)), ...]

或什至可以通过添加:- op声明来做到这一点:

or even this, which you can do by adding an :- op declaration:

[circle(1) below square(1), circle(2) below square(1), ...]

,然后您的模式匹配看起来会更简单,例如:

and then your pattern matches will look even simpler, like:

compute(Shape1 below Shape2) :- ...

类似地,对于您的形状,如果您具有更多的结构,将会更容易理解正在发生的事情:

Similarly, for your shapes, it would be a little easier to understand what is going on if you have a little more structure:

shape(circle(1), 4, X@Y)

对我来说比

[[circle,1], 4, [X,Y]]

我发现输入列表中有未绑定变量,这有点奇怪.我收集您是希望他们以后能获得价值.我想这种方法没有错,我只是惊讶地看到混合使用地面和非地面作为输入.

I find it a little odd that you've got unbound variables inside your input list. I gather you're hoping they'll obtain values later on. I suppose there's nothing wrong with this approach, I'm just surprised to see a mixture of ground and nonground acting as inputs.

您的第二个麻烦源是您将几种过程混合在一起.我很确定您在某处正在进行DCG解析步骤.通过解析其中的弱列表表示,您将迫使自己在这些方法中做更多工作,从而破坏列表并获得其含义.考虑:

Your second source of trouble is that you're mixing several kinds of procedure together. I'm pretty sure you have a DCG parsing step going on somewhere. By parsing into this weak, listy representation in there, you're forcing yourself to do more work inside these methods destructuring your lists and obtaining their meaning. Consider:

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一样的事情会使您的处理更加复杂.

IOW, you could create structure during the parse that will simplify your life during the processing. Similarly, doing a lot of what looks to me like debug I/O is making your processing more complex.

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.

我想,如果我盯着这个看,我会发现调试起来会容易一些.

I think if I were staring at this I would find it a bit easier to debug.

这篇关于在列表列表中查找形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆