2015-05-25 60 views
1

我在prolog中的代码出现在相反的预期顺序。下面是代码:为什么我的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). 

这里是输出:从门厅

荷马移动到橱柜
荷马从餐室移动到门厅
荷马从厨房移动到餐室
荷马从移动sidehall到厨房
荷马从车库移到侧厅

我写这个的方式,我希望能打印出'Homer从车库移动到sidehall'的拳头,然后按照与它相反的顺序打印该列表。对于如何解决这个问题,有任何的建议吗?

+1

你确定你提供了所有的源代码吗?这个输出是由哪个查询产生的? –

回答

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). 

这将使谓语尾递归,从而在不断的堆栈空间运行,但上升一个新的问题:运动引起任何地方也不会打印回溯,以找到成功的路线不会撤消运动的打印。通常的解决方案是构建一个步骤列表(使用额外的参数),然后在最后打印列表(反转后)。我将把这些留给你作为练习。

+0

感谢您的帮助!你能否更多地了解“额外论点”?我不确定你在暗示我应该做什么。 – user3414510

+1

搜索SO for“prolog path”。 SO中已经存在很多类似的问题。 –