存储错误 - 第一深度搜索算法

时间:2013-03-25 15:14:32

标签: algorithm storage ada

我正在研究一种能解决3D谜题的算法。 但是我遇到了一个问题,我使用的算法是First Search Depth,它似​​乎运行良好,直到我得到“提升STORAGE_ERROR:EXCEPTION_STACK_OVERFLOW”。我不太确定为什么它不起作用。任何猜测为什么这不起作用?

我想要这个算法做什么: 它需要一个List,一个数字和一个目标。对于此示例,列表长7个部分。它试图进入第一个坐标的部分。如果它不适合,它会旋转直到它适合,然后它自己调用它(6个部分)。如果零件全部以24种方式旋转(所有可能的方式来旋转3D零件),那么它将移动到另一个坐标并再次尝试适合。当所有部件都没有或没有任何作用时,它应该退出,我有另一个算法,在同一个列表中发送另一个订单到这个算法。

我还希望算法查看最后一个坐标是否与目标不匹配,然后它应该回溯并尝试找到另一个解决方案。

以下是一些代码:

procedure Pseudo(Parts : in out List_Type; Figure : in out Figure_Type; Goal : in out Figure_Type; LastCoord : in out Integer) is
        Unchanged : Part_Type := Parts.Data;
        Next : boolean := False;
        UnchangedFigure : Figure_Type;
    begin
    UnchangedFigure := Figure;
        if Empty(Parts) then
            raise Finished;
        else
            for I in 1..24 loop 
                RotNumber(Parts.Data,I); -- rotera
                if Check(Parts.Data,Figure) then -- test om den platsar
                    Maincheck(Parts.Data,Figure,Goal,Next);
                    if Next then
                        Unchanged := Parts.Data;
                        Append_Part(Parts.Data,Figure);
                        Remove_First(Parts);
                        Next := False;
                        Pseudo(Parts,Figure,Goal,LastCoord);
                        Next := False;
                        Figure := UnchangedFigure;
                        Insert_First(Unchanged,Parts);
                        Figure.CoordX := 0;
                        Figure.CoordY := 0;
                        Figure.CoordZ := 0;
                    end if;
                end if;
                Parts.Data := Unchanged;
            end loop;
        end if;
        -- if LastCoord /= 7 then --(Original 
            -- if To_String(Figure.Data)(LastCoord) /= To_String(Goal.Data)(LastCoord) then
                -- Put("over");
                -- return;
            -- end if;
        -- end if;
        LastCoord := Figure.CoordZ*Figure.X*Figure.Y + (Figure.Y-Figure.CoordY-1)*(Figure.X) + Figure.CoordX +1;
        if Figure.CoordY < Figure.Y-1 then
            Figure.CoordY := Figure.CoordY +1;
            Pseudo(Parts,Figure,Goal,LastCoord);
        elsif Figure.CoordY = Figure.Y-1 then
            if Figure.CoordX < Figure.X-1 then
                Figure.CoordX := Figure.CoordX +1;
                Figure.CoordY := 0;
                Pseudo(Parts,Figure,Goal,LastCoord);
            elsif Figure.CoordX = Figure.X-1 then
                if Figure.CoordZ < Figure.Z-1 then
                    Figure.CoordZ := Figure.CoordZ +1;
                    Figure.CoordX := 0;
                    Figure.CoordY := 0;
                    Pseudo(Parts,Figure,Goal,LastCoord);
                elsif Figure.CoordZ = Figure.Z-1 then
                    return;
                end if;
            end if;
        end if;
    end Pseudo;

1 个答案:

答案 0 :(得分:1)

首先,不要使用异常来控制程序流,这是不好的做法。请考虑使用其他out参数,而不是raise Finished

我认为将所有参数声明为in out也是错误的。查看Parts:在循环中,将图形附加到其Data成员,然后删除列表的第一个元素。之后,您调用Pseudo,它将再次列出该列表,如果不成功,Parts将可能具有与调用之前完全不同的内容。你恢复之后的第一个元素,但是Append_Part确实保持永久。我无法确定这是否真的是一个问题。在调用Pseudo之后恢复列表和数字的努力也是一个明显的迹象,表明您不希望这些参数为in out

另一件看起来很可疑的事情是,在循环之后,你改变了图形的坐标,然后再次调用Pseudo - 这会将第一次迭代结束时的坐标重置为0(如果条件匹配) 。可能的控制流程是:

  • Pseudo开始,Parts不为空。循环开始。我们假设图的Coord值最初为0。
  • 循环的迭代不会导致Finished。循环结束。
  • 算法会更改某些坐标并调用Pseudo。我们现在假设Parts仍然具有与第一次调用Pseudo时相同的值。正如我所写的那样,情况似乎并非如此,但如果我理解你的描述应该是正确的。
  • 第二次调用Pseudo它与第一次调用相同,只是图中某些坐标不同(可能Last_Coord,这似乎并不重要)。
  • Parts不能为空,循环开始。
  • 现在让我们假设在循环中的某个时刻,条件匹配,但对Pseudo的调用失败(如“不提升已完成”)。坐标将重置为0。
  • 从那时起,执行与第一次Pseudo调用的执行相同,因为它运行的数据现在是相同的。因此,循环中不会引发Finished,之后,Pseudo将第三次被调用,其参数与之前完全相同。

如您所见,这将导致无休止的递归。我无法确定是否会发生这种情况,因为我对您的类型或您调用的子程序一无所知。

在目前的情况下,您的代码很难理解,因为它具有非常复杂的控制流。如果你带走了一些代码的复杂性,那么追踪错误会更容易。我建议使用循环迭代坐标而不是递归。这可以解决您的问题。