对于我的“陈述语言”课程,我们必须编写一个解决七巧板拼图的序言程序。
通过拼图点的坐标列表来识别拼图。例如,puzzle(7,[(0,0),(8,0),(4,4)])
是一个标识符为7的拼图,代表一个三角形。
这是我(天真)解决这个问题的方法。执行从调用tangram(Puzzle, Puts)
开始。该程序从所有可能的拼图开始。然后,我选择一块,尝试一个位置和一个旋转,如果这给了拼图的有效位置,我放置拼图。 (=将块放在Puts列表中,该列表将在程序结束时返回。)我回顾了所有这些可能性。这是代码:
%Harm De Weirdt
%3e Bachelor Informatica
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% MAIN PROGRAM %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%All possible rotations of a piece.
angle(0).
angle(90).
angle(180).
angle(270).
%Puzzle is a list of the coordinates of the corners of the puzzle to be solved.
%Puts is a list of 7 elements indicating how each piece should be placed in order to solve the puzzle.
tangram(Puzzle, Puts):-
findall(block(BlockId, PointList), block(BlockId, PointList), PossiblePieces),
placePieces(PossiblePieces, Puts, Puzzle).
%placePieces(Pieces, Puts)
%Place all the puzzle pieces from Pieces on the puzzle.
%Puts is a list containing the position of all the pieces.
placePieces([], _,_).
placePieces([block(BlockId, PointList)|OtherPieces], Puts, Puzzle):-
between(0,8,X),
between(0,6,Y),
angle(Angle),
allowedPosition(PointList, (X,Y), Angle, Puzzle, Puts),
append(Puts, [put(BlockId, ((X,Y), Angle))], NewPuts),
placePieces(OtherPieces, NewPuts, Puzzle),
write(Puts).
allowedPosition(Block, (X,Y), Angle, Puzzle, Puts):-
rotatePolygon(Block, Angle, RotatedPolygon),
translatePolygon(RotatedPolygon, (X,Y), TranslatedPolygon),
insideFigure(TranslatedPolygon, Puzzle),
noOverlap(TranslatedPolygon, Puts).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% EXTRA PREDICATES %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%translate(Point, TranslationVector, TranslatedPoint)
%TranslatedPoint is the result of Translating Point with TranslationVector
translate((X, Y), (TX, TY), (RX, RY)):-
RX is X + TX,
RY is Y + TY.
%translatePolygon(Polygon, TranslationVector, TranslatedPolygon)
%Translates a Polygon, defined by a list of its Points, by a given TranslationVector,
%resulting in the TranslatedPolygon
translatePolygon([], _Vector, []).
translatePolygon([(X,Y)|Rest], (TX, TY), TranslatedPolygon):-
translatePolygon(Rest, (TX, TY), PartiallyTranslatedPolygon),
translate((X, Y), (TX, TY), (NewX, NewY)),
TranslatedPolygon = [(NewX, NewY)| PartiallyTranslatedPolygon].
一些可能的难题:
[(0,0),(4,0),(4,4),(0,4)]
[(3,0),(5,2),(5,4),(4,5),(2,5),(0,3)]
[(0,0),(6,0),(7,1),(7,3),(3,3)]
运行此问题时出现以下错误:
ERROR: is/2: Arguments are not sufficiently instantiated
当跟踪时,似乎不知道Translate中的TX和TY值是否未实例化。追溯我认为不知何故X和Y不会在placePieces谓词中实例化。如果没有剩下的值,那么谓词就会失败,对吧?
我一直在查看我的代码超过5个小时,似乎无法找到我的错误。 希望你们中的一个人有时间来看看这个并让我朝着正确的方向前进。
提前致谢!
答案 0 :(得分:3)
如果您只是使用CLP(FD)约束进行算术,则此错误将消失。只需使用约束(is)/2
替换(#=)/2
:
:- use_module(library(clpfd)).
translate((X, Y), (TX, TY), (RX, RY)):-
RX #= X + TX,
RY #= Y + TY.
重要的是,(#=)/2
可以在所有方向上使用 ,如果变量仍然出现在其参数中,也可以使用。{/ p>
其他评论:
(-)/2
来表示对,即X-Y
等。maplist/3
将帮助您缩短代码。答案 1 :(得分:1)
尝试使用错误获取堆栈跟踪。发生错误时,一些Prolog系统显示堆栈跟踪:SWI Prolog,SICStus Prolog,Jekejeke Prolog。
你必须对Prolog系统进行一些实验。由于各种原因,堆栈可能不会显示。例如,尝试普通的咨询而不是编译。或者尝试打开调试模式而不是正常执行。
如果Prolog系统在发生错误时自动进入调试器,您可能也看不到堆栈跟踪。但通常调试器会为您提供显示堆栈跟踪的命令。典型的命令是:g for goals(backtrace)。
当您看到堆栈跟踪时,您可以更紧密地确定问题发生的位置。