我在prolog中的代码出现在相反的预期顺序中。这是代码:
room(homermargeroom, donuts).
room(homermargeroom, tv).
room(ensuite, nothing).
room(lisaroom, beer).
room(bartroom, donuts).
room(hallway, nothing).
room(bathroom, nothing).
room(maggieroom, nothing).
/* These are the locations where Bart, Lisa and Maggie are hiding */
hiding(bart, cupboard).
hiding(lisa, ensuite).
hiding(maggie, bathroom).
canHomerGet(Start, End, Item) :-
homermove(Start, End),
canTravelThrough(Start, Item),
canTravelThrough(End, Item),
write('Homer moves from '), write(Start), write(' to '), write(End), nl.
canHomerGet(Start, End, Item) :-
homermove(Start, Somewhere),
canTravelThrough(Somewhere, Item),
canHomerGet(Somewhere, End, Item),
write('Homer moves from '), write(Start), write(' to '), write(Somewhere), nl.
canTravelThrough(Somewhere, _Item) :-
room(Somewhere, nothing).
canTravelThrough(Somewhere, Item) :-
room(Somewhere, tv),
Item == portableTV.
canTravelThrough(Somewhere, Item) :-
room(Somewhere, donuts),
Item == nachos.
canTravelThrough(Somewhere, Item) :-
room(Somewhere, sistersinlaw),
Item == blindfold.
canTravelThrough(Somewhere, Item) :-
room(Somewhere, beer),
Item == margarita.
canHomerFind(Child, Item) :-
hiding(Child, Destination),
canHomerGet(garage, Destination, Item).
这是输出:
荷马从门厅移动到橱柜
荷马从餐厅搬到门厅 荷马从厨房搬到餐厅 荷马从侧厅转移到厨房 荷马从车库移到侧厅
我写这篇文章的方式,我希望这可以打印出'荷马从车库移到侧面'的拳头,然后以相反的顺序打印该列表。有关如何解决此问题的任何建议吗?
答案 0 :(得分:2)
您对谓词canHomerGet/3
的定义仅在最后写入移动输出。在第二个子句中,递归调用先于写入移动。这使得这个谓词非尾递归。即移动的写入在隐式递归堆栈上保存,然后在对谓词的调用成功时从堆栈中弹出。因此,打印的第一个移动是最后一个,最后打印的移动是第一个移动。
您可能想通过将第二个子句修改为:
来解决此问题canHomerGet(Start, End, Item) :-
homermove(Start, Somewhere),
canTravelThrough(Somewhere, Item),
write('Homer moves from '), write(Start), write(' to '), write(Somewhere), nl,
canHomerGet(Somewhere, End, Item).
这将使谓词尾递归,从而在恒定的堆栈空间中运行,但会出现一个新的问题:无处不在的运动也会被打印为回溯以找到成功的路线不会撤消运动的打印。通常的解决方案是构建一个步骤列表(使用附加参数),然后在结尾处打印列表(在反转之后)。我会把它留给你作为锻炼。